Elad Luz
Research Lead
Published on
April 10, 2025
This article provides all the essential information you need to:
While there is a wealth of online resources about Microsoft OAuth, primarily on Microsoft Docs and various forums, the information is often scattered across many pages and assumes familiarity with inconsistent terminology. This guide aims to provide a comprehensive overview of everything you need to know, which is why the article is long—it covers all the essential details to ensure a complete understanding of the topic.
After explaining the motivation for OAuth, we give a high level overview of the process. We then cover the essential parameters required for registering an app, including the Sign-In Audience, Redirect URI, and Permissions. We’ll also explore the relationship between Service Principals and these configurations. Key topics like Scopes and User Consent are discussed, alongside an explanation of the various tokens used in OAuth, including their validity periods. Additionally, the article examines the different authentication flows—such as Implicit, Authorization, and Hybrid flows—while also distinguishing between confidential and public clients.
The article ends with a detailed description of key OAuth HTTP requests and their parameters, and a glossary of all related terms.
OAuth is an industry-standard protocol with two primary use cases:
OAuth allows an application to access a user's resources hosted by another provider. This access is granted on behalf of the user and is referred to as delegated access.
For example, imagine you want to use a third-party web application that helps users schedule meetings. To do so, you would need to grant the app permission to integrate with your calendar (e.g., Google Calendar or O365 Calendar). This allows the app to view your upcoming events and schedule new ones on your behalf. Such integration is commonly implemented using OAuth.
In some cases, an application doesn't need to access the user's resources but simply needs to validate the user's identity (e.g., Single Sign-On, or SSO). In this scenario, OpenID Connect (OIDC), which is built on top of OAuth, is often used.
The Microsoft Identity Platform supports OAuth in various forms, allowing applications to authenticate users with Microsoft accounts and access their resources hosted on Microsoft services.
While this article focuses on OAuth with the Microsoft Identity Platform, it's worth noting that implementations with other providers follow a very similar process.
This section provides a high-level overview of how OAuth is set up and used for applications requiring access to a resource on behalf of a user.
The first step in the OAuth flow is for a vendor to register their application with Microsoft Entra ID. This process is relatively straightforward and requires the following information:
More on those later.
Once the app is registered, the vendor will receive an Application ID (also known as Client ID), which is linked to the vendor's tenant ID (referred to as the "Home Tenant").
The registered app is used by the vendor's web-app that is publicly accessible through their website.
When a user accesses the web app, they are prompted to sign in using a Microsoft Account. At this point:
On the first time a user interacts with the app, after successfully signing in, they will be prompted to consent to the app’s requested permissions. The app’s name and the required permissions will be displayed for the user’s review.
If the user has already previously consented to the requested permissions, the consent step is skipped.
After the user successfully signs in and consents to the requested permissions, the app receives an Access Token and possibly a Refresh Token. Those tokens contain the necessary permissions and allow the app to interact with Microsoft APIs on behalf of the user (Delegated Access) and maintain long-term access (more on this later).
If the application uses OAuth solely for user validation (e.g., Single Sign-On or SSO), instead of an access token, the app may receive an ID Token. This token contains information sufficient to validate the user and authenticate the session.
The previous section provided a high-level overview of the OAuth flow. In this section, we dive deeper into implementation details such as parameters, settings, information exchange, flow variations, and their associated security implications.
When registering an application, vendors are prompted to set the Application Audience. This decision determines who can authenticate with the app and how access is granted. The available audience options are:
If an app is restricted to the home tenant only, it is considered single-tenant. All other configurations are considered multi-tenant. (For more details, see here).
This decision impacts the permissions the app can request, the authentication URL and how Microsoft handles access control for the app.
The type of Sign-In Audience directly influences the permissions available to the app (source here).
Additionally, different audiences provide access to different permission sets:
If an app supports both Organizations and Private Accounts, it may need to adapt its implementation to handle differences. For example, both audiences offer Calendar permissions, but only Organizations provide the API to write to organization-specific shared calendars.
The Authority URL is the endpoint the app sends authentication requests to. This URL varies depending on the Sign-In Audience. See available options under Authorize Request.
For Organizations:
A list of Service Principals in your organization is available in the Entra Admin Center under “Enterprise Applications”, See here.
For Private Accounts:
In OAuth, Scopes define what access an application is granted, essentially they are a set of permissions.
This reference from Microsoft provides a list of all Microsoft Graph API Permissions. Most of the Scopes relate to the actions that an Access Token allows the app to perform with the Microsoft Graph API. Some OIDC (OpenID Connect) scopes—such as profile, email, and openid—relate to the metadata returned within the ID Token.
Consider the following scope, which grants an app read access to a user’s calendar:
If an app receives the Calendars.Read scope, it will be able to use the Access Token to interact with the Graph API and read a user’s calendar events.
Important Notes:
Here is another example-
An app that received the “Calendars.Read” scope will receive an “ID Token” that along with other information will also encapsulate the user’s email address.
The API reference also indicates whether an Admin Consent is required for a particular scope (look for the AdminConsentRequired). “By default, all users are allowed to consent to applications for permissions that don't require administrator consent” (quote from here)
An administrator can change when users are allowed to consent by going to the User Consent Settings on the Entra Admin Center and choosing one of the alternative settings.
It's important to note that the consent text may not always fully explain the implications of granting certain permissions. Users should always make sure they thoroughly understand what access they are granting before consenting to any application.
After the user provides consent or logs in, the web application receives an Access Token (if it has requested one). This token allows the app to make API requests on behalf of the user to access their resources. The permissions granted to the app are determined by the scopes approved by the user.
A Microsoft Access Token is typically valid for just over one hour, after which it expires.
If the requested scope includes offline_access, the app will also receive a Refresh Token. This token enables the app to obtain new Access Tokens after the previous ones expire. The Refresh Token ensures that the app can continue accessing the user's resources without requiring the user to log in again.
In the case of Confidential Clients, the Refresh Token may be granted a longer validity period, which contrasts with Public Clients (see the section on Confidential vs. Public Clients).
To examine the apps that have been granted Delegated Access to your account:
Review the list of apps, and for each app, click on “Details” to view the specific scopes and permissions granted.
Examining each application individually in the Entra Admin Center can be tedious. Alternatively, you may prefer to use the Azure CLI to review access by listing the Service Principals in the tenant.
Instructions for using the CLI can be found here.
OAuth supports different flows depending on your application’s implementation and security preferences.
Single-Page Apps (SPAs) typically store all of their logic in the browser, including the handling of sensitive tokens. This keeps the sensitive tokens from being stored on the vendor’s side. However, it also exposes the tokens to other components or third-party code running in the same browser or webpage.
Server-side apps, if implemented correctly, can store sensitive data more securely. However, storing offline access tokens for a large number of users in one location carries long-term security risks.
When implementing OAuth, the web app is typically hosted on a different origin than the external authorization service. For example, the web app might be hosted at https://myapp[.]com, while the external service (such as Microsoft) is hosted on a different domain.
The web app directs the user to an authentication page hosted by the external authorization service, usually in a new browser window. Once the user successfully authenticates, the external service needs to send the necessary tokens (Access Token, Authorization Code, or ID Token) back to the web app. However, because the external service resides on a different domain, the browser cannot send the tokens directly to the web app.
This is where the redirect URI comes into play. After successful authentication, the external service redirects the user's browser to the redirect URI specified by the web app in the original request. The redirect URI should match one of the pre-registered redirect URLs that the web app set up when the app was initially registered with the authorization service.
For Confidential Clients tokens are obtained by a backend server, while for Single-Page-Apps tokens are obtained by the code run at your browser.
In the Implicit Flow, the web app receives the Access Token directly from the authorization server via the redirect URI, either through URI fragments or HTML Form POST. This flow is typically used for client-side applications like Single-Page Apps.
Refresh tokens are unavailable for the Implicit Flow.
In the Authorization Flow, the web app first receives an Authorization Code at the redirect URI. The app then exchanges this code for an Access Token (and a Refresh Token if offline_access was requested) in a subsequent request. The Authorization Code is valid for 10 minutes and can only be used once (for more details, see here).
To ensure the security of the communication and prevent attacks like CSRF, the PKCE (Proof Key for Code Exchange) extension is used. In this process, the client first generates a random string known as the Code Verifier, hashes it, and sends the hashed value as the Code Challenge during the authorization request. In the subsequent token request, the client sends the original Code Verifier to prove that the request originated from the same source, ensuring the integrity of the exchange.
OIDC (OpenID Connect) is an authentication layer built on top of OAuth. It allows an app to validate the user and optionally receive their profile information, provided that the appropriate scopes are requested.
In this flow, the app receives an ID Token in the redirect. The ID Token is a base64-encoded JSON that contains user-related information and security metadata to validate the authenticator. For more details, refer to here.
The Hybrid Flow combines the Authorization Flow with OIDC. In this flow, the app can request both an ID Token and an Authorization Code to be returned with the redirect. This allows the app to authenticate the user and request access to their resources in a single flow.
For Single-Page Apps, the redirect introduces several security challenges:
Authorization Flow Security: The Authorization Flow is generally more secure because it prevents CSRF attacks and ensures that the data returned in the redirect is useless without the Authorization Code. This makes it more secure than the Implicit Flow.
When a user is already signed in to Microsoft and starts using apps that have previously received their consent, it wouldn't make sense for each app to require the user to sign in every time they are opened. Therefore, when requesting authentication, an app can attempt a Silent Sign-In, which does not require any user interaction. A Silent Sign-In is successful if all conditions are met:
The Silent Sign-In attempt can fail (silently as well) in which case the app can proceed to a Non-Silent Sign-In.
In a later part the article introduces the Authorize request where the “prompt” argument is used to tell whether to attempt a silent sign-in.
It’s important to distinguish a Silent Sign-In from the offline_access and refresh tokens. While Silent Sign-In allows for authentication without user interaction, refresh tokens provide continuous access to user resources by enabling the app to renew access tokens without requiring the user to log in again.
Refresh Tokens are unavailable to obtain by the Implicit Flow, however the Implicit Flow can attempt a Silent Sign-In.
When registering an app, vendors can configure an app secret that is sent during the second stage of the Authorization Flow. This occurs when the Authorization Code is exchanged for an Access Token. However, app secrets should only be used by Confidential Clients.
In addition to the enhanced security they provide, Confidential Clients are also provided with Refresh Tokens that last longer. Additionally, Refresh Tokens for Confidential Clients are not revoked when a user signs out of SSO (Single Sign-On).
In addition, notice the below statement from here which points out that Refresh Tokens for Public Clients (referred as SPA in the statement) expire after 24 hours.
More about confidential and public clients here.
with the terms, scenarios, and variation in setups, it should be trivial for you to understand the implementation.
All flows (Authorization, Implicit, Hybrid) must start with this request.
This 2nd step is required in the Authorization Flow to obtain the Access Token (and / or ID Token if OIDC and a Refresh Token if offline_access scope was requested) given a valid Authorization Code (Obtained in the Authorize Request)and Code Verifier.
Recap of all discussed terms in the article.