Azure Implementing Authentication

The following is from Azure Developer Training lab for AZ-203

Microsoft identity platform overview

Microsoft identity platform is an evolution of the Azure Active Directory (Azure AD) identity service and developer platform. It allows developers to build applications that sign in all Microsoft identities, get tokens to call Microsoft Graph, other Microsoft APIs, or APIs that developers have built. It’s a full-featured platform that consists of an authentication service, open-source libraries, application registration and configuration (through a developer portal and applicationAPI), full developer documentation, code samples, and other developer content. The Microsoft identity platform supports industry standard protocols such as OAuth 2.0 and OpenID Connect.

 

Application types in Azure AD

Azure Active Directory (Azure AD) supports authentication for a variety of modern app architectures, all of them based on industry-standard protocols OAuth 2.0 or OpenID Connect.

The following diagram illustrates the scenarios and application types, and how different components can be added:

These are the five primary application scenarios supported by Azure AD:

  • Single-page application (SPA): A user needs to sign in to a single-page application that is secured by Azure AD.
  • Web browser to web application: A user needs to sign in to a web application that is secured by Azure AD.
  • Native application to web API: A native application that runs on a phone, tablet, or PC needs to authenticate a user to get resources from a web API that is secured by Azure AD.
  • Web application to web API: A web application needs to get resources from a web API secured by Azure AD.
  • Daemon or server application to web API: A daemon application or a server application with no web user interface needs to get resources from a web API secured by Azure AD.

 

App registration

Any application that outsources authentication to Azure AD must be registered in a directory. This step involves telling Azure AD about your application, including the URL where it’s located, the URL to send replies after authentication, the URI to identify yourapplication, and more. This information is required for a few key reasons:

  • Azure AD needs to communicate with the application when handling sign-on or exchanging tokens. The information passed between Azure AD and the application includes the following:
    • Application ID URI – The identifier for an application. This value is sent to Azure AD during authentication to indicate which application the caller wants a token for. Additionally, this value is included in the token so that the application knows it was theintended target.
    • Reply URL and Redirect URI – For a web API or web application, the Reply URL is the location where Azure AD will send the authentication response, including a token if authentication was successful. For a native application, the Redirect URI is aunique identifier to which Azure AD will redirect the user-agent in an OAuth 2.0 request.
    • Application ID – The ID for an application, which is generated by Azure AD when the application is registered. When requesting an authorization code or token, the Application ID and Key are sent to Azure AD during authentication.
    • Key – The key that is sent along with an Application ID when authenticating to Azure AD to call a web API.
  • Azure AD needs to ensure the application has the required permissions to access your directory data, other applications in your organization, and so on.

Single-tenant and multi-tenant apps

Provisioning becomes clearer when you understand that there are two categories of applications that can be developed and integrated with Azure AD:

  • Single tenant application – A single tenant application is intended for use in one organization. These are typically line-of-business (LoB) applications written by an enterprise developer. A single tenant application only needs to be accessed by users in onedirectory, and as a result, it only needs to be provisioned in one directory. These applications are typically registered by a developer in the organization.
  • Multi-tenant application – A multi-tenant application is intended for use in many organizations, not just one organization. These are typically software-as-a-service (SaaS) applications written by an independent software vendor (ISV). Multi-tenant applications need to be provisioned in each directory where they will be used, which requires user or administrator consent to register them. This consent process starts when an application has been registered in the directory and is given access to the GraphAPI or perhaps another web API. When a user or administrator from a different organization signs up to use the application, they are presented with a dialog that displays the permissions the application requires. The user or administrator can then consent to the application, which gives the application access to the stated data, and finally registers the application in their directory.
Additional considerations when developing single tenant or multi-tenant apps

Some additional considerations arise when developing a multi-tenant application instead of a single tenant application. For example, if you are making your application available to users in multiple directories, you need a mechanism to determine which tenant they’re in. A single tenant application only needs to look in its own directory for a user, while a multi-tenant application needs to identify a specific user from all the directories in Azure AD. To accomplish this task, Azure AD provides a common authentication endpoint where any multi-tenant application can direct sign-in requests, instead of a tenant-specific endpoint. This endpoint is https://login.microsoftonline.com/common for all directories in Azure AD, whereas a tenant-specific endpoint might be https://login.microsoftonline.com/contoso.onmicrosoft.com. The common endpoint is especially important to consider when developing your application because you’ll need the necessary logic to handle multiple tenants during sign-in, sign-out, and token validation.

If you are currently developing a single tenant application but want to make it available to many organizations, you can easily make changes to the application and its configuration in Azure AD to make it multi-tenant capable. In addition, Azure AD uses the same signing key for all tokens in all directories, whether you are providing authentication in a single tenant or multi-tenant application.

 

Application and service principal objects in Azure Active Directory

Sometimes, the meaning of the term “application” can be misunderstood when used in the context of Azure Active Directory (Azure AD). This article clarifies the conceptual and concrete aspects of Azure AD application integration, with an illustration of registration and consent for a multi-tenant application.

Overview

An application that has been integrated with Azure AD has implications that go beyond the software aspect. “Application” is frequently used as a conceptual term, referring to not only the application software, but also its Azure AD registration and role in authentication/authorization “conversations” at runtime.

By definition, an application can function in these roles:

  • Client role (consuming a resource)
  • Resource server role (exposing APIs to clients)
  • Both client role and resource server role

An OAuth 2.0 Authorization Grant flow defines the conversation protocol, which allows the client/resource to access/protect a resource’s data, respectively.

In the following sections, you’ll see how the Azure AD application model represents an application at design-time and run-time.

Example

The following diagram illustrates the relationship between an application’s application object and corresponding service principal objects, in the context of a sample multi-tenant application called HR app. There are three Azure AD tenants in this example scenario:

  • Adatum – The tenant used by the company that developed the HR app
  • Contoso – The tenant used by the Contoso organization, which is a consumer of the HR app
  • Fabrikam – The tenant used by the Fabrikam organization, which also consumes the HR app

 

In this example scenario:

Step Description
1 Is the process of creating the application and service principal objects in the application’s home tenant.
2 When Contoso and Fabrikam administrators complete consent, a service principal object is created in their company’s AzureAD tenant and assigned the permissions that the administrator granted. Also note that the HR app could be configured/designed to allow consent by users for individual use.
3 The consumer tenants of the HR application (Contoso and Fabrikam) each have their own service principal object. Each represents their use of an instance of the application at runtime, governed by the permissions consented by the respective administrator.

Permissions and consent in the Azure Active Directory v1.0 and v2.0 endpoints

Azure Active Directory (Azure AD) makes extensive use of permissions for both OAuth and OpenID Connect (OIDC) flows. When your app receives an access token from Azure AD, the access token will include claims that describe the permissions that your app has in respect to a particular resource.

Permissions, also known as scopes, make authorization easy for the resource because the resource only needs to check that the token contains the appropriate permission for whatever API the app is calling.

Types of permissions

Azure AD defines two kinds of permissions:

  • Delegated permissions – Are used by apps that have a signed-in user present. For these apps, either the user or an administrator consents to the permissions that the app requests and the app is delegated permission to act as the signed-in user when making calls to an API. Depending on the API, the user may not be able to consent to the API directly and would instead require an administrator to provide “admin consent”.
  • Application permissions – Are used by apps that run without a signed-in user present; for example, apps that run as background services or daemons. Application permissions can only be consented by an administrator because they are typically powerful and allow access to data across user-boundaries, or data that would otherwise be restricted to administrators.

Effective permissions are the permissions that your app will have when making requests to an API.

  • For delegated permissions, the effective permissions of your app will be the least privileged intersection of the delegated permissions the app has been granted (through consent) and the privileges of the currently signed-in user. Your app can never have more privileges than the signed-in user. Within organizations, the privileges of the signed-in user may be determined by policy or by membership in one or more administrator roles. To learn which administrator roles can consent to delegated permissions, seeAdministrator role permissions in Azure AD. For example, assume your app has been granted the User.ReadWrite.All delegated permission in Microsoft Graph. This permission nominally grants your app permission to read and update the profile of every user in an organization. If the signed-in user is a global administrator, your app will be able to update the profile of every user in the organization. However, if the signed-in user is not in an administrator role, your app will be able to update only the profile of the signed-in user. It will not be able to update the profiles of other users in the organization because the user that it has permission to act on behalf of does not have those privileges.
  • For application permissions, the effective permissions of your app are the full level of privileges implied by the permission. For example, an app that has the User.ReadWrite.All application permission can update the profile of every user in the organization.

 

Permission attributes

Permissions in Azure AD have a number of properties that help users, administrators, or app developers make informed decisions about what the permission grants access to.

Property name Description Example
ID Is a GUID value that uniquely identifies this permission. 570282fd-fa5c-430d-a7fd-fc8dc98a9dca
IsEnabled Indicates whether this permission is available for use. true
Type Indicates whether this permission requires user consent or admin consent. User
AdminConsentDescription Is a description that’s shown to administrators during the admin consentexperiences Allows the app to read email in user mailboxes.
AdminConsentDisplayName Is the friendly name that’s shown to administrators during the admin consentexperience. Read user mail
UserConsentDescription Is a description that’s shown to users during a user consent experience. Allows the app to read email in your mailbox.
UserConsentDisplayName Is the friendly name that’s shown to users during a user consent experience. Read your mail
Value Is the string that’s used to identify the permission during OAuth 2.0 authorize flows.Value may also be combined with the App ID URI string in order to form a fullyqualified permission name. Mail.Read

Types of consent

Applications in Azure AD rely on consent in order to gain access to necessary resources or APIs. There are a number of kinds of consent that your app may need to know about in order to be successful. If you are defining permissions, you will also need tounderstand how your users will gain access to your app or API.

  • Static user consent – Occurs automatically during the OAuth 2.0 authorize flow when you specify the resource that your app wants to interact with. In the static user consent scenario, your app must have already specified all the permissions it needs in theapp’s configuration in the Azure portal. If the user (or administrator, as appropriate) has not granted consent for this app, then Azure AD will prompt the user to provide consent at this time.
  • Dynamic user consent – Is a feature of the v2 Azure AD app model. In this scenario, your app requests a set of permissions that it needs in the OAuth 2.0 authorize flow for v2 apps. If the user has not consented already, they will be prompted to consent at thistime. Learn more about dynamic consent.Important: Dynamic consent can be convenient, but presents a big challenge for permissions that require admin consent, since the admin consent experience doesn’t know about those permissions at consent time. Ifyou require admin privileged permissions or if your app uses dynamic consent, you must register all of the permissions in the Azure portal (not just the subset of permissions that require admin consent). This enables tenant admins to consent on behalf of alltheir users.
  • Admin consent – Is required when your app needs access to certain high-privilege permissions. Admin consent ensures that administrators have some additional controls before authorizing apps or users to access highly privileged data from the organization.

Best practices

Client best practices
  • Only request for permissions that your app needs. Apps with too many permissions are at risk of exposing user data if they are compromised.
  • Choose between delegated permissions and application permissions based on the scenario that your app supports.
    • Always use delegated permissions if the call is being made on behalf of a user.
    • Only use application permissions if the app is non-interactive and not making calls on behalf of any specific user. Application permissions are highly privileged and should only be used when absolutely necessary.
  • When using an app based on the v2.0 endpoint, always set the static permissions (those specified in your application registration) to be the superset of the dynamic permissions you request at runtime (those specified in code and sent as query parameters in your authorize request) so that scenarios like admin consent works correctly.
Resource/API best practices
  • Resources that expose APIs should define permissions that are specific to the data or actions that they are protecting. Following this best practice helps to ensure that clients do not end up with permission to access data that they do not need and that users are well informed about what data they are consenting to.
  • Resources should explicitly define Read and ReadWrite permissions separately.
  • Resources should mark any permissions that allow access to data across user boundaries as Admin permissions.
  • Resources should follow the naming pattern Subject.Permission[.Modifier], where:
    • Subject corresponds with the type of data that is available
    • Permission corresponds to the action that a user may take upon that data
    • Modifier is used optionally to describe specializations of another permission

 

OAuth2 Authentication

Authorize access to web applications using OpenID Connect

OpenID Connect is a simple identity layer built on top of the OAuth 2.0 protocol. OAuth 2.0 defines mechanisms to obtain and use access tokens to access protected resources, but they do not define standard methods to provide identity information. OpenIDConnect implements authentication as an extension to the OAuth 2.0 authorization process. It provides information about the end user in the form of an id_token that verifies the identity of the user and provides basic profile information about the user.

OpenID Connect is our recommendation if you are building a web application that is hosted on a server and accessed via a browser.

Register your application with your AD tenant

First, you need to register your application with your Azure Active Directory (Azure AD) tenant. This will give you an Application ID for your application, as well as enable it to receive tokens.

  • Sign in to the Azure portal.
  • Choose your Azure AD tenant by clicking on your account in the top right corner of the page, followed by clicking on the Switch Directory navigation and then select the appropriate tenant.
    • Skip this step, if you’ve only one Azure AD tenant under your account or if you’ve already selected the appropriate Azure AD tenant.
  • In the left hand navigation pane, click on Azure Active Directory.
  • Click on App Registrations and click on New application registration.
  • Follow the prompts and create a new application. It doesn’t matter if it is a web application or a native application for this tutorial.
    • For Web Applications, provide the Sign-On URL, which is the base URL of your app, where users can sign in e.g http://localhost:12345.
    • For Native Applications provide a Redirect URI, which Azure AD will use to return token responses. Enter a value specific to your application, .e.g http://MyFirstAADApp.
  • Once you’ve completed registration, Azure AD will assign your application a unique client identifier, the Application ID. You need this value in the next sections, so copy it from the application page.
  • To find your application in the Azure portal, click App registrations, and then click View all applications.

Authentication flow using OpenID Connect

The most basic sign-in flow contains the following steps – each of them is described in detail below.

 

OpenID Connect metadata document

OpenID Connect describes a metadata document that contains most of the information required for an app to perform sign-in. This includes information such as the URLs to use and the location of the service’s public signing keys. The OpenID Connect metadatadocument can be found at:

https://login.microsoftonline.com/{tenant}/.well-known/openid-configuration

The metadata is a simple JavaScript Object Notation (JSON) document. See the following snippet for an example. The snippet’s contents are fully described in the OpenID Connect specification. Note that providing tenant rather than common in place of {tenant}above will result in tenant-specific URIs in the JSON object returned.

{ "authorization_endpoint": "https://login.microsoftonline.com/common/oauth2/authorize", "token_endpoint": "https://login.microsoftonline.com/common/oauth2/token", "token_endpoint_auth_methods_supported": [ "client_secret_post", "private_key_jwt", "client_secret_basic" ], "jwks_uri": "https://login.microsoftonline.com/common/discovery/keys" "userinfo_endpoint":"https://login.microsoftonline.com/{tenant}/openid/userinfo", ... }

Send the sign-in request

When your web application needs to authenticate the user, it must direct the user to the /authorize endpoint. This request is similar to the first leg of the OAuth 2.0 Authorization Code Flow, with a few important distinctions:

  • The request must include the scope openid in the scope parameter.
  • The response_type parameter must include id_token.
  • The request must include the nonce parameter.

So a sample request would look like this:

// Line breaks for legibility only GET https://login.microsoftonline.com/{tenant}/oauth2/authorize? client_id=6731de76-14a6-49ae-97bc-6eba6914391e &response_type=id_token &redirect_uri=http%3A%2F%2Flocalhost%3a12345 &response_mode=form_post &scope=openid &state=12345 &nonce=7362CAEA-9CA5-4B43-9BA3-34D7C303EBA7
Parameter Description
tenant required The {tenant} value in the path of the request can be used to control who can signinto the application. The allowed values are tenant identifiers, for example,8eaef023-2b34-4da1-9baa-8bc8c9d6a490 orcontoso.onmicrosoft.com or common for tenant-independent tokens
client_id required The Application Id assigned to your app when you registered it with Azure AD. Youcan find this in the Azure Portal. Click Azure Active Directory, click AppRegistrations, choose the application and locate the Application Id on theapplication page.
response_type required Must include id_token for OpenID Connect sign-in. It may also include otherresponse_types, such as code or token.
scope required A space-separated list of scopes. For OpenID Connect, it must include the scopeopenid, which translates to the “Sign you in” permission in the consent UI. Youmay also include other scopes in this request for requesting consent.
nonce required A value included in the request, generated by the app, that is included in theresulting id_token as a claim. The app can then verify this value to mitigatetoken replay attacks. The value is typically a randomized, unique string or GUIDthat can be used to identify the origin of the request.
redirect_uri recommended The redirect_uri of your app, where authentication responses can be sent andreceived by your app. It must exactly match one of the redirect_uris you registered inthe portal, except it must be url encoded.
response_mode optional Specifies the method that should be used to send the resulting authorization_codeback to your app. Supported values are form_post for HTTP form post andfragment for URL fragment. For web applications, we recommend usingresponse_mode=form_post to ensure the most secure transfer of tokens toyour application. The default for any flow including an id_token is fragment.
state recommended A value included in the request that is returned in the token response. It can be astring of any content that you wish. A randomly generated unique value is typicallyused for preventing cross-site request forgery attacks. The state is also used toencode information about the user’s state in the app before the authenticationrequest occurred, such as the page or view they were on.
prompt optional Indicates the type of user interaction that is required. Currently, the only validvalues are ‘login’, ‘none’, and ‘consent’. prompt=login forces the user to entertheir credentials on that request, negating single-sign on. prompt=none is theopposite – it ensures that the user is not presented with any interactive promptwhatsoever. If the request cannot be completed silently via single-sign on, theendpoint returns an error. prompt=consent triggers the OAuth consent dialogafter the user signs in, asking the user to grant permissions to the app.
login_hint optional Can be used to pre-fill the username/email address field of the sign-in page for theuser, if you know their username ahead of time. Often apps use this parameterduring reauthentication, having already extracted the username from a previoussign-in using the preferred_username claim.

At this point, the user is asked to enter their credentials and complete the authentication.

Sample response

A sample response, after the user has authenticated, could look like this:

POST / HTTP/1.1 Host: localhost:12345 Content-Type: application/x-www-form-urlencoded id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNB...&state=12345
Parameter Description
id_token The id_token that the app requested. You can use the id_token to verify the user’s identity and begin a session with theuser.
state A value included in the request that is also returned in the token response. A randomly generated unique value is typically usedfor preventing cross-site request forgery attacks. The state is also used to encode information about the user’s state in the appbefore the authentication request occurred, such as the page or view they were on.
Error response

Error responses may also be sent to the redirect_uri so the app can handle them appropriately:

POST / HTTP/1.1 Host: localhost:12345 Content-Type: application/x-www-form-urlencoded error=access_denied&error_description=the+user+canceled+the+authentication

Parameter Description
error An error code string that can be used to classify types of errors that occur, and can be used to react to errors.
error_description A specific error message that can help a developer identify the root cause of an authentication error.
Error codes for authorization endpoint errors

The following table describes the various error codes that can be returned in the error parameter of the error response.

Error Code Description Client Action
invalid_request Protocol error, such as a missing required parameter. Fix and resubmit the request. This is a development error, and is typically caughtduring initial testing.
unauthorized_client The client application is not permitted to request an authorization code. This usually occurs when the client application is not registered in Azure AD or isnot added to the user’s Azure AD tenant. The application can prompt the user withinstruction for installing the application and adding it to Azure AD.
access_denied Resource owner denied consent The client application can notify the user that it cannot proceed unless the userconsents.
unsupported_response_type The authorization server does not support the response type in the request. Fix and resubmit the request. This is a development error, and is typically caughtduring initial testing.
server_error The server encountered an unexpected error. Retry the request. These errors can result from temporary conditions. The clientapplication might explain to the user that its response is delayed due to a temporaryerror.
temporarily_unavailable The server is temporarily too busy to handle the request. Retry the request. The client application might explain to the user that its response isdelayed due to a temporary condition.
invalid_resource The target resource is invalid because it does not exist, Azure AD cannot find it, or itis not correctly configured. This indicates the resource, if it exists, has not been configured in the tenant. Theapplication can prompt the user with instruction for installing the application andadding it to Azure AD.

Validate the id_token

Just receiving an id_token is not sufficient to authenticate the user; you must validate the signature and verify the claims in the id_token per your app’s requirements. The Azure AD endpoint uses JSON Web Tokens (JWTs) and public key cryptography tosign tokens and verify that they are valid.

You can choose to validate the id_token in client code, but a common practice is to send the id_token to a backend server and perform the validation there. Once you’ve validated the signature of the id_token, there are a few claims you are required toverify.

You may also wish to validate additional claims depending on your scenario. Some common validations include:

  • Ensuring the user/organization has signed up for the app.
  • Ensuring the user has proper authorization/privileges
  • Ensuring a certain strength of authentication has occurred, such as multi-factor authentication.

Once you have validated the id_token, you can begin a session with the user and use the claims in the id_token to obtain information about the user in your app. This information can be used for display, records, personalization, etc.

Send a sign-out request

When you wish to sign the user out of the app, it is not sufficient to clear your app’s cookies or otherwise end the session with the user. You must also redirect the user to the end_session_endpoint for sign-out. If you fail to do so, the user will be able toreauthenticate to your app without entering their credentials again, because they will have a valid single sign-on session with the Azure AD endpoint.

You can simply redirect the user to the end_session_endpoint listed in the OpenID Connect metadata document:

GET https://login.microsoftonline.com/common/oauth2/logout? post_logout_redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
Parameter Description
post_logout_redirect_uri recommended The URL that the user should be redirected to after successful logout. If notincluded, the user is shown a generic message.

Single sign-out

When you redirect the user to the end_session_endpoint, Azure AD clears the user’s session from the browser. However, the user may still be signed in to other applications that use Azure AD for authentication. To enable those applications to sign the userout simultaneously, Azure AD sends an HTTP GET request to the registered LogoutUrl of all the applications that the user is currently signed in to. Applications must respond to this request by clearing any session that identifies the user and returning a 200response. If you wish to support single sign out in your application, you must implement such a LogoutUrl in your application’s code. You can set the LogoutUrl from the Azure portal:

  1. Navigate to the Azure Portal.
  2. Choose your Active Directory by clicking on your account in the top right corner of the page.
  3. From the left hand navigation panel, choose Azure Active Directory, then choose App registrations and select your application.
  4. Click on Settings, then Properties and find the Logout URL text box.

Token Acquisition

Many web apps need to not only sign the user in, but also access a web service on behalf of that user using OAuth. This scenario combines OpenID Connect for user authentication while simultaneously acquiring an authorization_code that can be used toget access_tokens using the OAuth Authorization Code Flow.

Get Access Tokens

To acquire access tokens, you need to modify the sign-in request from above:

// Line breaks for legibility only GET https://login.microsoftonline.com/{tenant}/oauth2/authorize? client_id=6731de76-14a6-49ae-97bc-6eba6914391e // Your registered Application Id &response_type=id_token+code &redirect_uri=http%3A%2F%2Flocalhost%3a12345 // Your registered Redirect Uri, url encoded &response_mode=form_post // `form_post' or 'fragment' &scope=openid &resource=https%3A%2F%2Fservice.contoso.com%2F // The identifier of the protected resource (web API) that your application needs access to &state=12345 // Any value, provided by your app &nonce=678910 // Any value, provided by your app

By including permission scopes in the request and using response_type=code+id_token, the authorize endpoint ensures that the user has consented to the permissions indicated in the scope query parameter, and return your app an authorizationcode to exchange for an access token.

Successful response

A successful response using response_mode=form_post looks like:

POST /myapp/ HTTP/1.1 Host: localhost Content-Type: application/x-www-form-urlencoded id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNB...&code=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...&state=12345
Parameter Description
id_token The id_token that the app requested. You can use the id_token to verify the user’s identity and begin a session with theuser.
code The authorization_code that the app requested. The app can use the authorization code to request an access token for the targetresource. Authorization_codes are short lived, and typically expire after about 10 minutes.
state If a state parameter is included in the request, the same value should appear in the response. The app should verify that the statevalues in the request and response are identical.
Error response

Error responses may also be sent to the redirect_uri so the app can handle them appropriately:

POST /myapp/ HTTP/1.1 Host: localhost Content-Type: application/x-www-form-urlencoded error=access_denied&error_description=the+user+canceled+the+authentication
Parameter Description
error An error code string that can be used to classify types of errors that occur, and can be used to react to errors.
error_description A specific error message that can help a developer identify the root cause of an authentication error.

For a description of the possible error codes and their recommended client action, see Error codes for authorization endpoint errors above.

Once you’ve gotten an authorization code and an id_token, you can sign the user in and get access tokens on their behalf. To sign the user in, you must validate the id_token exactly as described above.

 

Understanding the OAuth2 implicit grant flow in Azure Active Directory

The OAuth2 implicit grant is notorious for being the grant with the longest list of security concerns in the OAuth2 specification. And yet, that is the approach implemented by ADAL JS and the one we recommend when writing SPA applications. What gives? It’s all a matter of tradeoffs: and as it turns out, the implicit grant is the best approach you can pursue for applications that consume a Web API via JavaScript from a browser.

What is the OAuth2 implicit grant?

The quintessential OAuth2 authorization code grant is the authorization grant that uses two separate endpoints. The authorization endpoint is used for the user interaction phase, which results in an authorization code. The token endpoint is then used by the client for exchanging the code for an access token, and often a refresh token as well. Web applications are required to present their own application credentials to the token endpoint, so that the authorization server can authenticate the client.

The OAuth2 implicit grant is a variant of other authorization grants. It allows a client to obtain an access token (and id_token, when using OpenId Connect) directly from the authorization endpoint, without contacting the token endpoint nor authenticating the client. This variant was designed for JavaScript based applications running in a Web browser: in the original OAuth2 specification, tokens are returned in a URI fragment. That makes the token bits available to the JavaScript code in the client, but it guarantees they won’t be included in redirects toward the server. Returning tokens via browser redirects directly from the authorization endpoint. It also has the advantage of eliminating any requirements for cross origin calls, which are necessary if the JavaScript application is required to contact the token endpoint.

An important characteristic of the OAuth2 implicit grant is the fact that such flows never return refresh tokens to the client. The next section shows how this isn’t necessary and would in fact be a security issue.

Suitable scenarios for the OAuth2 implicit grant

The OAuth2 specification declares that the implicit grant has been devised to enable user-agent applications – that is to say, JavaScript applications executing within a browser. The defining characteristic of such applications is that JavaScript code is used for accessing server resources (typically a Web API) and for updating the application user experience accordingly. Think of applications like Gmail or Outlook Web Access: when you select a message from your inbox, only the message visualization panel changes to display the new selection, while the rest of the page remains unmodified. This characteristic is in contrast with traditional redirect-based Web apps, where every user interaction results in a full page postback and a full page rendering of the new server response.

Applications that take the JavaScript based approach to its extreme are called single-page applications, or SPAs. The idea is that these applications only serve an initial HTML page and associated JavaScript, with all subsequent interactions being driven by WebAPI calls performed via JavaScript. However, hybrid approaches, where the application is mostly postback-driven but performs occasional JS calls, are not uncommon – the discussion about implicit flow usage is relevant for those as well.

Redirect-based applications typically secure their requests via cookies, however, that approach does not work as well for JavaScript applications. Cookies only work against the domain they have been generated for, while JavaScript calls might be directed toward other domains. In fact, that will frequently be the case: think of applications invoking Microsoft Graph API, Office API, Azure API – all residing outside the domain from where the application is served. A growing trend for JavaScript applications is to have no backend at all, relying 100% on third party Web APIs to implement their business function.

Currently, the preferred method of protecting calls to a Web API is to use the OAuth2 bearer token approach, where every call is accompanied by an OAuth2 access token. The Web API examines the incoming access token and, if it finds in it the necessary scopes, it grants access to the requested operation. The implicit flow provides a convenient mechanism for JavaScript applications to obtain access tokens for a Web API, offering numerous advantages in respect to cookies:

  • Tokens can be reliably obtained without any need for cross origin calls – mandatory registration of the redirect URI to which tokens are return guarantees that tokens are not displaced
  • JavaScript applications can obtain as many access tokens as they need, for as many Web APIs they target – with no restriction on domains
  • HTML5 features like session or local storage grant full control over token caching and lifetime management, whereas cookies management is opaque to the app
  • Access tokens aren’t susceptible to Cross-site request forgery (CSRF) attacks

The implicit grant flow does not issue refresh tokens, mostly for security reasons. A refresh token isn’t as narrowly scoped as access tokens, granting far more power hence inflicting far more damage in case it is leaked out. In the implicit flow, tokens are deliveredin the URL, hence the risk of interception is higher than in the authorization code grant.

However, a JavaScript application has another mechanism at its disposal for renewing access tokens without repeatedly prompting the user for credentials. The application can use a hidden iframe to perform new token requests against the authorization endpointof Azure AD: as long as the browser still has an active session (read: has a session cookie) against the Azure AD domain, the authentication request can successfully occur without any need for user interaction.

This model grants the JavaScript application the ability to independently renew access tokens and even acquire new ones for a new API (provided that the user previously consented for them). This avoids the added burden of acquiring, maintaining, and protectinga high value artifact such as a refresh token. The artifact that makes the silent renewal possible, the Azure AD session cookie, is managed outside of the application. Another advantage of this approach is a user can sign out from Azure AD, using any of theapplications signed into Azure AD, running in any of the browser tabs. This results in the deletion of the Azure AD session cookie, and the JavaScript application will automatically lose the ability to renew tokens for the signed out user.

Is the implicit grant suitable for my app?

The implicit grant presents more risks than other grants. However, the higher risk profile is largely due to the fact that it is meant to enable applications that execute active code, served by a remote resource to a browser. If you are planning an SPA architecture,have no backend components or intend to invoke a Web API via JavaScript, use of the implicit flow for token acquisition is recommended.

If your application is a native client, the implicit flow isn’t a great fit. The absence of the Azure AD session cookie in the context of a native client deprives your application from the means of maintaining a long lived session. Which means your application willrepeatedly prompt the user when obtaining access tokens for new resources.

If you are developing a Web application that includes a backend, and consuming an API from its backend code, the implicit flow is also not a good fit. Other grants give you far more power. For example, the OAuth2 client credentials grant provides the ability toobtain tokens that reflect the permissions assigned to the application itself, as opposed to user delegations. This means the client has the ability to maintain programmatic access to resources even when a user is not actively engaged in a session, and so on. Notonly that, but such grants give higher security guarantees. For instance, access tokens never transit through the user browser, they don’t risk being saved in the browser history, and so on. The client application can also perform strong authentication whenrequesting a token.

Authorize access to Azure Active Directory web applications using the OAuth 2.0 code grant flow

Azure Active Directory (Azure AD) uses OAuth 2.0 to enable you to authorize access to web applications and web APIs in your Azure AD tenant. This guide is language independent, and describes how to send and receive HTTP messages without using any of ouropen-source libraries.

The OAuth 2.0 authorization code flow is described in section 4.1 of the OAuth 2.0 specification. It is used to perform authentication and authorization in most application types, including web apps and natively installed apps.

Register your application with your AD tenant

First, you need to register your application with your Azure Active Directory (Azure AD) tenant. This will give you an Application ID for your application, as well as enable it to receive tokens.

  • Sign in to the Azure portal.
  • Choose your Azure AD tenant by clicking on your account in the top right corner of the page, followed by clicking on the Switch Directory navigation and then select the appropriate tenant.
    • Skip this step, if you’ve only one Azure AD tenant under your account or if you’ve already selected the appropriate Azure AD tenant.
  • In the left hand navigation pane, click on Azure Active Directory.
  • Click on App Registrations and click on New application registration.
  • Follow the prompts and create a new application. It doesn’t matter if it is a web application or a native application for this tutorial.
    • For Web Applications, provide the Sign-On URL, which is the base URL of your app, where users can sign in e.g http://localhost:12345.
    • For Native Applications provide a Redirect URI, which Azure AD will use to return token responses. Enter a value specific to your application, .e.g http://MyFirstAADApp.
  • Once you’ve completed registration, Azure AD will assign your application a unique client identifier, the Application ID. You need this value in the next sections, so copy it from the application page.
  • To find your application in the Azure portal, click App registrations, and then click View all applications.

Request an authorization code

The authorization code flow begins with the client directing the user to the /authorize endpoint. In this request, the client indicates the permissions it needs to acquire from the user. You can get the OAuth 2.0 authorization endpoint for your tenant by selecting Appregistrations > Endpoints in the Azure portal.

// Line breaks for legibility only https://login.microsoftonline.com/{tenant}/oauth2/authorize? client_id=6731de76-14a6-49ae-97bc-6eba6914391e &response_type=code &redirect_uri=http%3A%2F%2Flocalhost%3A12345 &response_mode=query &resource=https%3A%2F%2Fservice.contoso.com%2F &state=12345

Parameter Need Description
tenant required The {tenant} value in the path of the request can be used to control who can signinto the application. The allowed values are tenant identifiers, for example,8eaef023-2b34-4da1-9baa-8bc8c9d6a490 orcontoso.onmicrosoft.com or common for tenant-independent tokens
client_id required The Application ID assigned to your app when you registered it with Azure AD. Youcan find this in the Azure Portal. Click Azure Active Directory in the servicessidebar, click App registrations, and choose the application.
response_type required Must include code for the authorization code flow.
redirect_uri recommended The redirect_uri of your app, where authentication responses can be sent andreceived by your app. It must exactly match one of the redirect_uris you registered inthe portal, except it must be url encoded. For native & mobile apps, you should usethe default value of urn:ietf:wg:oauth:2.0:oob.
response_mode optional Specifies the method that should be used to send the resulting token back to yourapp. Can be query, fragment, or form_post. query provides the code as aquery string parameter on your redirect URI. If you’re requesting an ID token usingthe implicit flow, you cannot use query as specified in the OpenID spec. If you’rerequesting just the code, you can use query, fragment, or form_post.form_post executes a POST containing the code to your redirect URI. Thedefault is query for a code flow.
state recommended A value included in the request that is also returned in the token response. Arandomly generated unique value is typically used for preventing cross-site requestforgery attacks. The state is also used to encode information about the user’s state inthe app before the authentication request occurred, such as the page or view theywere on.
resource recommended The App ID URI of the target web API (secured resource). To find the App ID URI,in the Azure Portal, click Azure Active Directory, click Application registrations,open the application’s Settings page, then click Properties. It may also be anexternal resource like https://graph.microsoft.com. This is required inone of either the authorization or token requests. To ensure fewer authenticationprompts place it in the authorization request to ensure consent is received from theuser.
scope ignored For v1 Azure AD apps, scopes must be statically configured in the Azure Portalunder the applications Settings, Required Permissions.
prompt optional Indicate the type of user interaction that is required.

Valid values are:

login: The user should be prompted to reauthenticate.

select_account: The user is prompted to select an account, interrupting single signon. The user may select an existing signed-in account, enter their credentials for aremembered account, or choose to use a different account altogether.

consent: User consent has been granted, but needs to be updated. The user shouldbe prompted to consent.

admin_consent: An administrator should be prompted to consent on behalf of allusers in their organization

login_hint optional Can be used to pre-fill the username/email address field of the sign-in page for theuser, if you know their username ahead of time. Often apps use this parameterduring reauthentication, having already extracted the username from a previoussign-in using the preferred_username claim.
domain_hint optional Provides a hint about the tenant or domain that the user should use to sign in. Thevalue of the domain_hint is a registered domain for the tenant. If the tenant isfederated to an on-premises directory, AAD redirects to the specified tenantfederation server.
code_challenge_method recommended The method used to encode the code_verifier for the code_challengeparameter. Can be one of plain or S256. If excluded, code_challenge isassumed to be plaintext if code_challenge is included. Azure AAD v1.0supports both plain and S256.
code_challenge recommended Used to secure authorization code grants via Proof Key for Code Exchange (PKCE)from a native or public client. Required if code_challenge_method isincluded.

Note: If the user is part of an organization, an administrator of the organization can consent or decline on the user’s behalf, or permit the user to consent. The user is given the option to consent only when the administrator permits it.

At this point, the user is asked to enter their credentials and consent to the permissions requested by the app in the Azure Portal. Once the user authenticates and grants consent, Azure AD sends a response to your app at the redirect_uri address in yourrequest with the code.

Successful response

A successful response could look like this:

GET HTTP/1.1 302 Found Location: http://localhost:12345/?code= AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrqqf_ZT_p5uEAEJJ_nZ3UmphWygRNy2C3jJ239gV_DBnZ2syeg95Ki-374WHUP-i3yIhv5i-7KU2CEoPXwURQp6IVYMw-DjAOzn7C3JCu5wpngXmbZKtJdWmiBzHpcO2aICJPu1KvJrDLDP20chJBXzVYJtkfjviLNNW7l7Y3ydcHDsBRKZc3GuMQanmcghXPyoDg41g8XbwPudVh7uCmUponBQpIhbuffFP_tbV8SNzsPoFz9CLpBCZagJVXeqWoYMPe2dSsPiLO9Alf_YIe5zpi-zY4C3aLw5g9at35eZTfNd0gBRpR5ojkMIcZZ6IgAA&session_state=7B29111D-C220-4263-99AB-6F6E135D75EF&state=D79E5777-702E-4260-9A62-37F75FF22CCE

Parameter Description
admin_consent The value is True if an administrator consented to a consent request prompt.
code The authorization code that the application requested. The application can use the authorization code to request an access tokenfor the target resource.
session_state A unique value that identifies the current user session. This value is a GUID, but should be treated as an opaque value that ispassed without examination.
state If a state parameter is included in the request, the same value should appear in the response. It’s a good practice for theapplication to verify that the state values in the request and response are identical before using the response. This helps to detectCross-Site Request Forgery (CSRF) attacks against the client.
Error response

Error responses may also be sent to the redirect_uri so that the application can handle them appropriately.

GET http://localhost:12345/? error=access_denied &error_description=the+user+canceled+the+authentication

Parameter Description
error An error code value defined in Section 5.2 of the OAuth 2.0 Authorization Framework. The next table describes the error codesthat Azure AD returns.
error_description A more detailed description of the error. This message is not intended to be end-user friendly.
state The state value is a randomly generated non-reused value that is sent in the request and returned in the response to preventcross-site request forgery (CSRF) attacks.
Error codes for authorization endpoint errors

The following table describes the various error codes that can be returned in the error parameter of the error response.

Error Code Description Client Action
invalid_request Protocol error, such as a missing required parameter. Fix and resubmit the request. This is a development error, and is typically caughtduring initial testing.
unauthorized_client The client application is not permitted to request an authorization code. This usually occurs when the client application is not registered in Azure AD or isnot added to the user’s Azure AD tenant. The application can prompt the user withinstruction for installing the application and adding it to Azure AD.
access_denied Resource owner denied consent The client application can notify the user that it cannot proceed unless the userconsents.
unsupported_response_type The authorization server does not support the response type in the request. Fix and resubmit the request. This is a development error, and is typically caughtduring initial testing.
server_error The server encountered an unexpected error. Retry the request. These errors can result from temporary conditions. The clientapplication might explain to the user that its response is delayed due to a temporaryerror.
temporarily_unavailable The server is temporarily too busy to handle the request. Retry the request. The client application might explain to the user that its response isdelayed due to a temporary condition.
invalid_resource The target resource is invalid because it does not exist, Azure AD cannot find it, or itis not correctly configured. This indicates the resource, if it exists, has not been configured in the tenant. Theapplication can prompt the user with instruction for installing the application andadding it to Azure AD.

Use the authorization code to request an access token

Now that you’ve acquired an authorization code and have been granted permission by the user, you can redeem the code for an access token to the desired resource, by sending a POST request to the /token endpoint:

// Line breaks for legibility only POST /{tenant}/oauth2/token HTTP/1.1 Host: https://login.microsoftonline.com Content-Type: application/x-www-form-urlencoded grant_type=authorization_code &client_id=2d4d11a2-f814-46a7-890a-274a72a7309e &code=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrqqf_ZT_p5uEAEJJ_nZ3UmphWygRNy2C3jJ239gV_DBnZ2syeg95Ki-374WHUP-i3yIhv5i-7KU2CEoPXwURQp6IVYMw-DjAOzn7C3JCu5wpngXmbZKtJdWmiBzHpcO2aICJPu1KvJrDLDP20chJBXzVYJtkfjviLNNW7l7Y3ydcHDsBRKZc3GuMQanmcghXPyoDg41g8XbwPudVh7uCmUponBQpIhbuffFP_tbV8SNzsPoFz9CLpBCZagJVXeqWoYMPe2dSsPiLO9Alf_YIe5zpi-zY4C3aLw5g9at35eZTfNd0gBRpR5ojkMIcZZ6IgAA &redirect_uri=https%3A%2F%2Flocalhost%3A12345 &resource=https%3A%2F%2Fservice.contoso.com%2F &client_secret=p@ssw0rd //NOTE: client_secret only required for web apps

Parameter Description
tenant required The {tenant} value in the path of the request can be used to control who can signinto the application. The allowed values are tenant identifiers, for example,8eaef023-2b34-4da1-9baa-8bc8c9d6a490 orcontoso.onmicrosoft.com or common for tenant-independent tokens
client_id required The Application Id assigned to your app when you registered it with Azure AD. Youcan find this in the Azure portal. The Application Id is displayed in the settings ofthe app registration.
grant_type required Must be authorization_code for the authorization code flow.
code required The authorization_code that you acquired in the previous section
redirect_uri required The same redirect_uri value that was used to acquire theauthorization_code.
client_secret required for web apps, not allowed for public clients The application secret that you created in the Azure Portal for your app under Keys.It cannot be used in a native app (public client), because client_secrets cannot bereliably stored on devices. It is required for web apps and web APIs (all confidentialclients), which have the ability to store the client_secret securely on theserver side. The client_secret should be URL-encoded before being sent.
resource recommended The App ID URI of the target web API (secured resource). To find the App ID URI,in the Azure Portal, click Azure Active Directory, click Application registrations,open the application’s Settings page, then click Properties. It may also be anexternal resource like https://graph.microsoft.com. This is required inone of either the authorization or token requests. To ensure fewer authenticationprompts place it in the authorization request to ensure consent is received from theuser. If in both the authorization request and the token request, the resource`parameters must match.
code_verifier optional The same code_verifier that was used to obtain the authorization_code. Required ifPKCE was used in the authorization code grant request.

To find the App ID URI, in the Azure Portal, click Azure Active Directory, click Application registrations, open the application’s Settings page, then click Properties.

Successful response

Azure AD returns an access token upon a successful response. To minimize network calls from the client application and their associated latency, the client application should cache access tokens for the token lifetime that is specified in the OAuth 2.0 response. Todetermine the token lifetime, use either the expires_in or expires_on parameter values.

If a web API resource returns an invalid_token error code, this might indicate that the resource has determined that the token is expired. If the client and resource clock times are different (known as a “time skew”), the resource might consider the token to beexpired before the token is cleared from the client cache. If this occurs, clear the token from the cache, even if it is still within its calculated lifetime.

A successful response could look like this:

{ "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1THdqcHdBSk9NOW4tQSJ9.eyJhdWQiOiJodHRwczovL3NlcnZpY2UuY29udG9zby5jb20vIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvN2ZlODE0NDctZGE1Ny00Mzg1LWJlY2ItNmRlNTdmMjE0NzdlLyIsImlhdCI6MTM4ODQ0MDg2MywibmJmIjoxMzg4NDQwODYzLCJleHAiOjEzODg0NDQ3NjMsInZlciI6IjEuMCIsInRpZCI6IjdmZTgxNDQ3LWRhNTctNDM4NS1iZWNiLTZkZTU3ZjIxNDc3ZSIsIm9pZCI6IjY4Mzg5YWUyLTYyZmEtNGIxOC05MWZlLTUzZGQxMDlkNzRmNSIsInVwbiI6ImZyYW5rbUBjb250b3NvLmNvbSIsInVuaXF1ZV9uYW1lIjoiZnJhbmttQGNvbnRvc28uY29tIiwic3ViIjoiZGVOcUlqOUlPRTlQV0pXYkhzZnRYdDJFYWJQVmwwQ2o4UUFtZWZSTFY5OCIsImZhbWlseV9uYW1lIjoiTWlsbGVyIiwiZ2l2ZW5fbmFtZSI6IkZyYW5rIiwiYXBwaWQiOiIyZDRkMTFhMi1mODE0LTQ2YTctODkwYS0yNzRhNzJhNzMwOWUiLCJhcHBpZGFjciI6IjAiLCJzY3AiOiJ1c2VyX2ltcGVyc29uYXRpb24iLCJhY3IiOiIxIn0.JZw8jC0gptZxVC-7l5sFkdnJgP3_tRjeQEPgUn28XctVe3QqmheLZw7QVZDPCyGycDWBaqy7FLpSekET_BftDkewRhyHk9FW_KeEz0ch2c3i08NGNDbr6XYGVayNuSesYk5Aw_p3ICRlUV1bqEwk-Jkzs9EEkQg4hbefqJS6yS1HoV_2EsEhpd_wCQpxK89WPs3hLYZETRJtG5kvCCEOvSHXmDE6eTHGTnEgsIk--UlPe275Dvou4gEAwLofhLDQbMSjnlV5VLsjimNBVcSRFShoxmQwBJR_b2011Y5IuD6St5zPnzruBbZYkGNurQK63TJPWmRd3mbJsGM0mf3CUQ", "token_type": "Bearer", "expires_in": "3600", "expires_on": "1388444763", "resource": "https://service.contoso.com/", "refresh_token": "AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4rTfgV29ghDOHRc2B-C_hHeJaJICqjZ3mY2b_YNqmf9SoAylD1PycGCB90xzZeEDg6oBzOIPfYsbDWNf621pKo2Q3GGTHYlmNfwoc-OlrxK69hkha2CF12azM_NYhgO668yfcUl4VBbiSHZyd1NVZG5QTIOcbObu3qnLutbpadZGAxqjIbMkQ2bQS09fTrjMBtDE3D6kSMIodpCecoANon9b0LATkpitimVCrl-NyfN3oyG4ZCWu18M9-vEou4Sq-1oMDzExgAf61noxzkNiaTecM-Ve5cq6wHqYQjfV9DOz4lbceuYCAA", "scope": "https%3A%2F%2Fgraph.microsoft.com%2Fmail.read", "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIyZDRkMTFhMi1mODE0LTQ2YTctODkwYS0yNzRhNzJhNzMwOWUiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83ZmU4MTQ0Ny1kYTU3LTQzODUtYmVjYi02ZGU1N2YyMTQ3N2UvIiwiaWF0IjoxMzg4NDQwODYzLCJuYmYiOjEzODg0NDA4NjMsImV4cCI6MTM4ODQ0NDc2MywidmVyIjoiMS4wIiwidGlkIjoiN2ZlODE0NDctZGE1Ny00Mzg1LWJlY2ItNmRlNTdmMjE0NzdlIiwib2lkIjoiNjgzODlhZTItNjJmYS00YjE4LTkxZmUtNTNkZDEwOWQ3NGY1IiwidXBuIjoiZnJhbmttQGNvbnRvc28uY29tIiwidW5pcXVlX25hbWUiOiJmcmFua21AY29udG9zby5jb20iLCJzdWIiOiJKV3ZZZENXUGhobHBTMVpzZjd5WVV4U2hVd3RVbTV5elBtd18talgzZkhZIiwiZmFtaWx5X25hbWUiOiJNaWxsZXIiLCJnaXZlbl9uYW1lIjoiRnJhbmsifQ." }
Parameter Description
access_token The requested access token as a signed JSON Web Token (JWT). The app can use this token to authenticate to the securedresource, such as a web API.
token_type Indicates the token type value. The only type that Azure AD supports is Bearer.
expires_in How long the access token is valid (in seconds).
expires_on The time when the access token expires. The date is represented as the number of seconds from 1970-01-01T0:0:0Z UTC untilthe expiration time. This value is used to determine the lifetime of cached tokens.
resource The App ID URI of the web API (secured resource).
scope Impersonation permissions granted to the client application. The default permission is user_impersonation. The ownerof the secured resource can register additional values in Azure AD.
refresh_token An OAuth 2.0 refresh token. The app can use this token to acquire additional access tokens after the current access tokenexpires. Refresh tokens are long-lived, and can be used to retain access to resources for extended periods of time.
id_token An unsigned JSON Web Token (JWT) representing an ID token. The app can base64Url decode the segments of this token torequest information about the user who signed in. The app can cache the values and display them, but it should not rely on themfor any authorization or security boundaries.
Error response

The token issuance endpoint errors are HTTP error codes, because the client calls the token issuance endpoint directly. In addition to the HTTP status code, the Azure AD token issuance endpoint also returns a JSON document with objects that describe the error.

A sample error response could look like this:

{ "error": "invalid_grant", "error_description": "AADSTS70002: Error validating credentials. AADSTS70008: The provided authorization code or refresh token is expired. Send a new interactive authorization request for this user and resource.\r\nTrace ID: 3939d04c-d7ba-42bf-9cb7-1e5854cdce9e\r\nCorrelation ID: a8125194-2dc8-4078-90ba-7b6592a7f231\r\nTimestamp: 2016-04-11 18:00:12Z", "error_codes": [ 70002, 70008 ], "timestamp": "2016-04-11 18:00:12Z", "trace_id": "3939d04c-d7ba-42bf-9cb7-1e5854cdce9e", "correlation_id": "a8125194-2dc8-4078-90ba-7b6592a7f231" }
Parameter Description
error An error code string that can be used to classify types of errors that occur, and can be used to react to errors.
error_description A specific error message that can help a developer identify the root cause of an authentication error.
error_codes A list of STS-specific error codes that can help in diagnostics.
timestamp The time at which the error occurred.
trace_id A unique identifier for the request that can help in diagnostics.
correlation_id A unique identifier for the request that can help in diagnostics across components.
Error codes for token endpoint errors
Error Code Description Client Action
invalid_request Protocol error, such as a missing required parameter. Fix and resubmit the request
invalid_grant The authorization code is invalid or has expired. Try a new request to the /authorize endpoint
unauthorized_client The authenticated client is not authorized to use this authorization grant type. This usually occurs when the client application is not registered in Azure AD or isnot added to the user’s Azure AD tenant. The application can prompt the user withinstruction for installing the application and adding it to Azure AD.
invalid_client Client authentication failed. The client credentials are not valid. To fix, the application administrator updates thecredentials.
unsupported_grant_type The authorization server does not support the authorization grant type. Change the grant type in the request. This type of error should occur only duringdevelopment and be detected during initial testing.
invalid_resource The target resource is invalid because it does not exist, Azure AD cannot find it, or itis not correctly configured. This indicates the resource, if it exists, has not been configured in the tenant. Theapplication can prompt the user with instruction for installing the application andadding it to Azure AD.
interaction_required The request requires user interaction. For example, an additional authenticationstep is required. Instead of a non-interactive request, retry with an interactive authorization requestfor the same resource.
temporarily_unavailable The server is temporarily too busy to handle the request. Retry the request. The client application might explain to the user that its response isdelayed due to a temporary condition.

Use the access token to access the resource

Now that you’ve successfully acquired an access_token, you can use the token in requests to Web APIs, by including it in the Authorization header.

Sample request
GET /data HTTP/1.1 Host: service.contoso.com Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1THdqcHdBSk9NOW4tQSJ9.eyJhdWQiOiJodHRwczovL3NlcnZpY2UuY29udG9zby5jb20vIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvN2ZlODE0NDctZGE1Ny00Mzg1LWJlY2ItNmRlNTdmMjE0NzdlLyIsImlhdCI6MTM4ODQ0MDg2MywibmJmIjoxMzg4NDQwODYzLCJleHAiOjEzODg0NDQ3NjMsInZlciI6IjEuMCIsInRpZCI6IjdmZTgxNDQ3LWRhNTctNDM4NS1iZWNiLTZkZTU3ZjIxNDc3ZSIsIm9pZCI6IjY4Mzg5YWUyLTYyZmEtNGIxOC05MWZlLTUzZGQxMDlkNzRmNSIsInVwbiI6ImZyYW5rbUBjb250b3NvLmNvbSIsInVuaXF1ZV9uYW1lIjoiZnJhbmttQGNvbnRvc28uY29tIiwic3ViIjoiZGVOcUlqOUlPRTlQV0pXYkhzZnRYdDJFYWJQVmwwQ2o4UUFtZWZSTFY5OCIsImZhbWlseV9uYW1lIjoiTWlsbGVyIiwiZ2l2ZW5fbmFtZSI6IkZyYW5rIiwiYXBwaWQiOiIyZDRkMTFhMi1mODE0LTQ2YTctODkwYS0yNzRhNzJhNzMwOWUiLCJhcHBpZGFjciI6IjAiLCJzY3AiOiJ1c2VyX2ltcGVyc29uYXRpb24iLCJhY3IiOiIxIn0.JZw8jC0gptZxVC-7l5sFkdnJgP3_tRjeQEPgUn28XctVe3QqmheLZw7QVZDPCyGycDWBaqy7FLpSekET_BftDkewRhyHk9FW_KeEz0ch2c3i08NGNDbr6XYGVayNuSesYk5Aw_p3ICRlUV1bqEwk-Jkzs9EEkQg4hbefqJS6yS1HoV_2EsEhpd_wCQpxK89WPs3hLYZETRJtG5kvCCEOvSHXmDE6eTHGTnEgsIk--UlPe275Dvou4gEAwLofhLDQbMSjnlV5VLsjimNBVcSRFShoxmQwBJR_b2011Y5IuD6St5zPnzruBbZYkGNurQK63TJPWmRd3mbJsGM0mf3CUQ
Error Response

Secured resources that implement RFC 6750 issue HTTP status codes. If the request does not include authentication credentials or is missing the token, the response includes an WWW-Authenticate header. When a request fails, the resource server respondswith the HTTP status code and an error code.

The following is an example of an unsuccessful response when the client request does not include the bearer token:

HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer authorization_uri="https://login.microsoftonline.com/contoso.com/oauth2/authorize", error="invalid_token", error_description="The access token is missing.",
Parameter Description
authorization_uri The URI (physical endpoint) of the authorization server. This value is also used as a lookup key to get more information aboutthe server from a discovery endpoint.

The client must validate that the authorization server is trusted. When the resource is protected by Azure AD, it is sufficient toverify that the URL begins with https://login.microsoftonline.com or another hostname that Azure AD supports.A tenant-specific resource should always return a tenant-specific authorization URI.

error An error code value defined in Section 5.2 of the OAuth 2.0 Authorization Framework.
error_description A more detailed description of the error. This message is not intended to be end-user friendly.
resource_id Returns the unique identifier of the resource. The client application can use this identifier as the value of the resourceparameter when it requests a token for the resource.

It is important for the client application to verify this value, otherwise a malicious service might be able to induce an elevation-of-privileges attack.

The recommended strategy for preventing an attack is to verify that the resource_id matches the base of the web API URLthat being accessed. For example, if https://service.contoso.com/data is being accessed, the resource_idcan be htttps://service.contoso.com/. The client application must reject a resource_id that does not begin with thebase URL unless there is a reliable alternate way to verify the id.

Refreshing the access tokens

Access Tokens are short-lived and must be refreshed after they expire to continue accessing resources. You can refresh the access_token by submitting another POST request to the /token endpoint, but this time providing the refresh_token instead of the code.Refresh tokens are valid for all resources that your client has already been given consent to access – thus, a refresh token issued on a request for resource=https://graph.microsoft.com can be used to request a new access token forresource=https://contoso.com/api.

Refresh tokens do not have specified lifetimes. Typically, the lifetimes of refresh tokens are relatively long. However, in some cases, refresh tokens expire, are revoked, or lack sufficient privileges for the desired action. Your application needs to expect and handleerrors returned by the token issuance endpoint correctly.

When you receive a response with a refresh token error, discard the current refresh token and request a new authorization code or access token. In particular, when using a refresh token in the Authorization Code Grant flow, if you receive a response with theinteraction_required or invalid_grant error codes, discard the refresh token and request a new authorization code.

A sample request to the tenant-specific endpoint (you can also use the common endpoint) to get a new access token using a refresh token looks like this:

// Line breaks for legibility only POST /{tenant}/oauth2/token HTTP/1.1 Host: https://login.microsoftonline.com Content-Type: application/x-www-form-urlencoded client_id=6731de76-14a6-49ae-97bc-6eba6914391e &refresh_token=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1aXxUjq... &grant_type=refresh_token &resource=https%3A%2F%2Fservice.contoso.com%2F &client_secret=JqQX2PNo9bpM0uEihUPzyrh // NOTE: Only required for web apps
Successful response

A successful token response will look like:

{ "token_type": "Bearer", "expires_in": "3600", "expires_on": "1460404526", "resource": "https://service.contoso.com/", "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1THdqcHdBSk9NOW4tQSJ9.eyJhdWQiOiJodHRwczovL3NlcnZpY2UuY29udG9zby5jb20vIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvN2ZlODE0NDctZGE1Ny00Mzg1LWJlY2ItNmRlNTdmMjE0NzdlLyIsImlhdCI6MTM4ODQ0MDg2MywibmJmIjoxMzg4NDQwODYzLCJleHAiOjEzODg0NDQ3NjMsInZlciI6IjEuMCIsInRpZCI6IjdmZTgxNDQ3LWRhNTctNDM4NS1iZWNiLTZkZTU3ZjIxNDc3ZSIsIm9pZCI6IjY4Mzg5YWUyLTYyZmEtNGIxOC05MWZlLTUzZGQxMDlkNzRmNSIsInVwbiI6ImZyYW5rbUBjb250b3NvLmNvbSIsInVuaXF1ZV9uYW1lIjoiZnJhbmttQGNvbnRvc28uY29tIiwic3ViIjoiZGVOcUlqOUlPRTlQV0pXYkhzZnRYdDJFYWJQVmwwQ2o4UUFtZWZSTFY5OCIsImZhbWlseV9uYW1lIjoiTWlsbGVyIiwiZ2l2ZW5fbmFtZSI6IkZyYW5rIiwiYXBwaWQiOiIyZDRkMTFhMi1mODE0LTQ2YTctODkwYS0yNzRhNzJhNzMwOWUiLCJhcHBpZGFjciI6IjAiLCJzY3AiOiJ1c2VyX2ltcGVyc29uYXRpb24iLCJhY3IiOiIxIn0.JZw8jC0gptZxVC-7l5sFkdnJgP3_tRjeQEPgUn28XctVe3QqmheLZw7QVZDPCyGycDWBaqy7FLpSekET_BftDkewRhyHk9FW_KeEz0ch2c3i08NGNDbr6XYGVayNuSesYk5Aw_p3ICRlUV1bqEwk-Jkzs9EEkQg4hbefqJS6yS1HoV_2EsEhpd_wCQpxK89WPs3hLYZETRJtG5kvCCEOvSHXmDE6eTHGTnEgsIk--UlPe275Dvou4gEAwLofhLDQbMSjnlV5VLsjimNBVcSRFShoxmQwBJR_b2011Y5IuD6St5zPnzruBbZYkGNurQK63TJPWmRd3mbJsGM0mf3CUQ", "refresh_token": "AwABAAAAv YNqmf9SoAylD1PycGCB90xzZeEDg6oBzOIPfYsbDWNf621pKo2Q3GGTHYlmNfwoc-OlrxK69hkha2CF12azM_NYhgO668yfcUl4VBbiSHZyd1NVZG5QTIOcbObu3qnLutbpadZGAxqjIbMkQ2bQS09fTrjMBtDE3D6kSMIodpCecoANon9b0LATkpitimVCrl PM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4rTfgV29ghDOHRc2B-C_hHeJaJICqjZ3mY2b_YNqmf9SoAylD1PycGCB90xzZeEDg6oBzOIPfYsbDWNf621pKo2Q3GGTHYlmNfwoc-OlrxK69hkha2CF12azM_NYhgO668yfmVCrl-NyfN3oyG4ZCWu18M9-vEou4Sq-1oMDzExgAf61noxzkNiaTecM-Ve5cq6wHqYQjfV9DOz4lbceuYCAA" }
Parameter Description
token_type The token type. The only supported value is bearer.
expires_in The remaining lifetime of the token in seconds. A typical value is 3600 (one hour).
expires_on The date and time on which the token expires. The date is represented as the number of seconds from 1970-01-01T0:0:0Z UTCuntil the expiration time.
resource Identifies the secured resource that the access token can be used to access.
scope Impersonation permissions granted to the native client application. The default permission is user_impersonation. The owner ofthe target resource can register alternate values in Azure AD.
access_token The new access token that was requested.
refresh_token A new OAuth 2.0 refresh_token that can be used to request new access tokens when the one in this response expires.
Error response

A sample error response could look like this:

{ "error": "invalid_resource", "error_description": "AADSTS50001: The application named https://foo.microsoft.com/mail.read was not found in the tenant named 295e01fc-0c56-4ac3-ac57-5d0ed568f872. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant.\r\nTrace ID: ef1f89f6-a14f-49de-9868-61bd4072f0a9\r\nCorrelation ID: b6908274-2c58-4e91-aea9-1f6b9c99347c\r\nTimestamp: 2016-04-11 18:59:01Z", "error_codes": [ 50001 ], "timestamp": "2016-04-11 18:59:01Z", "trace_id": "ef1f89f6-a14f-49de-9868-61bd4072f0a9", "correlation_id": "b6908274-2c58-4e91-aea9-1f6b9c99347c" }
Parameter Description
error An error code string that can be used to classify types of errors that occur, and can be used to react to errors.
error_description A specific error message that can help a developer identify the root cause of an authentication error.
error_codes A list of STS-specific error codes that can help in diagnostics.
timestamp The time at which the error occurred.
trace_id A unique identifier for the request that can help in diagnostics.
correlation_id A unique identifier for the request that can help in diagnostics across components.

Service to service calls using client credentials

The OAuth 2.0 Client Credentials Grant Flow permits a web service (confidential client) to use its own credentials instead of impersonating a user, to authenticate when calling another web service. In this scenario, the client is typically a middle-tier web service,a daemon service, or web site. For a higher level of assurance, Azure AD also allows the calling service to use a certificate (instead of a shared secret) as a credential.

Client credentials grant flow diagram

The following diagram explains how the client credentials grant flow works in Azure Active Directory (Azure AD).

  1. The client application authenticates to the Azure AD token issuance endpoint and requests an access token.
  2. The Azure AD token issuance endpoint issues the access token.
  3. The access token is used to authenticate to the secured resource.
  4. Data from the secured resource is returned to the client application.

Register the Services in Azure AD

Register both the calling service and the receiving service in Azure Active Directory (Azure AD). For detailed instructions, see Integrating applications with Azure Active Directory.

Request an Access Token

To request an access token, use an HTTP POST to the tenant-specific Azure AD endpoint.

https://login.microsoftonline.com/<tenant id>/oauth2/token

Service-to-service access token request

There are two cases depending on whether the client application chooses to be secured by a shared secret, or a certificate.

First case: Access token request with a shared secret

When using a shared secret, a service-to-service access token request contains the following parameters:

Parameter Description
grant_type required Specifies the requested grant type. In a Client Credentials Grant flow, the value mustbe client_credentials.
client_id required Specifies the Azure AD client id of the calling web service. To find the callingapplication’s client ID, in the Azure portal, click Azure Active Directory, click Appregistrations, click the application. The client_id is the Application ID.
client_secret required Enter a key registered for the calling web service or daemon application in AzureAD. To create a key, in the Azure portal, click Azure Active Directory, click Appregistrations, click the application, click Settings, click Keys, and add a Key. URL-encode this secret when providing it.
resource required Enter the App ID URI of the receiving web service. To find the App ID URI, in theAzure portal, click Azure Active Directory, click App registrations, click the serviceapplication, and then click Settings and Properties.
Example

The following HTTP POST requests an access token for the https://service.contoso.com/ web service. The client_id identifies the web service that requests the access token.

POST /contoso.com/oauth2/token HTTP/1.1 Host: login.microsoftonline.com Content-Type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=625bc9f6-3bf6-4b6d-94ba-e97cf07a22de&client_secret=qkDwDJlDfig2IpeuUZYKH1Wb8q1V0ju6sILxQQqhJ+s=&resource=https%3A%2F%2Fservice.contoso.com%2F

Second case: Access token request with a certificate

A service-to-service access token request with a certificate contains the following parameters:

Parameter Description
grant_type required Specifies the requested response type. In a Client Credentials Grant flow, the valuemust be client_credentials.
client_id required Specifies the Azure AD client id of the calling web service. To find the callingapplication’s client ID, in the Azure portal, click Azure Active Directory, click Appregistrations, click the application. The client_id is the Application ID.
client_assertion_type required The value must be urn:ietf:params:oauth:client-assertion-type:jwt-bearer
client_assertion required An assertion (a JSON Web Token) that you need to create and sign with thecertificate you registered as credentials for your application. Read about certificate credentials to learn how to register your certificate and the format of the assertion.
resource required Enter the App ID URI of the receiving web service. To find the App ID URI, in theAzure portal, click Azure Active Directory, click App registrations, click the serviceapplication, and then click Settings and Properties.

Notice that the parameters are almost the same as in the case of the request by shared secret except that the client_secret parameter is replaced by two parameters: a client_assertion_type and client_assertion.

Example

The following HTTP POST requests an access token for the https://service.contoso.com/ web service with a certificate. The client_id identifies the web service that requests the access token.

POST /<tenant_id>/oauth2/token HTTP/1.1 Host: login.microsoftonline.com Content-Type: application/x-www-form-urlencoded resource=https%3A%2F%contoso.onmicrosoft.com%2Ffc7664b4-cdd6-43e1-9365-c2e1c4e1b3bf&client_id=97e0a5b7-d745-40b6-94fe-5f77d35c6e05&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJhbGciOiJSUzI1NiIsIng1dCI6Imd4OHRHeXN5amNScUtqRlBuZDdSRnd2d1pJMCJ9.eyJ{a lot of characters here}M8U3bSUKKJDEg&grant_type=client_credentials
Service-to-Service Access Token Response

A success response contains a JSON OAuth 2.0 response with the following parameters:

Parameter Description
access_token The requested access token. The calling web service can use this token to authenticate to the receiving web service.
token_type Indicates the token type value. The only type that Azure AD supports is Bearer. For more information about bearer tokens, seeThe OAuth 2.0 Authorization Framework: Bearer Token Usage (RFC 6750).
expires_in How long the access token is valid (in seconds).
expires_on The time when the access token expires. The date is represented as the number of seconds from 1970-01-01T0:0:0Z UTC untilthe expiration time. This value is used to determine the lifetime of cached tokens.
not_before The time from which the access token becomes usable. The date is represented as the number of seconds from 1970-01-01T0:0:0Z UTC until time of validity for the token.
resource The App ID URI of the receiving web service.
Example of response

The following example shows a success response to a request for an access token to a web service.

{ "access_token":"eyJhbGciOiJSUzI1NiIsIng1dCI6IjdkRC1nZWNOZ1gxWmY3R0xrT3ZwT0IyZGNWQSIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJodHRwczovL3NlcnZpY2UuY29udG9zby5jb20vIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvN2ZlODE0NDctZGE1Ny00Mzg1LWJlY2ItNmRlNTdmMjE0NzdlLyIsImlhdCI6MTM4ODQ0ODI2NywibmJmIjoxMzg4NDQ4MjY3LCJleHAiOjEzODg0NTIxNjcsInZlciI6IjEuMCIsInRpZCI6IjdmZTgxNDQ3LWRhNTctNDM4NS1iZWNiLTZkZTU3ZjIxNDc3ZSIsIm9pZCI6ImE5OTE5MTYyLTkyMTctNDlkYS1hZTIyLWYxMTM3YzI1Y2RlYSIsInN1YiI6ImE5OTE5MTYyLTkyMTctNDlkYS1hZTIyLWYxMTM3YzI1Y2RlYSIsImlkcCI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0LzdmZTgxNDQ3LWRhNTctNDM4NS1iZWNiLTZkZTU3ZjIxNDc3ZS8iLCJhcHBpZCI6ImQxN2QxNWJjLWM1NzYtNDFlNS05MjdmLWRiNWYzMGRkNThmMSIsImFwcGlkYWNyIjoiMSJ9.aqtfJ7G37CpKV901Vm9sGiQhde0WMg6luYJR4wuNR2ffaQsVPPpKirM5rbc6o5CmW1OtmaAIdwDcL6i9ZT9ooIIicSRrjCYMYWHX08ip-tj-uWUihGztI02xKdWiycItpWiHxapQm0a8Ti1CWRjJghORC1B1-fah_yWx6Cjuf4QE8xJcu-ZHX0pVZNPX22PHYV5Km-vPTq2HtIqdboKyZy3Y4y3geOrRIFElZYoqjqSv5q9Jgtj5ERsNQIjefpyxW3EwPtFqMcDm4ebiAEpoEWRN4QYOMxnC9OUBeG9oLA0lTfmhgHLAtvJogJcYFzwngTsVo6HznsvPWy7UP3MINA", "token_type":"Bearer", "expires_in":"3599", "expires_on":"1388452167", "resource":"https://service.contoso.com/" }