OAuth 2.0 with Microsoft: Start Here
.png)
Introduction
This article provides all the essential information you need to:
- Understand key OAuth terminology (plus a bonus glossary at the bottom of the page)
- Properly implement and secure OAuth
- Build a solid foundation for security researchers examining OAuth
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.
Why Use OAuth?
OAuth is an industry-standard protocol with two primary use cases:
OAuth for Resource Access
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.
OAuth for Authentication
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.
OAuth Flow: From Start to Finish
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.
1. Vendor Registers Their Application
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:
- Display Name: A name for the app.
- Audience: Defines whether the app will be used by organizations, private users, or other specified groups.
- Permissions: A list of permissions the app requires from users.
- Redirect URI: The URI to which users will be redirected after authentication.
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").

2. App Specifies the Registered App ID
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:
- The app sends an authentication request to Microsoft, specifying the App ID (Client ID) along with additional parameters (to be discussed later).
- A new window appears under the Microsoft domain, asking the user to sign in to their account.
3. User Consent on First Use
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.
4. App Receives Permissions
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.
OAuth in More Detail
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.
Sign-In Audience: Organizations vs. Private Accounts
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:
- Private Accounts
- Organizations
- Both Private Accounts and Organizations
- Only accounts in the home tenant (the tenant where the app was first registered)
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.
Permissions
The type of Sign-In Audience directly influences the permissions available to the app (source here).
- Private Accounts: Apps supporting private accounts can request up to 30 permissions.
- Organizations: Apps supporting organizational accounts can request up to 400 permissions.
Additionally, different audiences provide access to different permission sets:
- Both Private Accounts and Organizations share permissions for common resources, such as: User Profile, Calendar, Contacts, Files, Mailbox, Notes, Notifications, Tasks…
- However, only Organizations have access to permissions for more business-specific services, including: Groups, Microsoft Teams, Security, Backup, Audit Logs…
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.
Service Principals
For Organizations:
- The first time a user consents to an app, a Service Principal is created in the tenant. This happens only once per tenant (E.g for the next user in that same tenant to consent the app will make use of the existing Service Principal).
- The Service Principal represents the application instance within the tenant and is used for authentication and authorization.
- This identity is managed by the organization through Entra ID and is used to enforce security and access control (note: Service Principals incur no additional charges).
A list of Service Principals in your organization is available in the Entra Admin Center under “Enterprise Applications”, See here.
For Private Accounts:
- No Service Principals are created since these accounts are not associated with a specific organization and no tenant is created for them.
Scopes and User Consent
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:
- Focus on the "Delegated" access column on the right, which refers to user-specific permissions. Meaning - the application will only be able to access the resources accessible to the user as well. This contrasts with "Application" access, which grants broader permissions to access organization-wide resources and is irrelevant to our OAuth scope discussion.
- For each permission, this list also specifies whether it is also available for personal accounts (for the above example look at the sentence at the bottom).
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.
Security Considerations
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.
Access Duration and “Offline Access”
Access Token
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.
Refresh Token
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.
- Single Page Apps (SPA): Refresh Tokens are valid for 24 hours.
- Other Scenarios: Refresh Tokens are valid for up to 90 days.
- After each use, the app receives a new Refresh Token along with a new Access Token.
- More details available here.
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).
Security Considerations
- Token Storage: Avoid storing tokens and other sensitive information in locations that are easily accessible to other code running on the same page. It’s essential that tokens are not accessible to third-party code, written to logs, or stored in browser history.
- Revocation:
- An Access Token cannot be revoked once issued.
- However, Refresh Tokens can be revoked if necessary. For more details on revoking Refresh Tokens, refer to here
Listing Apps with Granted Access and Revoking Permissions
To examine the apps that have been granted Delegated Access to your account:
For Private Accounts
- Log in to your Microsoft Account.
- In the left or top pane, click on "Privacy".
- Under "App Access", select the list of apps that have access to your account.
Review the list of apps, and for each app, click on “Details” to view the specific scopes and permissions granted.

For Organizations
- In the Entra Admin Center, navigate to the list of enterprise applications.
- The list will display an Application ID column (Client ID) and an Object ID column (also known as the Service Principal Object ID).
- Currently, there is no way to filter for Delegated Applications directly from this screen.
- To check the permissions granted to each app, click on an application, then click on the “Permissions” button in the left pane. This will list all granted scopes and you can verify whether they are delegated.
- You can also view the user who granted the permissions.

Using Azure CLI
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.
Silent Sign-In
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 user has previously consented to the app.
- The user is still logged in to Microsoft.
- A session cookie is available (note that this requires 3rd-party cookies to be enabled).
- The active session has a single user (multiple users would require an account picker interaction).
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.
Confidential vs. Public Clients
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.
- Confidential Clients: These are typically apps hosted on secure servers, where the secret can be safely stored. Such apps can maintain high security because the secret is kept protected on the server.
- Public Clients: Apps such as Single Page Apps (SPAs), mobile and desktop apps are considered Public Clients. They cannot securely store the app secret, and as a result are not allowed to use one.
The benefits of 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.
The HTTP request parameters
The MSAL library implements the following requests (and more) and it might be best to use their implementation, however now that you are familiar with the terms, scenarios, and variation in setups, it should be trivial for you to understand the implementation.
Token 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.
- HTTP Request URL - use the Token url corresponding to the Sign-In Audience
- For single tenant apps - specify the Tenant ID
- client_id (App ID) - the one issued to your app following its registration
- redirect_uri- should be one of the uris configured for the application during registration
- scope - space separated list of scopes
- grant_type - set to authorization_code
- code_verifier - the code verifier previously created by the client
- client_secret - Additional secrets may be used if app is considered confidential (E.g. hosted on a secured server)
Glossary
Recap of all discussed terms in the article.
We do newsletters, too
Discover tips, technical guides and best practices in our biweekly newsletter.