Distributed System Concerns
OAuth 2.0 & OpenID Connect
Delegated authorization and an identity layer built on top of it.
In short
Delegated authorization and an identity layer built on top of it.
In a microservices ecosystem, applications must secure their API boundaries. Sharing user passwords directly with third-party applications is a major security risk. OAuth 2.0 is the industry-standard delegated authorization framework that allows third-party apps to obtain limited API access on a user's behalf. OpenID Connect (OIDC) is a thin identity layer built on top of OAuth 2.0 to authenticate who the user is.
1. Learning Objectives
- Differentiate between authentication (who you are) and authorization (what you can do).
- Explain the four core roles defined in the OAuth 2.0 framework.
- Trace the steps of the OAuth 2.0 Authorization Code flow with PKCE.
- Analyze token formats, including Access Tokens, Refresh Tokens, and OIDC ID Tokens (JWTs).
- Verify signed JWT payloads using public cryptographic keys.
- Implement an OAuth 2.0 Authorization Code exchange and PKCE validation simulator in Java, Python, and C++.
2. Prerequisites
Before learning about authorization flows, ensure you understand:
- HTTP Redirections: Standard HTTP status codes like
302 Found. - Cryptographic Hashing (SHA-256): Generating secure hashes from input text.
- JWT Structures: JSON Web Token Header, Payload, and Signature layouts.
3. Why This Topic Matters
Modern web security depends on delegating identity management safely.
If you build a calendar scheduling app and need access to your users' Google Calendars, you should never ask users for their Google passwords. Storing these passwords would expose your database to massive security liabilities and compromise customer credentials during data breaches.
OAuth 2.0 and OIDC solve this:
- Delegated Access: Users grant restricted access permissions (scopes) without sharing passwords.
- Token Isolation: Applications use short-lived access tokens to query resource APIs.
- Federated Identity: Simplifies registration by allowing users to sign in using their existing Google, Apple, or GitHub profiles.
4. Real-world Analogy
Think of using a Hotel Valet Key:
When you park your car at a hotel, you do not hand the valet parking attendant your master key chain (which opens your car doors, glove box, home front door, and office mailbox).
Instead, you hand them a Valet Key (OAuth Access Token).
This valet key is a limited-access credential. It only allows the valet to turn on the engine and park the car in the hotel lot (restricted scope). It does not open the locked glove box or trunk, and it ceases to work when the hotel valet returns the car to you.
5. Core Concepts
- OAuth 2.0 Roles:
- Resource Owner: The user who owns the account data (e.g. Alice).
- Client: The application requesting access (e.g. a scheduling app).
- Authorization Server: The server that authenticates the user and issues tokens (e.g. Okta, Keycloak, Auth0, Google).
- Resource Server: The API holding the protected data (e.g. Google Calendar API).
- Access Token: A string (often a signed JWT) that proves the bearer has authorization to access APIs with specific scopes.
- ID Token: A signed JWT issued by OpenID Connect that contains claims about the identity of the authenticated user (e.g.
sub,email,name). - Authorization Code Flow: The standard flow where the client redirects the user to the authorization server to get a temporary code, then exchanges that code for access tokens on a secure backchannel, protecting the token from browser exposure.
- PKCE (Proof Key for Code Exchange): An extension for mobile and single-page apps. It dynamically generates a code verifier and challenge to prevent authorization code interception attacks.
- Scopes: Permission boundaries requested by the client (e.g.
read:profile,write:calendar).
6. Visualizations
Authorization Code Flow with PKCE
OIDC ID Token JWT Layout
7. How It Works Step-by-Step
Authorization Code Flow Execution
- PKCE Generation: The client app generates a high-entropy string
code_verifier. It computes the SHA-256 hash of the verifier, Base64Url-encodes it, and sets it ascode_challenge. - User Redirect: The client redirects the user's browser to the Authorization Server's
/authorizeendpoint:GET /authorize?client_id=app123&response_type=code&scope=openid email&code_challenge=challenge_abc&code_challenge_method=S256&redirect_uri=https://client.com/callback. - User Consent: The user logs in and consents to share their email. The authorization server returns a temporary
code_xyzto the client's redirect URI. - Token Exchange: The client makes a direct POST request (backchannel) to the Authorization Server's
/tokenendpoint, bypassing the browser:POST /token { client_id: 'app123', code: 'code_xyz', code_verifier: 'verifier_abc', grant_type: 'authorization_code' }. - Verifier Validation: The authorization server hashes the incoming
code_verifierand checks if it matches the originalcode_challenge. If they match, it issues an Access Token and an ID Token (OIDC JWT). - API Access: The client calls resource APIs, including the Access Token in the HTTP Authorization header:
Authorization: Bearer.
8. Internal Architecture
Identity provider infrastructures use secure keys and token distribution layers:
- JWKS (JSON Web Key Set) Endpoint: The Authorization Server publishes its public keys at a standard endpoint:
/.well-known/jwks.json. Resource Servers fetch these public keys to verify JWT signatures locally, avoiding network lookups for every request. - Cryptographic Signing: The authorization server signs tokens using asymmetric private keys (e.g. RS256). Any server can verify the signature using the corresponding public key.
- Token Introspection: Alternatively, for opaque tokens (random strings containing no data), resource servers make API calls to the authorization server (
/introspect) to check token validity.
9. Request Lifecycle
Let's trace a client request authenticated via a JSON Web Token:
- API Call with Token: The client calls a protected API:
GET /orders, sending the JWT in the Authorization header. - Signature Verification: The resource server parses the JWT header, extracts the key ID (
kid), and checks its local cache for the authorization server's public key. It verifies the cryptographic signature locally. - Claim Checks: The server verifies standard claims:
- Expiration (
exp): Confirms the current time is before the expiration timestamp. - Audience (
aud): Confirms the token was intended for this API. - Scopes: Confirms the token includes the required scopes (e.g.
read:orders).
- Expiration (
- Data Response: If verification succeeds, the resource server processes the request and returns the data.
10. Deep Dive
A. OAuth 2.0 vs. OpenID Connect Comparison
| Metric | OAuth 2.0 | OpenID Connect (OIDC) |
|---|---|---|
| Primary Focus | Delegated Authorization (permissions). | Federated Authentication (identity). |
| Core Token Type | Access Token (opaque string or JWT). | ID Token (always a signed JWT). |
| Target Audience | The Resource Server (API). | The Client Application. |
| Payload Information | Scopes and access limits. | User profile details (email, sub, roles). |
B. Proof Key for Code Exchange (PKCE) Mechanics
In native mobile apps or single-page apps (SPAs), there is no secure backend to store client secrets. An attacker can intercept the temporary authorization code during the browser redirect step.
PKCE (RFC 7636) solves this by replacing client secrets with dynamic challenges:
- The client creates a random string
code_verifier. - It hashes the verifier to create a
code_challenge, which it sends to the authorization server during the initial redirect. The authorization server stores the challenge. - When the client exchanges the authorization code for tokens, it sends the original
code_verifier. - The authorization server hashes the verifier. If it matches the stored challenge, it confirms the request came from the same client and issues the tokens. An attacker who intercepted the authorization code cannot exchange it because they do not have the verifier string.
11. Production Examples
- Google Identity Platform: Implements OpenID Connect, allowing third-party applications to authenticate users via "Sign in with Google" buttons.
- Okta / Auth0: Popular enterprise Identity-as-a-Service (IDaaS) platforms that provide centralized user directories, OAuth 2.0 authorization flows, and OIDC ID tokens.
- GitHub OAuth Portal: Allows developers to request access scopes (e.g.
repo,user) to build integrations on top of GitHub developer profiles.
12. Advantages
- Zero Password Sharing: Users consent to API access without sharing passwords with third-party apps.
- Federated Single Sign-On: Users can access multiple independent apps using a single set of identity provider credentials.
- Decoupled Security (JWKS): Microservice resource nodes verify signed tokens locally, avoiding database checks and network lookups.
13. Limitations
- Token Revocation Complexity: Since JWTs are stateless and verified locally, revoking a leaked token before it expires is difficult without using blacklist caches.
- Implementation Complexity: Implementing PKCE, redirection states, and token refreshes correctly requires ongoing developer effort.
- Single Point of Vulnerability: If the primary identity provider (e.g. Google or Okta) suffers an outage, users cannot log in to any downstream applications.
14. Trade-offs
- Opaque vs. JWT Access Tokens: Opaque tokens are random strings that force resource servers to query the authorization server for every request, which is secure but slow. JWTs store claims and are verified locally, which is fast but makes token revocation difficult.
- Short-lived vs. Long-lived Tokens: Short-lived access tokens (e.g. 15 minutes) reduce the security window if a token is leaked, but require frequent background token refreshes. Long-lived tokens reduce refresh overhead but increase the window of vulnerability.
15. Performance Considerations
- Cache JWKS Public Keys: Cache the public keys fetched from the authorization server locally on resource nodes to avoid querying the JWKS endpoint for every API call.
- Keep JWT Payloads Compact: Store only essential claims (e.g.
subandroles) in JWTs, avoiding large payloads that bloat request headers.
16. Failure Scenarios
- Token Replay Attacks: An attacker intercepts a valid access token and uses it to call APIs on the resource server.
Mitigation: Force HTTPS/TLS for all connections, use short expiration windows on access tokens, and bind tokens to client IP addresses if possible. - Private Key Compromise: An attacker gains access to the authorization server's private key, allowing them to sign valid tokens for any user.
Mitigation: Store signing keys in hardware security modules (HSMs) and rotate keys regularly.
17. Best Practices
- Always use PKCE for mobile and single-page apps (SPAs).
- Keep access tokens short-lived (e.g. 15 minutes) and store refresh tokens in secure HttpOnly cookies.
- Validate the signature, expiration, and audience claims of every JWT before processing requests.
18. Common Mistakes
- Storing client secrets in mobile apps or single-page apps (SPAs), where attackers can easily decompile and extract them.
- Failing to validate the cryptographic signature or expiration claim of a JWT, leaving APIs vulnerable to tampering.
- Using the Implicit Grant flow (which returns access tokens directly in URLs), which is deprecated due to browser history leakage risks.
19. Implementation (Authorization Code Exchange and PKCE)
Below is a complete implementation of an OAuth 2.0 and OIDC token exchange simulator in Java, Python, and C++. The simulator models the client app generating verifiers/challenges, the authorization server validating PKCE credentials, and generating signed mock JWT access/ID tokens.
20. Interview Questions & Answers
Q1. What is the fundamental difference between Authentication and Authorization?
Answer:
- Authentication (AuthN): Verifies who you are (e.g. log in with username/password, OTP, or face recognition). OpenID Connect handles authentication, issuing an ID Token (JWT).
- Authorization (AuthZ): Verifies what you can do (e.g. check if a user is permitted to write records). OAuth 2.0 handles authorization, issuing an Access Token that defines access limits.
Q2. Why is the Implicit Grant flow deprecated in modern OAuth 2.0 guidelines?
Answer: The Implicit Flow returns the Access Token directly in the redirection URL hash fragment. This exposes the token to several security vulnerabilities:
- Browser History Leakage: The token remains visible in browser history logs, where malicious extensions or scripts can extract it.
- No Backchannel Exchange: Bypasses verifications, allowing attackers to hijack redirect traffic. Modern standards mandate using the Authorization Code flow with PKCE instead.
Q3. Explain how PKCE prevents code interception attacks in mobile applications.
Answer: In mobile apps, malicious apps on the device can register the same redirect URI schema (e.g. myapp://callback) and intercept the temporary authorization code returned by the browser.
PKCE prevents this by generating a dynamic, high-entropy code_verifier on the client. The client sends only the hashed code_challenge during the initial request. When exchanging the code for tokens, the client must present the raw code_verifier.
Since an intercepting app does not have this verifier, it cannot exchange the code for tokens, rendering the code useless.
21. Practice Exercises
- Exercise 1 (Easy): Trace a diagram showing the difference between authentication and authorization roles.
- Exercise 2 (Medium): Modify the Python
AuthorizationServerimplementation to generate and verify a Refresh Token alongside the access token. - Exercise 3 (Hard): Implement a Python module that parses and cryptographically validates a mock JWT's signature block, checking if header/payload hashes match the signature signature.
22. Challenge Problem
The Stateless Token Revocation Challenge: You operate an enterprise API server cluster authenticated via stateless JWT access tokens with a 1-hour expiration.
A user reports that their device was stolen. SREs must invalidate their active access tokens immediately.
Since resource servers verify JWT signatures locally to avoid database queries, they are unaware that the token has been revoked, allowing an attacker to access the API for up to an hour.
- Propose an architecture to handle instant token revocation without losing the performance benefits of stateless JWT verification.
- Draw a diagram showing the user revocation request, token blacklist sync, and API gateway validation checks.
- Describe the trade-offs of using Redis blacklist caches versus short-lived tokens with frequent database syncs.
23. Summary
OAuth 2.0 and OpenID Connect are the industry standards for securing APIs and managing user identities in distributed systems. OAuth 2.0 delegates authorization using access tokens, while OIDC adds an authentication layer using signed ID tokens (JWTs). Implementing the Authorization Code flow with PKCE and validating tokens locally via JWKS endpoints ensures systems are both secure and scalable.
24. Cheat Sheet
| Token Type | Intended Audience | Contains Claims? | Standard Format |
|---|---|---|---|
| Access Token | Resource Server (API) | Yes (Scopes and limits) | Opaque string or JWT |
| ID Token | Client Application | Yes (User profile claims) | Always a signed JWT |
| Refresh Token | Authorization Server | No (used only to renew access) | Opaque string |
25. Quiz
1. What is the primary purpose of OpenID Connect (OIDC)?
- A. Database file encryption.
- B. Adding an identity (authentication) layer on top of OAuth 2.0.
- C. Speeding up page rendering.
- D. Enforcing rate limits.
Answer: B. OIDC builds on top of OAuth 2.0 to verify user identity.
2. Which OAuth role represents the API hosting the protected user data?
- A. Client.
- B. Resource Server.
- C. Authorization Server.
- D. Resource Owner.
Answer: B. The Resource Server hosts the target data APIs.
3. Why is PKCE used in mobile and single-page apps?
- A. To compress image payloads.
- B. To prevent authorization code interception attacks in environments without client secrets.
- C. To encrypt user passwords.
- D. To run background threads.
Answer: B. PKCE uses dynamic verifiers to prevent intercepted codes from being exchanged.
4. Which token type is designed to be sent to client applications to verify user profile details?
- A. Access Token.
- B. ID Token (JWT).
- C. Refresh Token.
- D. Session Cookie.
Answer: B. OIDC ID Tokens contain signed profile claims (email, name) intended for client apps.
5. What does the acronym JWKS stand for?
- A. Java Web Key Store.
- B. JSON Web Key Set.
- C. Joint Web Key System.
- D. Javascript Web Keys.
Answer: B. JWKS publishes the public keys used to verify signed tokens.
6. What is a key disadvantage of stateless JWT verification?
- A. High DB latency.
- B. Difficulty revoking tokens immediately before they expire.
- C. Requires custom C++ code.
- D. Fails over UDP.
Answer: B. Since JWTs are verified locally without database lookups, immediate revocation is complex.
7. Which grant type should be used for backend-to-backend API integration without user interaction?
- A. Implicit Grant.
- B. Client Credentials Grant.
- C. Authorization Code Flow.
- D. Password Grant.
Answer: B. Client Credentials allow servers to authenticate directly on their own behalf.
8. What is the standard HTTP header used to present an access token?
- A. X-Auth-User.
- B. Authorization: Bearer <token>.
- C. Access-Control-Allow-Origin.
- D. Cookie: session_id.
Answer: B. The Bearer token scheme is the standard for presenting access tokens.
9. Why is the Implicit Grant flow deprecated?
- A. It is too slow.
- B. It returns access tokens directly in URLs, exposing them in browser histories and referrers.
- C. It requires database writes.
- D. It uses XML instead of JSON.
Answer: B. Returning tokens in URLs is unsafe, leading to the deprecation of the Implicit Flow.
10. In a JWT, what does the signature block verify?
- A. The client IP address.
- B. That the Header and Payload have not been tampered with since they were signed.
- C. The database connection status.
- D. The expiration date.
Answer: B. The signature block confirms that token payloads remain untampered.
26. Further Reading
- RFC 6749: The OAuth 2.0 Authorization Framework.
- OpenID Connect Core 1.0 Specification.
- OAuth 2 in Action — Justin Richer and Janua-Kristina Rago.
27. Next Lesson Preview
OAuth delegates access permissions for specific APIs. To authenticate users seamlessly across multiple independent websites using a single login session, we must implement Single Sign-On (SSO)—the core concern we will explore in the next lesson.
Key takeaways
- OAuth 2.0 = authorization; OIDC = authentication on top of it.
- Access tokens grant API access; ID tokens prove identity.