Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Register Microsoft Entra ID apps and configure OAuth 2.0 authentication with MSAL integration.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/oauth-flows.md
1# OAuth 2.0 Flows23This document provides an illustration of OAuth 2.0 authentication flows supported by Microsoft Entra ID.45**Note:** All the following implementation steps are for illustration purposes. It's always recommended to use a library to handle the authentication flow.67## Authorization Code Flow89### Flow Steps1011```121. User → App: Navigate to app's web UI132. App → User: Redirect to Microsoft login143. User → Entra ID: Authenticate & consent154. Entra ID → App: Authorization code (via redirect URI)165. App → Entra ID: Exchange code for tokens (with client secret)176. Entra ID → App: Access token + refresh token + ID token187. App → API: Call API with access token19```2021### Implementation Steps2223#### 1. Build Authorization URL2425```26https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?27client_id={application_id}28&response_type=code29&redirect_uri={redirect_uri}30&response_mode=query31&scope={scopes}32&state={random_state}33```3435**Parameters:**36- `tenant`: Your tenant ID or `common` for multi-tenant37- `client_id`: Application (client) ID from app registration38- `redirect_uri`: Must match exactly what's registered39- `scope`: Space-separated permissions (e.g., `openid profile User.Read`)40- `state`: Random value to prevent CSRF attacks4142#### 2. User Authenticates4344User is redirected to Microsoft login page, authenticates, and grants consent.4546#### 3. Receive Authorization Code4748App receives callback at redirect URI:49```50https://your-app.com/callback?51code={authorization_code}52&state={state_value}53```5455**Validation:**56- Verify `state` matches what you sent57- Extract `code` parameter5859#### 4. Exchange Code for Tokens6061```http62POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token63Content-Type: application/x-www-form-urlencoded6465client_id={application_id}66&scope={scopes}67&code={authorization_code}68&redirect_uri={redirect_uri}69&grant_type=authorization_code70&client_secret={client_secret}71```7273**Response:**74```json75{76"access_token": "eyJ0eXAi...",77"token_type": "Bearer",78"expires_in": 3600,79"refresh_token": "M.R3_BAY...",80"id_token": "eyJ0eXAi..."81}82```8384#### 5. Use Access Token8586```http87GET https://graph.microsoft.com/v1.0/me88Authorization: Bearer {access_token}89```9091## Authorization Code Flow with PKCE9293PKCE (Proof Key for Code Exchange) adds security for public clients that cannot securely store a client secret.9495### Flow Steps9697```981. App: Generate code verifier (random string)992. App: Generate code challenge (SHA256 hash of verifier)1003. App → Entra ID: Authorization request with code challenge1014. User → Entra ID: Authenticate & consent1025. Entra ID → App: Authorization code1036. App → Entra ID: Exchange code + code verifier for token1047. Entra ID: Validates verifier matches challenge1058. Entra ID → App: Access token + ID token106```107108### Implementation Steps109110#### 1. Generate PKCE Values111112**Code Verifier:** 43-128 character random string113```javascript114// JavaScript example115const codeVerifier = generateRandomString(128);116```117118**Code Challenge:** Base64URL-encoded SHA256 hash of verifier119```javascript120const codeChallenge = base64URLEncode(sha256(codeVerifier));121```122123#### 2. Build Authorization URL124125```126https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize?127client_id={application_id}128&response_type=code129&redirect_uri={redirect_uri}130&scope={scopes}131&state={state}132&code_challenge={code_challenge}133&code_challenge_method=S256134```135136#### 3. Exchange Code for Tokens (No Secret)137138```http139POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token140Content-Type: application/x-www-form-urlencoded141142client_id={application_id}143&scope={scopes}144&code={authorization_code}145&redirect_uri={redirect_uri}146&grant_type=authorization_code147&code_verifier={code_verifier}148```149150## Client Credentials Flow151152### Flow Steps153154```1551. App → Entra ID: Request token with client ID + secret1562. Entra ID: Validate credentials1573. Entra ID → App: Access token (application permissions)1584. App → API: Call API with token159```160161### Implementation Steps162163#### 1. Configure Application Permissions164165In app registration:1661. Go to "API permissions"1672. Add **Application** permissions (not delegated)1683. Grant admin consent (required for app permissions)169170**Example permissions:**171- `User.Read.All` (application) - Read all users172- `Directory.Read.All` (application) - Read directory173174#### 2. Request Access Token175176```http177POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token178Content-Type: application/x-www-form-urlencoded179180client_id={application_id}181&scope=https://graph.microsoft.com/.default182&client_secret={client_secret}183&grant_type=client_credentials184```185186**Parameters:**187- `scope`: Use `{resource}/.default` format188- For Microsoft Graph: `https://graph.microsoft.com/.default`189- For your API: `api://{api_app_id}/.default`190191**Response:**192```json193{194"access_token": "eyJ0eXAi...",195"token_type": "Bearer",196"expires_in": 3599197}198```199200#### 3. Use Access Token201202```http203GET https://graph.microsoft.com/v1.0/users204Authorization: Bearer {access_token}205```206207## Device Code Flow208209**Use for:** Devices without browsers (IoT, CLIs), headless environments210211### Flow Steps212213```2141. App → Entra ID: Request device code2152. Entra ID → App: Device code + user code + verification URL2163. App → User: Display code and URL2174. User: Opens URL on another device, enters code2185. User → Entra ID: Authenticates & consents2196. App → Entra ID: Poll for token2207. Entra ID → App: Access token (after user completes auth)221```222223### Implementation Steps224225#### 1. Request Device Code226227```http228POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/devicecode229Content-Type: application/x-www-form-urlencoded230231client_id={application_id}232&scope={scopes}233```234235**Response:**236```json237{238"user_code": "GTHK-QPMN",239"device_code": "GMMhmHCXhWEzkobqIHGG_EnNYYsAkukHspeYUk9E8",240"verification_uri": "https://microsoft.com/devicelogin",241"expires_in": 900,242"interval": 5,243"message": "To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code GTHK-QPMN to authenticate."244}245```246247#### 2. Display Instructions to User248249```250To sign in, open https://microsoft.com/devicelogin251and enter code: GTHK-QPMN252```253254#### 3. Poll for Token255256```http257POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token258Content-Type: application/x-www-form-urlencoded259260client_id={application_id}261&grant_type=urn:ietf:params:oauth:grant-type:device_code262&device_code={device_code}263```264265**Poll every 5 seconds (use `interval` from response)**266267**Pending Response (user hasn't completed auth yet):**268```json269{270"error": "authorization_pending",271"error_description": "AADSTS70016: Pending end-user authorization..."272}273```274275**Success Response:**276```json277{278"access_token": "eyJ0eXAi...",279"token_type": "Bearer",280"expires_in": 3600,281"refresh_token": "M.R3_BAY...",282"id_token": "eyJ0eXAi..."283}284```285286## Refresh Token Flow287288**Use for:** Refreshing expired access tokens without re-authentication289290### When to Refresh291292- Access tokens typically expire in 1 hour293- Refresh tokens are long-lived (14-90 days)294- Refresh before access token expires for seamless UX295296### Implementation297298```http299POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token300Content-Type: application/x-www-form-urlencoded301302client_id={application_id}303&scope={scopes}304&refresh_token={refresh_token}305&grant_type=refresh_token306&client_secret={client_secret}307```308309**Note:** `client_secret` only required for confidential clients310311**Response:**312```json313{314"access_token": "eyJ0eXAi...",315"token_type": "Bearer",316"expires_in": 3600,317"refresh_token": "M.R3_BAY...",318"id_token": "eyJ0eXAi..."319}320```321322**Important:** New refresh token is returned; use it for next refresh323324## Token Types325326### Access Token327328- Used to call APIs329- Contains claims (user ID, permissions, etc.)330- Short-lived (typically 1 hour)331- Format: JWT (JSON Web Token)332333**Sample claims:**334```json335{336"aud": "https://graph.microsoft.com",337"iss": "https://sts.windows.net/{tenant}/",338"sub": "{user_object_id}",339"scp": "User.Read Mail.Read",340"exp": 1680000000341}342```343344### Refresh Token345346- Used to get new access tokens347- Long-lived (days to months)348- Opaque string (not JWT)349- Single-use (new one issued with each refresh)350351### ID Token352353- Contains user identity information354- Used by the app to authenticate user355- Format: JWT356357**Sample claims:**358```json359{360"sub": "{user_object_id}",361"name": "Jane Doe",362"preferred_username": "[email protected]",363"email": "[email protected]",364"oid": "{object_id}"365}366```367368## Scopes and Permissions369370### Scope Format371372**Microsoft Graph:**373```374https://graph.microsoft.com/User.Read375https://graph.microsoft.com/Mail.Send376```377378**Custom API:**379```380api://{api_application_id}/access_as_user381```382383## Security Considerations384385| Practice | Why |386|----------|-----|387| **Use state parameter** | Prevents CSRF attacks |388| **Use PKCE for public clients** | Prevents authorization code interception |389| **Validate tokens** | Verify signature, issuer, audience, expiration |390| **Use HTTPS only** | Protect tokens in transit |391| **Store tokens securely** | Use secure storage, never in localStorage for sensitive apps |392| **Implement token refresh** | Seamless UX without repeated logins |393| **Handle token expiration** | Gracefully refresh or re-authenticate |394| **Minimal scope principle** | Request only necessary permissions |395396## Additional Resources397398[OAuth 2.0 spec](https://www.rfc-editor.org/rfc/rfc6749)