OAuth 2.0 with Microsoft: Start Here

How OAuth 2.0 works on Microsoft
Elad Luz

Elad Luz

Research Lead

Published on

April 10, 2025

Table of Contents

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.

Registration page from ENTRA Admin Center

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").

App Overview page from ENTRA Admin Center (taken from here)

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.

Consent example screenshot (taken from here)

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).

Registration page from ENTRA Admin Center

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.

Authority URL

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.

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

  1. Log in to your Microsoft Account.
  2. In the left or top pane, click on "Privacy".
  3. 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.

App Access Details Screen

For Organizations

  1. In the Entra Admin Center, navigate to the list of enterprise applications.
  2. The list will display an Application ID column (Client ID) and an Object ID column (also known as the Service Principal Object ID).
  3. Currently, there is no way to filter for Delegated Applications directly from this screen.
  4. 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.
  5. You can also view the user who granted the permissions.
Screenshot taken from a dummy tenant
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.

Implicit, Authorization (Explicit), and Hybrid Flows

OAuth supports different flows depending on your application’s implementation and security preferences.

Single-Page Web Apps (Public Client)

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 (Confidential Client)

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.

The Redirect URI

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.

Implicit Flow

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.

Authorization (Explicit) 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 Flow (OpenID Connect)

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.

Hybrid Flow (Authorization + OIDC)

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.

Security Considerations

For Single-Page Apps, the redirect introduces several security challenges:

  1. State Reset: The web app may need to reset its state or memory during the redirect, forcing it to store sensitive data in local storage or session storage (e.g., the code challenge in the Authorization flow). This exposes sensitive data to potential risks.

  2. Token Exposure: In the Implicit Flow, using URI fragments is less secure because the token is exposed in the browser’s history, referrer headers, and is visible to other JavaScript running on the same page.

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.

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.

Screenshot from here

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.

Authorize Request

All flows (Authorization, Implicit, Hybrid) must start with this request.

  • HTTP Request URL - use the Authority url corresponding to the Sign-In Audience
    • For single tenant apps - specify the Tenant ID
URL Audience
https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?<url args here> Organizations only
https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?<url args here> Private Accounts only
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?<url args here> Both Private and Organizations
https://login.microsoftonline.com/<Tenant ID here>/oauth2/v2.0/authorize?<url args here> Single Tenant
  • client_id (App ID) - the one issued to your app following its registration
  • response_type - what tokens the redirect uri returns
    • code for authorization code (Authorization Flow)
    • token for Access Token (Implicit Flow)
    • id_token for ID Token  (OIDC Flow, this can be specified together with code or token for hybrid flow)
  • redirect_uri - should be one of the uris configured for the application during registration
  • scope - space separated list of scopes from here
  • prompt - for silent login this should be set to none. Otherwise this parameter is optional.
  • For Authorization Flow, one should also specify those-
    • code_challenge_method - preferably to use s256
    • code_challenge -
      • The client generates a random code (aka “Code Verifier”)
      • The code challenge value is a SHA256 of the “Code Verifier”

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
URL Audience
https://login.microsoftonline.com/organizations/oauth2/v2.0/token?<url args here> Organizations only
https://login.microsoftonline.com/consumers/oauth2/v2.0/token?<url args here> Private Accounts only
https://login.microsoftonline.com/common/oauth2/v2.0/token?<url args here> Both Private and Organizations
https://login.microsoftonline.com/<Tenant ID here>/oauth2/v2.0/token?<url args here> Single Tenant

  • 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.

Term Definition
OIDC An authentication protocol built on top of OAuth 2.0 that allows applications to verify a user's identity and obtain basic profile information using tokens.
Delegated Access Delegated access allows an application to access a user's resources on their behalf, with the user's consent, without sharing their credentials.
Confidential Client An application that can securely store credentials, such as the application’s secret, and is typically used for server-side applications that require higher security in handling tokens.
Public Clientt An application that cannot securely store credentials, and is typically used for client-side applications like mobile or web apps, where the client code is exposed.
App ID / Client ID A unique identifier assigned to an application registered in the Microsoft Identity platform, specified in the authorization request made by the application.
Home Tenant The tenant where an application is originally registered.
Consent The process by which a user grants permission for an application to access their resources or perform actions on their behalf.
Confidential Client An application that cannot securely store credentials, and is typically used for client-side applications like mobile or web apps, where the client code is exposed.
Access Token A time-limited credential issued by an authorization server that allows an application to access a user's resources or perform actions on their behalf.
ID Token A token issued by an authorization server that contains user identity information.
Single Tenant App An application that is used within its home tenant only.
Multi Tenant App An application that can be used in multiple tenants.
Authority URL The HTTP endpoint where the authorization request is sent.
Service Principal An identity representing an application in a tenant, allowing the app to authenticate and interact with resources within that tenant.
OAuth Scope The specific permissions or actions an application is requesting access to on behalf of a user
Graph API A unified endpoint that allows developers to access a wide range of data and services within the Microsoft ecosystem.
Refresh Token A refresh token is a credential used by an application to obtain a new access token when the original access token expires, without requiring the user to reauthenticate.
Offline Access An OAuth Scope required to receive a Refresh Token.
MSAL Library A set of libraries provided by Microsoft that helps developers integrate authentication into their applications.
Implicit Flow An OAuth flow designed for client-side web applications, where the access token is directly returned to the client from the authorization server.
Authorization Flow A multi stage OAuth flow introducing enhanced security.
OIDC Flow An OAuth flow allowing applications to verify a user's identity and obtain basic profile information via ID Tokens.
Hybrid Flow An OAuth flow consisting of OIDC Flow and one of Implicit or Authorization Flow.
Redirect URI A web address to which an authorization server sends the user after they authenticate.
SPA Single Page Applications are web applications that load once and dynamically update content within a single page, using JavaScript to handle interactions and store data locally in the browser. This is unlike traditional web applications, which rely on backend servers to process logic and store data.
Silent Sign-In An authentication process where an application attempts to authenticate a user without requiring user interaction.
PKCEp An OAuth extension that enhances security by using a code verifier and code challenge to protect authorization code exchanges from interception.
Code Verifier A random string used in the Authorization flow to secure the exchange of an authorization code for an access token.
Code Challenge A hashed version of a code verifier.
More like this