How Entra ID issues and refreshes tokens
Follow an app through OAuth 2.0 sign-in: the authorisation code, access and refresh tokens, and what happens when they expire or are revoked.
The app sends the user to Entra ID
The app redirects the browser to Entra's authorise endpoint with its client ID, a redirect URI and the scopes it wants, such as User.Read. A redirect URI that doesn't match the app registration fails with AADSTS50011.
All the steps
The app redirects the browser to Entra's authorise endpoint with its client ID, a redirect URI and the scopes it wants, such as User.Read. A redirect URI that doesn't match the app registration fails with AADSTS50011.
Entra ID handles the sign-in, Conditional Access and, if needed, consent to the requested permissions. If consent is missing and users can't give it, you'll see AADSTS65001 or an admin approval request.
Entra ID sends the browser back to the redirect URI with a short-lived authorisation code. The code isn't a token: on its own it can't call any API.
The web app sends the code to the token endpoint along with its own credential: a certificate or secret, or a PKCE verifier for public clients. Each code can only be used once (AADSTS54005).
The ID token says who signed in. The access token is a JWT for Microsoft Graph, valid for about an hour by default. The refresh token lets the app get new access tokens without another sign-in.
The app sends the access token with each request. Graph checks the signature, the audience (aud) and the permissions in the scp or roles claim. Paste a token into the JWT decoder to see these claims.
When the access token expires, the app uses the refresh token to get a new one. Conditional Access is evaluated again at this point, so new or changed policies take effect without the user noticing.
If the user was disabled, their sessions were revoked, their password changed, or the refresh token went unused for too long, Entra ID rejects it (for example AADSTS50173 or AADSTS70008) and the user signs in again.