Access Tokens in Microsoft Entra (aka AAD)
Access tokens are a crucial aspect of identity and access management in Microsoft Entra. They serve as the bridge between applications and protected resources, ensuring that only authorized entities gain access. In this post, we'll explore the different types of access tokens, and the flows involved in issuing them.
Access Tokens
In Microsoft Entra, to access a protected resource, your application needs the resource owner's authorization. The resource owner can consent to or deny your app's request.
Access Scenarios
As an application developer, you must identify how your application will access data. The application can use delegated access, acting on behalf of a signed-in user, or app-only access, acting only as the application's own identity.
Delegated Access (Access on Behalf of a User)
Use delegated access when you want a signed-in user to work with their own resources or resources they can access. The client application accesses the resource on behalf of the user. Delegated access requires delegated permissions (also known as scopes). Scopes are permissions for a given resource that define what a client application can access on behalf of the user. Both the client and the user must be authorized separately to make the request.
In this scenario, a user has signed into a client application. However, delegated access is not ideal for situations that need to run without a signed-in user, like automation. It may also be unsuitable for accessing many users' resources, such as data loss prevention or backups. For these operations, consider using application-only access.
App-Only Access (Access Without a User)
In App-Only access scenario, the application operates on its own without a signed-in user. Application access is used for tasks like automation and backup. This includes apps that run as background services or daemons. It's suitable when you don't want a specific user signed in or when the data needed can't be scoped to a single user.
App-only access uses app roles instead of delegated scopes. App roles are also known as application-only permissions. The client app must be granted the right application permissions for the resource app it is calling. Once granted, the client app can access the requested data.
The key point about app-only access is that the calling app acts on its own behalf and identity. There's no user interaction. If the app has been assigned a specific app role for a resource, it has full access to all resources and operations governed by that role.
Once an app has been assigned one or more app roles (app-only permissions), it can request an app-only token from Microsoft Entra ID using the client credentials flow or any other supported authentication flow. The assigned roles are added to the roles claim of the app's access token.
Flows of Issuing Access Tokens
Issuing access tokens in Microsoft Entra involves several flows, each tailored to different scenarios and security requirements. The choice of flow depends on factors such as the type of client application, the level of security needed, and the user experience requirements. Here are the most important flows:
Authorization Code Flow
Used for delegated access. The Authorization Code Flow is ideal for applications that require a high level of security, such as web applications and mobile apps. The auth code flow requires a user-agent that supports redirection from the authorization server (the Microsoft identity platform) back to your application. This flow involves several steps:
Authorization Request - The client application redirects the user to the authorization server, requesting authorization.
User Authentication - The user authenticates with the authorization server and grants permission.
Authorization Code Issuance - The authorization server issues an authorization code to the client.
Token Exchange - The client application exchanges the authorization code for an access token by making a backchannel request to the authorization server.
This flow ensures that the access token is never exposed to the user agent or potentially malicious scripts.
Client Credentials Flow
Used for app-only access. Client Credentials Flow is used by applications that act on their own behalf, rather than on behalf of a user. This flow is commonly used for server-to-server communication, such as APIs or backend services:
Token Request - The client application sends a token request to the authorization server, including its client credentials (client ID and secret).
Token Issuance - The authorization server verifies the client credentials and issues an access token directly to the client application.
This flow does not involve user interaction and is highly secure when using strong client authentication mechanisms.
On-Behalf-Of Flow
Used for delegated access, the On-Behalf-Of Flow is used when a service needs to call another downstream service on behalf of a user. For the middle-tier service to make authenticated requests to the downstream service, it needs to obtain an access token from the Microsoft identity platform. This is common in microservices architectures:
The user authenticates and obtains an access token for Service A.
Service A, acting on behalf of the user, requests an access token to access Service B from the authorization server.
The authorization server issues an access token to Service A, which can now call Service B on behalf of the user.
This flow allows for delegation of permissions, ensuring that services only access resources on behalf of an authenticated user.
App-Only Tokens vs. User Delegated Tokens
In Microsoft Entra, an access token is a security token issued by an authorization server as part of an OAuth 2.0 flow. It contains information about the user and the resource for which the token is intended. This information can be used to access web APIs and other protected resources. Access tokens are passed to a web API as the bearer token in the Authorization
header.
The default lifetime of an access token is variable. When issued, the Microsoft identity platform assigns a random value ranging between 60-90 minutes (75 minutes on average) as the default lifetime of an access token. The variation improves service resilience by spreading access token demand over a time, which prevents hourly spikes in traffic to Microsoft Entra ID.
In Authorization code flow and On-behalf-of flow, the authorization server frequently provides a pair of tokens. An access token is provided, which accesses the application or protected resource. A refresh token is provided, which is used to refresh the access token when the access token is close to expiring.
User Delegated Tokens
User delegated tokens are acquired on behalf of a user. These tokens carry the user's identity and permissions, allowing the application to act on behalf of the user. User delegated tokens are obtained through flows like the Authorization Code Flow or the On-Behalf-Of Flow. They are essential for scenarios where actions are performed under the user's context, ensuring proper authorization and access control.
App-Only Tokens
App-only tokens are acquired by applications that act on their own behalf without any user context. They are typically used for service-to-service communication or background jobs that do not require user interaction. App-only tokens are obtained through the Client Credentials Flow, ensuring that the application can authenticate itself independently. Many human-specific claims will be missing, such as name
or upn
.
Understanding Claims
Claims are pieces of information asserted about a user or an application. These claims are encoded within the access token and can include data such as the user's identity, the token's issuer, the token's expiration time, and the permissions granted to the client application. Typical claims include:
iss: The issuer of the token, which should match the authorization server's identifier.
aud: The audience for the token, the app for which the token was generated. Typically the resource server's identifier.
exp: The expiration time beyond which the token is no longer valid.
sub: The subject of the token, usually the user’s unique identifier.
scp: The permissions granted to the user. Not included in app tokens.
roles: The permissions granted to the client application.
tid: For users, represents the tenant that the user is signing in to. For apps, represents the tenant of the service principal, specified in `Authority` when requesting the token. The service should limit data access based on tid.
oid: The immutable identifier for the requestor, which is the verified identity of the user or service principal. Not included in app tokens.
upn: The username of the user. May be a phone number, email address, or unformatted string. Only use for display purposes and providing username hints in reauthentication scenarios. Not included in app tokens.
appid: The application ID of the client using the token. The application can act as itself or on behalf of a user. The application ID typically represents an application object, but it can also represent a service principal object in Microsoft Entra ID.
idtyp: An optional claim for V2.0 tokens. The value `
app
` indicates the token is issued for an application. This claim is the most accurate way for an API to determine if a token is an app token.
Validating Access Tokens
It's up to the application for which the token was generated, the web app that signed in the user, or the web API being called to validate the token. The authorization server signs the token with a private key and publishes the corresponding public key. To validate a token, the app verifies the signature using the authorization server's public key to ensure it was created with the private key. This process involves checking the token's signature, issuer, audience, and possibly other claims.
Avoid using claims such as email
, preferred_username
, upn
, or unique_name
to determine user access in an access token. These claims are not unique and can be managed by tenant administrators or even users at times, making them unreliable for authorization purposes. They should only be used for display purposes. Use the immutable claim values tid
and oid
as a combined key for application data and determining whether a user should be granted access.
Always check that the tid
in a token matches the tenant ID used to store data with the application. When information is stored for an application in the context of a tenant, it should only be accessed again later in the same tenant. Never allow data in one tenant to be accessed from another tenant.
You must always verify that the value of the aud
claim contained in the access token matches the client-id of your AAD application. The value can depend on how the client requested the token. The audience in the access token depends on the endpoint:
For v2.0 tokens, the audience is the client ID of the web API. It's a GUID.
For v1.0 tokens, the audience is one of the appID URIs declared in the web API that validates the token. For example,
api://{ApplicationID}
, or a unique name starting with a domain name (if the domain name is associated with a tenant).
Conclusion
Understanding access tokens in Microsoft Entra, their types, and the various flows of issuing them is crucial for implementing secure and efficient identity and access management solutions. Each type of token and flow has its specific use cases and security implications. By choosing the appropriate token type and flow, organizations can ensure that their applications and services are protected against unauthorized access while providing a seamless user experience.
Subscribe to my newsletter
Read articles from Ehsan Mirsaeedi directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by