Understanding OAuth Scopes And Roles In Azure AD

There are plenty of identity providers on the market and what they all have in common is the use of scopes and roles. But what exactly is the difference between a scope and a role? And in which scenarios do you use them? In order to understand how they work, you must first learn the basics of OAuth 2.0 and OpenID Connect. After you have learned the basics, I will show you how scopes work in delegated access scenarios and how to use app roles to authorize both users and applications. In short, you will have a complete understanding of how scopes and app roles work and how to configure them in Azure AD.

The basics of OAuth 2.0 and OpenID Connect

The OAuth 2.0 protocol allows applications to obtain and use access tokens to access protected resources. It is commonly used as a way for internet users to grant applications access to their data without giving them the passwords. For example, if you want to share your contacts list with a web application so it can send emails on your behalf and click on a “Sign in with Microsoft” button, then you are using OAuth 2.0.

OAuth 2.0 is designed only for authorization and does not provide methods to obtain identity information. OpenID Connect implements authentication as an extension to the OAuth 2.0 authorization process. For this reason, you use OpenID Connect to sign in users. As a result, the authorization server returns an identity token to the client which can be used to verify the identity of the user.

Parties involved in an authentication flow

The parties shown in the image below are part of an authentication flow using OAuth 2.0 and OpenID Connect. Note that Azure AD is pictured as the authorization server just to make clear what role it plays. It is not a requirement for using OAuth 2.0. There are many other identity providers on the market that offer spec-compliant services.

Parties involved in an authentication flow using OAuth 2.0 and OpenID Connect
  • Authorization server – The authorization server securely handles end-user’s information, their access and the trust relationships between the parties. When a client sends a user sign-in request, the authorization server authenticates the end-user and responds with an identity token and usually an access token.

  • Client application – The client is the application requesting access to a protected resource. The client could be a web app, mobile app or a web api that calls another web api. It uses the authorization server to sign-in the user using a username and password. Or, if there is no user involved, the client can authenticate itself using a client id and client secret.

  • Resource owner – The resource owner is typically an end-user that owns the protected resource. The end-user can grant access to the client so it is able to access the protected resource on behalf of the end-user. For example, the client app might call an external system’s web api to get the user’s email address from their profile on that system. This profile data is a resource the end-user owns on the external system, and the end-user can consent to or deny your app’s request to access their data.

  • Resource server – The resource server provides access to protected resources. The resource server is most often a web api capable of accepting and responding to protected resource requests using access tokens. The information inside an access token is used to grant or deny access.

The role of security tokens

Security tokens are used to secure communication between parties and to ensure that only authorized parties have access to protected resources. There are three types of security tokens: identity token, access token and refresh token. The authorization servers issues these security tokens as JSON Web Tokens (JWT). A JWT consists of a header, payload and signature. The header and signature are used to verify the authenticity of the token, while the payload contains all of the important data about the user or application.

Identity Token

An identity token represents an authentication of an end-user issued by the authorization server to the client. It contains claims about the authenticated user which allow the client to verify that a user is who they claim to be. The information inside an identity token can be used to improve user experience. For example, showing the name of the logged in user next to a sign out button. And, a web application can also use it to decide what pages a user may access. For example, a signed-in user with the administrator role can access pages on which it can do administrator tasks.

The example below shows a decoded version of an identity token.

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "1LTMzakihiRla_8z2BEJVXeWMqo"
}.{
  "ver": "2.0",
  "iss": "https://login.microsoftonline.com/9122040d-6c67-4c5b-b112-36a304b66dad/v2.0",
  "sub": "AAAAAAAAAAAAAAAAAAAAAIkzqFVrSaSaFHy782bbtaQ",
  "aud": "6cb04018-a3f5-46a7-b995-940c78f5aef3",
  "exp": 1536361411,
  "iat": 1536274711,
  "nbf": 1536274711,
  "name": "Abe Lincoln",
  "preferred_username": "AbeLi@microsoft.com",
  "oid": "00000000-0000-0000-66f3-3332eca7ea81",
  "roles": [
    "Administrator"
  ],
  "tid": "9122040d-6c67-4c5b-b112-36a304b66dad",
  "nonce": "123523",
  "aio": "Df2UVXL1ix!lMCWMSOJBcFatzcGfvFGhjKv8q5g0x732dR5MB5BisvGQO7YWByjd8iQDLq!eGbIDakyp5mnOrcdqHeYSnltepQmRp6AIZ8jY"
}.[Signature]

Access Token

An access token represents an authorization issued by the authorization server to the client and can be used to access a protected API. For example, if a signed-in user consents with the scopes requested by a web application, the authorization server returns an access token that can be used by the web application to access the API on behalf of the user. When the API receives the request including this access token, it will validate the access token and verify if it contains the required scopes and roles.

The example below shows a decoded version of an access token.

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "i6lGk3FZzxRcUb2C3nEQ7syHJlY"
}.{
  "aud": "6e74172b-be56-4843-9ff4-e66a39bb12e3",
  "iss": "https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47/v2.0",
  "iat": 1537231048,
  "nbf": 1537231048,
  "exp": 1537234948,
  "aio": "AXQAi/8IAAAAtAaZLo3ChMif6KOnttRB7eBq4/DccQzjcJGxPYy/C3jDaNGxXd6wNIIVGRghNRnwJ1lOcAnNZcjvkoyrFxCttv33140RioOFJ4bCCGVuoCag1uOTT22222gHwLPYQ/uf79QX+0KIijdrmp69RctzmQ==",
  "azp": "6e74172b-be56-4843-9ff4-e66a39bb12e3",
  "azpacr": "0",
  "name": "Abe Lincoln",
  "oid": "690222be-ff1a-4d56-abd1-7e4f7d38e474",
  "preferred_username": "abeli@microsoft.com",
  "rh": "I",
  "roles": [
    "ApiAdmin",
    "ApiUser"
  ],
  "scp": "Documents.ReadWrite.All",
  "sub": "HKZpfaHyWadeOouYlitjrI-KffTm222X5rrV3xDqfKQ",
  "tid": "72f988bf-86f1-41af-91ab-2d7cd011db47",
  "uti": "fqiBqXLPj0eQa82S-IYFAA",
  "ver": "2.0"
}.[Signature]

Refresh Token

A refresh token is used to obtain an access token and is issued by the authorization server to the client. When an access token becomes invalid or expires, the application can use the refresh token to obtain a new access token. The application can also use the refresh token to obtain an additional access token with identical or narrower scope.

The workings of authentication flows

Authentication flows are used for obtaining security tokens. Selecting the right flow depends on your application type and the scenario you wish to implement. The flows described in this chapter are:

  • Authorization Code Flow – Use this flow for single page apps, web apps, desktop apps and mobile apps.
  • Client Credentials Flow – Use this flow for applications that call APIs without a user.
  • Implicit Flow – You can use this flow for single page applications, but it is not a best practice.
  • On-Behalf-Of Flow – Use this flow for middle-tier APIs that call downstream APIs.

Authorization Code Flow

The authorization code flow requires a user-agent that support redirection from the authorization server back to your application. The web application in the example below uses the Azure AD authorization endpoint to sign in a user. Because the web application also wants to access an API on behalf of the user, it requests both an identity token and access token as part of the authentication request to the authorization server. When the user signs in for the first time, the authorization server requests the user to accept the scopes requested by the web application. Then, if the user accepts the scopes, the authorization server issues an authorization code and redirects the user back to the web application. The web application will then do a POST request to the token endpoint to exchange the authorization code for an identity token and access token.

Authorization Code Flow using Azure AD

Used in scenarios:

ScenarioTokens
Single Page Application that signs in users. Because the application will not call an API, it only requests an identity token.
Single Page Application that signs in users and calls a protected web api.The application requests an identity token and access token.
Web application that signs in users.Because the application will not call an API, it only requests an identity token.
Web application that signs in users and calls a protected web api.The application requests an identity token and access token.
Desktop application that signs in users and calls a protected web api.The application requests an identity token and access token.
Mobile application that signs in users and calls a protected web api.The application requests an identity token and access token.

Client Credentials Flow

The client credentials flow allows an application to authenticate itself using its own credentials and request an access token. In the example below, a daemon application is running in the background and wants to access an API. In order to use the protected API, the application needs an access token. Because there is no user involved, there are no scopes to be granted and the authorization endpoint cannot be used. To obtain an access token, the application sends an authentication request using its client id and secret to the token endpoint. As a result, the token endpoint returns an access token including the permissions to access the API.

Client Credentials Flow using Azure AD

Used in scenarios:

ScenarioTokens
Daemon application that calls a protected web api.Because there is no user involved, the application only requests an access token.

Implicit Flow

The implicit flow is created for Single Page Applications (SPA) running in a web browser. The web application in the example below uses the Azure AD authorization endpoint to sign in a user. Because the web application also wants to access an API on behalf of the user, it requests both an identity token and access token as part of the authentication request to the authorization server. When the user signs in for the first time, the authorization server requests the user to accept the scopes requested by the web application. Then, if the user accepts the scopes, the authorization server issues an identity and access token directly from the authorization endpoint and redirects the user back to the web application.

Using this flow is no longer considered a best practice. It is better to use the authorization code flow instead. The reason the implicit flow is created was because of an old limitation in web browsers. It used to be the case that JavaScript could only make requests to the same server that the page was loaded from. Because the authorization code flow requires a POST request to be sent to the authorization server, which is often on a different domain than the application, this wouldn’t work. The implicit flow worked around this limitation by avoiding that POST request, and instead returning the access token immediately in the redirect.

Implicit Flow using Azure AD

Used in scenarios:

ScenarioTokens
Single Page Application that signs in users.Because the application will not call an API, it only requests an identity token.
Single Page Application that signs in users and calls a protected web api.The application requests an identity token and access token.

On-Behalf-Of Flow

The on-behalf-of flow can be used by a middle-tier web api to access a downstream api. For example, assume that a web application signs in a user using the authorization code flow. The web application now contains an access token and uses it to call the middle-tier web api. The middle-tier web api needs to call another web api on behalf of the user. It can do so using its own client id and secret and the received access token from the client.

On-Behalf-Of Flow using Azure AD

Used in scenarios:

ScenarioTokens
Web api that calls a protected web api.The application only requests an access token.

Delegating access using scopes

If you are building an API and want to allow a client application to access that API on behalf of the signed-in user, you will need to create scopes. These scopes should describe the actions or resoures available to the client. When a user signs in, the client will need to ask the user to grant a specific scope, or set of scopes, for the resource it wants to access. Granting a scope means the user authorizes the client application to access that specific resource or action of the API on behalf of the user.

Define API scopes

You can define scopes in the app registration for your API as shown in the example below. This API supports actions to read, create, update and delete documents of the user. Before a client application can use these scopes, they need to be assigned to the app registration as shown in the next chapter.

Define API scopes in app registration

In this scenario, the user is the resource owner. The scopes define what resources and actions the client application can access on behalf of the user.

ScopeDescription
Documents.ReadAllows the app to read the signed-in user’s documents.
Documents.Read.AllAllows the app to read all documents the signed-in user can access.
Documents.ReadWriteAllows the app to read, create, update and delete the signed-in user’s documents.
Documents.ReadWrite.AllAllows the app to read, create, update and delete all documents the signed-in user can access.

For API access scenarios where the user is not the resource owner, you could define a more generic scope as shown in the table below. You should always use scopes in delegated access scenarios.

ScopeDescription
access_as_userAllows the app to access the API on behalf of the signed-in user.

Assign API scopes to a web app

As previously stated, you need to assign scopes to the client application before the application can use them. For example, the app registration in the image below has assigned the delegated scopes: Documents.ReadWrite.All, User.Read and User.ReadWrite. As a result, the web app can use these scopes in the authentication request to the authorization server. When a user signs in, the authorization server requests the user to grant the requested scopes. Only If the user grants these scopes requested by the web app, it can access the APIs on behalf of the user.

Grant API scopes to a web app

The web application can now use the assigned scopes in the authorization request to the Azure AD authorization endpoint. When the user signs into the web application for the first time, the authorization server requests the user to accept the scopes requested by the web application. Then, if the user accepts these scopes, the authorization endpoint returns an access token that looks like the token shown in the previous chapter. As a result, the web application can use this token to call the API on behalf of the signed-in user.

Grant API scopes

Authorizing access using app roles

In the previous chapter I have shown you how to delegate user access to a web application using scopes. When the web application calls your API on behalf of the user, you might want to verify if the user contains the required permissions to access that resource or action. You can use app roles to assign permissions to users and limit their level of access. For example, if the web application tries to execute a specific action only administrators are allowed to, the API should check if the administrator role is assigned to the user.

You can also use app roles in an app-only access scenario where the application calls the API under its own identity. In that case, you assign the app roles to the application. Take, for example, a background application that periodically checks for document updates and sends a summary by e-mail to all relevant users. The background application is only allowed to retrieve document updates and therefore it is assigned the app role Documents.Read.Updates. When the background application tries to retrieve the document updates, the API should check if this role is assigned to the application.

Define API app roles

You can define app roles in the app registration for your API. The example below shows the same app registration used earlier to define scopes. When you create an app role, you specify the allowed member types. For example, the app roles ApiAdmin and ApiUser can only be assigned to users and groups. But the app role Document.Read.Updates can only be assigned to applications.

Define app roles in app registration

Assign API app roles to a user

You can assign app roles to Azure AD users on the Enterprise Application page for your API. As can be seen in the example below, the two app roles ApiUser and ApiAdmin defined in the previous chapter are assigned to a user. It is also possible to assign an app role to a group of users. For example, your organisation defined a group for each department and you assigned the ApiUser role to the finance department. As a result, all users within the finance department inherits the ApiUser role.

Assign API app roles to a user

In the previous chapters, scopes were defined for an API and assigned to a web application. When the user presented in the image above signs in for the first time and accepts the requested scopes, the authorization endpoint returns an access token which includes the accepted scopes and assigned roles. As a result, the web application can use the token to access the API on behalf of the user. When the API receives the request, it verifies if the required scopes are accepted by the user, and if the user contains the required roles to access the requested resource or action.

Assign API app roles to an application

You can assign app roles to the app registration for your application as shown in the example below. This application will periodically check for updates using the Document API and sends a summary by e-mail to all relevant users. In order to use the API, the Document Update Notifier needs the required permissions. It is therefore assigned the app role Documents.Read.Updates. When the Document Update Notifier authenticates itself using the client credentials flow, the authorization endpoint returns an access token containing this app role. As a result, the application can use the API using this acess token to retrieve document updates.

Assign API app roles to an application

Conclusion

The OAuth 2.0 protocol allows applications to obtain and use access tokens to access protected APIs. It is designed only for authorization and does not provide methods to obtain identity information. OpenID Connect implements authentication as an extension to the OAuth 2.0 authorization process and is used to request an identity token. The identity token contains claims about the authenticated user which allows the client to verify that a user is who they claim to be.

Scopes are used in delegated access scenarios and should describe the actions or resoures available to the client. When a user signs in, the client will need to ask the user to grant a specific scope, or set of scopes, for the resource it wants to access. After consent of the user, the authorization server returns an access token including the granted scopes. In short, granting a scope means the user authorizes the client application to access the API on behalf of the user.

App roles are used to assign permissions to users and applications and limit their level of access. In case of a delegated access scenario, you can assign app roles to users and groups. For example, if a user tries to execute a specific action only administrators are allowed to, the API should check if the administrator role is part of the access token. In case of an app-only access scenario where there is no user involved, you assign app roles to an application.

2 thoughts on “Understanding OAuth Scopes And Roles In Azure AD”

  1. Great article. I know functionally how scopes and roles work, but I’m still not 100% I understand the implications. Is it fair to say that:

    – Scopes are mostly about consent to access resources. Scope validation is there to ensure that consent has been provided to perform an action on a resource. The user has control over this. (although admins may consent on their behalf)
    – App Roles are more from the perspective of application functionality. App Role validation ensures that the user (or service principal) is permitted to preform an action as decreed by the role assigned to them – by the app administrator i.e. the admin has control over this.

    Is this distinction correct?

    I’m implementing access control policies and performing app role and scope validation (user auth only). Are scopes really needed where the API isn’t accessing user resources? e.g. does a weather API really need a “read” consent scope? I have some backend services where there isn’t a concept of “ownership” of the data created. Is there any value in creating a “write” scope given that the user isn’t consenting to access to their resources? In both instances I would still use App Roles as access control to the API, but I’m not convinced that I need to create/validate scopes.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top