Limited Offer

30% OFF Lifetime Access ($139) with code SYSTEM30

TOPIC #161Advanced 11 min read

OAuth 2.0: Grant Types & Authorization Code Flow with PKCE

💡
Core Architecture Summary

Master delegated authorization: Authorization Code Grant with PKCE (Proof Key for Code Exchange) for SPAs and Mobile, Client Credentials for microservices, Device Flow for CLIs, and deprecation of the Implicit and Password grants.

Key Glossary Concepts in this TopicAll Glossary Terms

OAuth 2.0 Authorization Code Flow with PKCE 🛡️

Cryptographic binding between authorization request and token exchange preventing code interception attacks on public clients.

OAuth 2.0 Authorization Code Flow with PKCE 🛡️
100%
Rendering visual architecture flowchart...

01.1. What is OAuth 2.0? Delegated Authorization Explained

OAuth 2.0 (RFC 6749) is an open industry standard framework for delegated authorization. It allows a third-party application (e.g., Spotify) to access resources hosted on a service provider (e.g., Google Drive or Facebook Profile) on behalf of a user without the user ever revealing their credentials (passwords) to the third party.

The 4 Core Roles in OAuth 2.0:

  1. Resource Owner: The end user who owns the data and grants access.
  2. Client: The application requesting access (e.g., Single Page App, Mobile App, Backend Service).
    • Confidential Client: A server-side application capable of securely maintaining a secret (e.g., Node.js backend with CLIENT_SECRET).
    • Public Client: An application running on user-controlled hardware incapable of keeping secrets (e.g., React SPA, iOS/Android mobile app).
  3. Authorization Server: The system issuing access tokens after authenticating the Resource Owner and obtaining consent (e.g., Auth0, Okta, Keycloak, Google Identity).
  4. Resource Server: The backend API hosting the protected data (e.g., https://api.company.com/v1/orders). It accepts and validates access tokens.

02.2. Deep Dive: Authorization Code Flow with PKCE (RFC 7636)

For Single Page Applications (SPAs) and Mobile Apps (Public Clients), Authorization Code with PKCE (Proof Key for Code Exchange) is the mandatory gold standard.

Why PKCE was Created (The Authorization Code Interception Attack):

In native mobile apps, custom URL schemes (e.g., myapp://callback) register with the mobile operating system. Malicious apps installed on the same device could hijack the custom URI scheme and intercept the returned code. Because public clients have no secret key, the malicious app could immediately exchange the stolen code for an access token.

The Cryptographic Mechanics of PKCE:

  1. Generate code_verifier: The client generates a cryptographically high-entropy random string (43 to 128 characters from unreserved characters: [A-Z], [a-z], [0-9], -, ., _, ~):
    code_verifier = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
    
  2. Calculate code_challenge: The client hashes the verifier using SHA-256 and Base64URL-encodes the digest:

code\_challenge = Base64URL(SHA256(code\_verifier))

  1. Authorization Request: The client directs the browser to /authorize with code_challenge and code_challenge_method=S256. The Authorization Server stores the challenge alongside the generated authorization code.
  2. Token Exchange: The client sends a POST /oauth/token including the plain code_verifier in memory.
  3. Validation: The Authorization Server hashes the provided code_verifier with SHA-256. If the result matches the previously stored code_challenge, it proves that the entity requesting tokens is the exact same entity that initiated the authorization request. Even if an attacker intercepted the authorization code, they cannot exchange it without the secret code_verifier!

03.3. Overview of Modern vs Deprecated Grant Types

Modern OAuth 2.1 specifications consolidate grant types and deprecate dangerous legacy patterns:

1. Authorization Code Flow with PKCE (Modern Standard):

  • Target: SPAs (React, Vue), Mobile Apps (iOS, Android), and Server-Side Web Apps.
  • Security: Maximum protection against token leakage in browser history and redirection hijacking.

2. Client Credentials Grant (Machine-to-Machine M2M):

  • Target: Internal daemon services, background cron jobs, and microservice-to-microservice communication.
  • Workflow: The client authenticates directly using its client_id and client_secret via POST /oauth/token to obtain an access token with backend scopes (no user or browser involved).

3. Device Authorization Grant (RFC 8628):

  • Target: Smart TVs, CLI tools, Apple TV, game consoles (devices with limited input capabilities).
  • Workflow: The device displays a short verification code and URL (https://activate.example.com). The user visits the URL on their smartphone or laptop to authorize the device.

⚠️ Deprecated Grant Types (Do Not Use!):

  • Implicit Grant (Deprecated): Returned access tokens directly in URL fragments (#access_token=...), exposing tokens to browser history, referrer headers, and malicious extensions.
  • Resource Owner Password Credentials (ROPC / Deprecated): Required users to type their raw username and password directly into the client application, defeating the purpose of delegated authorization.

04.4. Production PKCE Helper Implementation in TypeScript

Below is a standard Web Crypto API implementation for generating PKCE parameters in browser/Node environments:

typescript
/**
 * Generates a cryptographically secure random code_verifier and SHA-256 code_challenge
 * compliant with RFC 7636.
 */
export async function generatePKCE(): Promise<{ codeVerifier: string; codeChallenge: string }> {
  // 1. Generate 32 cryptographically random bytes (high-entropy)
  const randomBytes = new Uint8Array(32);
  crypto.getRandomValues(randomBytes);

  // 2. Base64URL encode to produce code_verifier (43 characters)
  const codeVerifier = base64UrlEncode(randomBytes);

  // 3. Hash code_verifier with SHA-256
  const encoder = new TextEncoder();
  const data = encoder.encode(codeVerifier);
  const hashBuffer = await crypto.subtle.digest('SHA-256', data);

  // 4. Base64URL encode the SHA-256 digest to produce code_challenge
  const codeChallenge = base64UrlEncode(new Uint8Array(hashBuffer));

  return { codeVerifier, codeChallenge };
}

function base64UrlEncode(buffer: Uint8Array): string {
  let binary = '';
  const bytes = new Uint8Array(buffer);
  const len = bytes.byteLength;
  for (let i = 0; i < len; i++) {
    binary += String.fromCharCode(bytes[i]);
  }
  return btoa(binary)
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/, '');
}

⚖️Architectural Trade-offs & Production Realities

Architectural Advantages

  • Eliminates password sharing with third parties, enabling granular, time-bound scoped access
  • PKCE eliminates authorization code interception attacks on public clients (SPAs and mobile)
  • Client Credentials grant provides a standardized security model for machine-to-machine microservice communication

Trade-offs & Constraints

  • Multi-step redirect workflows add network latency during initial user onboarding and login
  • Complex protocol state management (state parameter validation, token rotation, scope management)
Production Implementation in Big Tech
Spotify & Google Calendar• Third-Party Integration via OAuth 2.0 PKCE

When connecting Spotify to Discord or Google Assistant, Spotify initiates an OAuth 2.0 PKCE flow. The user grants specific scopes (`user-read-playback-state`), and Spotify issues a scoped access token to Discord without Discord ever seeing or storing the user's Spotify credentials.

🎯 Staff+ Engineering Takeaways

  • OAuth 2.0 is a framework for delegated authorization, not authentication.
  • Authorization Code with PKCE is mandatory for all SPAs and Mobile Public Clients.
  • Client Credentials grant is the standard for service-to-service backend authorization.
  • Implicit Grant and Resource Owner Password Grant are deprecated and insecure.

Topic Knowledge Assessment 🧠

Step through 2 scenario questions to test your staff-level grasp.

Question 1 of 20 answered
#1

Why was PKCE (Proof Key for Code Exchange) created for OAuth 2.0 public clients (mobile apps and SPAs)?

Rate This Architecture Chapter4.9 / 5.0 (38 ratings)

How clear and staff-actionable was this system breakdown?