OAuth 2.0 Fundamentals
Understanding delegated authorization, the password anti-pattern, actor topologies, client trust models, token consumers, and modern security best practices under RFC 6749 and RFC 9700.
The Problem OAuth Solves: The Password Anti-Pattern
Before OAuth, if a third-party application (e.g., Yelp or a photo printing service) needed access to a user's data on another platform (e.g., Google Contacts or Flickr), the third-party app asked the user for their raw username and password.
"Enter your Google Email and Password so PhotoPrint can download your albums:"
Password: ••••••••••••
- Full Account Takeover: PhotoPrint gains unrestricted access to all your Gmail, Drive files, and Search history.
- Cannot Revoke: To revoke PhotoPrint's access, you must change your master Google password, breaking all other apps.
- Stored in Plaintext: Third-party apps stored user passwords in plaintext or reversible encryption to perform background syncing.
What is OAuth 2.0? (RFC 6749)
"The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf."
When you give a valet key to a parking attendant:
- Limited Access: The valet can start the engine and park the car, but cannot open the locked trunk or glovebox.
- Short Duration: The valet key is used only while parking and returned immediately after.
- No Master Key: You never hand over your master key or house keys on the keyring.
In OAuth 2.0, the Access Token is the digital valet key: it grants scoped, temporary, revocable access to specific API endpoints without ever disclosing the user's master credentials.
The Four OAuth Actors (RFC 6749 Section 1.1)
Every OAuth 2.0 architecture revolves around 4 distinct roles:
1. Resource Owner
The User (e.g. Alice)
The human entity that owns the data and has authority to grant access to it.
2. Client
The Application (e.g. PhotoPrint App)
The application requesting access to protected resources on behalf of the user.
3. Authorization Server
The IdP (e.g. Okta, Entra ID, Google)
Authenticates the Resource Owner, prompts for consent, and mints cryptographic tokens.
4. Resource Server
The Protected API (e.g. Photo Storage API)
Hosts protected resources and validates incoming Bearer access tokens before serving data.
API Keys vs OAuth 2.0 Bearer Tokens
Why static API keys fail for enterprise applications compared to OAuth tokens:
// 1. Static API Key Request (Insecure: static, broad, no user context)
GET /api/reports HTTP/1.1
Host: api.example.com
X-API-Key: secret_live_abcdef123456789
// 2. OAuth 2.0 Bearer Token Request (Secure: scoped, short-lived, signed)
GET /api/reports HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3JfMTIzIiwic2NvcGUiOiJyZWFkOnJlcG9ydHMiLCJleHAiOjE3NTUwMDM2MDB9... | Security Dimension | Static API Key | OAuth 2.0 Bearer Token |
|---|---|---|
| User Identity & Context | None (Application-level only) | Bound to specific user (sub claim) |
| Token Lifetime | Indefinite / Months (Hard to rotate) | Short-lived (15–60 mins) with refresh tokens |
| Granular Authorization | Coarse / All-or-nothing access | Fine-grained scopes (read:reports, write:users) |
| Revocation Impact | Catastrophic: Breaks all services sharing key | Granular: Revoke single user session without affecting others |
| Cryptographic Integrity | None: Shared symmetric string | Asymmetric digital signature (RS256 via public JWKS) |
OAuth Scopes & User Consent
In RFC 6749 Section 3.3, Scopes are space-delimited strings defining the exact permissions an application requests. Consent is the user-facing approval step where the Resource Owner explicitly grants or denies those permissions.
1. How Scopes Translate into Consent Screens
When an application requests authorization with query parameters:
GET /authorize?
response_type=code
&client_id=my_calendar_app
&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcb
&scope=openid%20profile%20read:calendar%20write:calendar
&state=af0ifjsldkj HTTP/1.1
Host: accounts.example.com "My Calendar App" wants permission to access your account:
- ✅ View your basic profile:
openid profile - ✅ Read calendar events:
read:calendar - ✅ Create and modify calendar events:
write:calendar
2. Scope Categories & Examples
A. Standard OpenID Connect (OIDC) Scopes
| Scope String | Claims Released | User Consent Description |
|---|---|---|
openid | sub (User identifier) | "Verify your identity" |
profile | name, picture, locale | "View your basic profile information" |
email | email, email_verified | "View your email address" |
phone | phone_number | "View your phone number" |
address | Formatted physical address | "View your physical address" |
offline_access | Issues a Refresh Token | "Maintain access when you are not using the app" |
B. Custom Microservice & REST API Scopes (Action:Resource)
| Scope String | Protected Endpoint | Permission Granted |
|---|---|---|
read:reports | GET /api/protected/reports | View internal analytical reports |
write:reports | POST /api/protected/reports | Create and publish reports |
read:users | GET /api/protected/users | List directory members |
write:users | POST /api/protected/users | Invite and provision user accounts |
delete:users | DELETE /api/protected/users/:id | Deprovision user accounts |
execute:jobs | POST /api/protected/jobs | Run background asynchronous workloads |
C. Real-World Cloud & SaaS Scopes
- Google:
https://www.googleapis.com/auth/drive.file(Manage Drive files created by app) - Microsoft Graph:
User.Read,Mail.Send,Files.ReadWrite.All - GitHub:
repo(Full private repo control),user:email(Read email addresses)
3. Incremental (Step-Up) Consent Pattern
Rather than demanding intrusive scopes upon initial registration, modern apps request only openid profile email on login, and request higher scopes (e.g. write:reports) incrementally only when the user triggers that specific feature.
Public vs Confidential Clients (RFC 6749 Section 2.1)
Clients are classified strictly by their ability to maintain the confidentiality of their credentials:
Confidential (Private) Clients
Examples: Node.js, Express, Spring Boot, ASP.NET running in secure server environments.
- Can securely maintain a
client_secretin server environment variables. - Performs back-channel token exchanges with client authentication (Basic Auth or POST body).
- Eligible for Client Credentials Flow (M2M).
Public Clients
Examples: React/Vue Single Page Apps, iOS/Android mobile apps, desktop apps.
- Cannot keep a secret: Source code is viewable via browser dev tools or binary decompilation.
- Must NOT have a
client_secret: Never bake a secret into an app shipped via App Store or npm bundle. - Must use PKCE (RFC 7636) to secure authorization code exchange.
Client Trust & Application Models
1. Redirect Model vs Embedded Model
| Model | How It Works | Security Posture & Best Practice |
|---|---|---|
| Redirect Model (Standard) | Client redirects user browser to IdP login page (e.g. https://auth.company.com). | Recommended Gold Standard: Client never touches user passwords; IdP manages MFA, passkeys, and session cookies securely. |
| Embedded Model (Direct SDK) | Client renders custom input fields in its own UI and calls backend APIs (e.g. Okta Interaction Code Flow). | High-Trust First-Party Only: Requires high trust; client app must be strictly audited to ensure credentials are not logged or exfiltrated. |
2. High-Trust First-Party vs Low-Trust Third-Party
- First-Party Apps: Developed by the same organization hosting the identity provider (e.g., Google Maps accessing Google Account). Often granted automatic consent or native embedded login experiences.
- Third-Party Apps: Built by external developers. Must always use the Redirect Model with explicit User Consent screens and PKCE.
Front Channel vs Back Channel
OAuth 2.0 segregates interactions across two distinct network paths:
- Front Channel: Carried out via user browser redirects (e.g.,
GET /authorize). Visible in browser history and logs; must only carry transient authorization codes, never raw tokens or client secrets. - Back Channel: Direct server-to-server TLS encrypted HTTPS POST requests (e.g.,
POST /token). Used for exchanging codes for access tokens and validating credentials.
sequenceDiagram
autonumber
actor RO as 👤 Resource Owner (User)
participant C as 📱 Client App (SPA / Web / Mobile)
participant AS as 🔑 Authorization Server (IdP)
participant RS as 🗄️ Resource Server (API)
Note over RO,AS: 🌐 FRONT CHANNEL (Browser Redirects / Visible)
RO->>C: 1. Initiate Action / Login
C->>AS: 2. Redirect to GET /authorize (scope, state, client_id)
RO->>AS: 3. Authenticate & Grant Consent
AS-->>C: 4. 302 Redirect to redirect_uri with code & state
Note over C,RS: 🔒 BACK CHANNEL (Direct TLS Encrypted HTTPS POST)
C->>AS: 5. POST /token (grant_type=authorization_code, code, client_secret/PKCE)
AS-->>C: 6. 200 OK (access_token, id_token, refresh_token)
C->>RS: 7. GET /api/data (Authorization: Bearer <access_token>)
RS-->>C: 8. 200 OK (Protected JSON Payload)
OAuth 2.0: Framework vs Protocol Variance
OAuth 2.0 is defined as an Authorization Framework rather than a rigid protocol. Because of this, identity vendors implement parameter options, token payload formats, and role mappings differently:
- Okta: Often issues roles inside a custom
groupsclaim array:"groups": ["Admins", "Engineers"]. - Microsoft Entra ID: Issues roles inside an
rolesclaim:"roles": ["Admin.All", "Reports.Read"]. - Auth0: Uses namespaced custom claims:
"https://myapi.com/roles": ["admin"].
Enterprise applications and API Gateways (such as Azure APIM) must implement claim normalization adapters to map vendor-specific claims into a unified internal permission model.
OAuth 2.0 Endpoints (RFC 6749, RFC 7662, RFC 7009)
/authorize: Front-channel endpoint for user authentication and consent./token: Back-channel endpoint for code and refresh token exchanges./introspect(RFC 7662): Resource server endpoint to verify token status and metadata./revoke(RFC 7009): Endpoint for explicit client-side token revocation.
Web Security 101 Checklist (RFC 9700)
state parameter: Generates a cryptographically random nonce stored in the client session before redirecting. Prevents Cross-Site Request Forgery (CSRF) login injection.
client_id to Token Requests: The Authorization Server must verify that the client redeeming an authorization code is the exact same client to which the code was issued.