4.3.2. Authentication, API Permissions, and App Roles
💡 First Principle: Permissions come in exactly two species, distinguished by whose power flows through the token: delegated permissions channel a signed-in user's rights (effective access = intersection of user's rights and granted scopes), while application permissions are the app's own standing power, exercised with no user present. Every API permission question resolves by asking: is there a user in the loop?
| Delegated permissions (scopes) | Application permissions (app roles) | |
|---|---|---|
| Token flow | User signs in; token carries scp claim | Client credentials; token carries roles claim |
| Effective power | Intersection: user's rights ∩ granted scopes | The full granted permission, tenant-wide |
| Who consents | User (low-risk) or admin | Admin only, always |
| Typical caller | Web/mobile apps acting for users | Daemons, background services, integrations |
| Example | Mail.Read → read the signed-in user's mail | Mail.Read → read every mailbox |
That same-name difference in the example row is the most reliable exam trap in the domain: Mail.Read delegated is modest; Mail.Read application is catastrophic if leaked. Requesting the right species and the least of it (prefer Mail.Read over Mail.ReadWrite, prefer per-mailbox RBAC where the API supports it) is the graded skill.
Configure API permissions on the registration: add Microsoft Graph (or another API) → pick delegated or application → specific permissions → grant admin consent where required (application permissions always; delegated ones marked admin-restricted). The client credentials flow is the application-permission runtime: app presents its certificate/secret, receives a token with roles, calls the API — no user, no MFA, which is exactly why admin consent guards it.
Create app roles flips your perspective to API producer: in your registration, define roles (Reader, Approver, value strings the token will carry), choose whether they're assignable to users/groups (delivered via enterprise-app assignment, 4.2.3) or to applications (your API's own "application permissions" for its daemon callers). Expose an API similarly defines scopes for delegated callers. Your app then authorizes by validating roles/scp claims — Phase 1's token anatomy earning its keep.
⚠️ Exam Trap: A background service with delegated permissions is a broken design — no user, no token. The pair to memorize: unattended/daemon → application permissions + client credentials + admin consent; interactive → delegated + auth code flow. Stems mixing them are testing the species boundary, not the API details.
Reflection Question: Your API must let human reviewers approve invoices in a web app, and let a nightly job export all approved invoices. Define the app roles/scopes you'd expose for each caller, and state which consent ceremony each requires.