Choosing the Right Microsoft Graph Authentication Flow: Delegated vs. Application Permissions
Decide between Delegated and Application permissions for Microsoft Graph API. Learn when to use Auth Code, Client Credentials, or OBO flows and how to verify tokens.
31 Aug 2026, 17:23 UTC

The Decision: User-Centric or Service-Centric Access
When integrating with Microsoft Graph, the primary engineering decision is whether the application acts on behalf of a user (Delegated) or as its own identity (Application). Choosing the wrong flow leads to either security vulnerabilities—such as granting a background script access to every mailbox in the company—or functional failures where a service cannot run because it is waiting for a user to log in.
Comparison of Authentication Flows
| Flow Type | Permission Type | Primary Use Case | Auth Method | Access Scope |
|---|---|---|---|---|
| Auth Code + PKCE | Delegated | Interactive Apps (Web/Mobile) | User Login | User's own permissions |
| Client Credentials | Application | Daemons, Cron jobs, Sync services | Secret or Certificate | Tenant-wide (all users) |
| On-Behalf-Of (OBO) | Delegated | Middle-tier API services | Token Exchange | User's own permissions |
Evaluating the Trade-offs
Delegated Permissions (The Principle of Least Privilege)
Delegated permissions are the safest choice for most applications. The application can only access data that the signed-in user has permission to see. If a user cannot access a specific SharePoint site, the app cannot access it either, regardless of the scopes requested during registration.
- Pros: Reduced blast radius; respects existing M365 ACLs (Access Control Lists).
- Cons: Requires an interactive user session; tokens expire and require refresh tokens.
Application Permissions (The High-Privilege Path)
Application permissions allow a service to run without any user present. This is necessary for backup tools, automated reporting, or tenant-wide synchronization. However, these permissions are broad. For example, Mail.Read as an application permission allows the app to read every mailbox in the organization.
- Pros: Fully automated; no user interaction required.
- Cons: Extremely high risk; requires Global Administrator consent; bypasses user-level permissions.
Implementation: Validating Permission Scopes
To verify which permission type is active in your token, you must inspect the JSON Web Token (JWT) claims. This prevents "permission creep" where an app is granted more access than intended.
Step 1: Obtain the Token
Run your authentication request via your chosen flow. If using the Client Credentials flow via CLI (run from a secure terminal with curl or Postman):
POST https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
client_id={client-id}
&scope=https://graph.microsoft.com/.default
&client_secret={client-secret}
&grant_type=client_credentials
Step 2: Inspect the Claims
Copy the access_token and paste it into a JWT decoder (such as jwt.ms). Look for these specific keys in the payload:
scp(Scopes): Present in Delegated tokens. It lists the specific user-delegated permissions (e.g.,User.Read Mail.Read).roles: Present in Application tokens. It lists the tenant-wide roles assigned to the service principal (e.g.,Mail.Read).
Operational Constraints and Risks
- Secret Rotation: Client secrets used in the Client Credentials flow have a maximum lifespan. If a secret expires, the service will return a
401 Unauthorizederror immediately. Implement a rotation schedule or use Certificates for higher security. - Admin Consent: Application permissions cannot be granted by the user; they must be granted by a Global Administrator in the Entra ID portal.
- Application Access Policies: To mitigate the risk of Application permissions, use Application Access Policies in Exchange Online to restrict a service's access to a specific subset of mailboxes rather than the entire tenant.
Verification Checklist
- Check the JWT: Does it contain
scp(Delegated) orroles(Application)? - Test the boundary: If using Delegated, can the app access data the user cannot? (It should not).
- Test the scope: If using Application, can it access all users? (If this is too broad, implement an Application Access Policy).
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.