Lesson 13 / 25

Roles and the Authorization Code Flow With PKCE

The recommended flow for web, mobile and single-page apps.

Four roles, one redirect dance

OAuth 2.0 (RFC 6749) defines the resource owner (the user), the client (the app), the authorization server (issues tokens) and the resource server (the API). In the authorization code flow the client redirects the browser to the authorization server; the user logs in and consents; the server redirects back with a short-lived code; the client exchanges the code at the token endpoint for tokens over a back channel. PKCE (RFC 7636) binds the code to the client that started the flow: the client creates a random code_verifier, sends its SHA-256 hash as code_challenge (method S256), and must present the verifier when redeeming the code, so a stolen code is useless. Current guidance (RFC 9700, the OAuth 2.0 Security Best Current Practice) recommends PKCE for all clients, a random state to tie the response to the request, and exact matching of registered redirect URIs.

Delegated access and federated login

OAuth 2.0 lets an application obtain limited access to an API on a user's behalf; OpenID Connect adds a standard identity layer for login.

Three ideas: authorization code flow with PKCE, ID tokens versus access tokens, client credentials and deprecated grants.
Figure 5.1 — Client, authorization server, user, resource server.

The flow on the wire

Simplified HTTP; values are illustrative.

# 1. Browser is redirected to the authorization server
GET https://auth.example.com/authorize?response_type=code
    &client_id=web-app
    &redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
    &scope=openid%20profile%20orders%3Aread
    &state=af0ifjsldkj
    &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
    &code_challenge_method=S256

# 2. After login and consent, the browser comes back
GET https://app.example.com/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=af0ifjsldkj

# 3. Client exchanges the code (back channel)
POST https://auth.example.com/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
&client_id=web-app&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

# 4. Response
{ "access_token": "...", "token_type": "Bearer", "expires_in": 600,
  "refresh_token": "...", "id_token": "eyJ..." }

A valet key with a claim ticket

OAuth gives the app a valet key that opens only some doors, instead of your master key (your password). PKCE is like keeping the stub of the claim ticket: someone who grabs the ticket alone cannot collect the car.

Quick check: What does PKCE protect against?

  • Weak user passwords
  • An intercepted authorization code being redeemed by another party
  • Expired access tokens
  • Cross-site scripting in the API
Answer

An intercepted authorization code being redeemed by another party — Only the client holding the code_verifier can redeem the code.