Skip to main content

Authorization Code

RFC 6749 §4.1

Client type: Confidential clients (server-side web apps) that can securely store a client secret

The Authorization Code grant is the most secure OAuth 2.0 flow. The user authenticates with the authorization server, which returns a short-lived code to the redirect URI. The server (not the browser) exchanges the code for tokens using the client secret. The access token is never exposed to the browser. Use for server-side web applications.

How it works

Authorization Code is the foundational OAuth 2.0 grant type. It separates user authentication (handled in the browser) from token issuance (handled server-to-server).

Flow: 1. Client redirects user to /authorize with response_type=code, client_id, redirect_uri, scope, state 2. User authenticates and grants permission 3. Authorization server redirects back to redirect_uri with code and state 4. Client backend exchanges code for tokens via POST /token with code, client_id, client_secret, redirect_uri 5. Authorization server returns access_token, refresh_token, expires_in

Security properties: - Access token never touches the browser - Client secret kept server-side - State parameter prevents CSRF - Code is single-use, short-lived (~10 minutes) - redirect_uri must exactly match the registered URI (OAuth 2.1 requirement)

Without PKCE: the code is vulnerable to interception if the browser redirects through an attacker-controlled redirect. For public clients, always use PKCE (see next grant type). For confidential clients, PKCE adds defense-in-depth.

PKCE + Auth Code: see the PKCE grant type for the full extension.

Flow Steps

  1. 1

    Client redirects to /authorize?response_type=code&client_id=...&redirect_uri=...&scope=...&state=...

  2. 2

    User authenticates and grants permission at authorization server UI

  3. 3

    Authorization server redirects to redirect_uri?code=abc123&state=...

  4. 4

    Client validates state (CSRF check), then POSTs code to /token with client_secret

  5. 5

    Authorization server returns access_token, refresh_token, expires_in

  6. 6

    Client stores refresh_token server-side; uses access_token for API calls

Parameters

ParameterRequiredDescription
response_typeYesMust be 'code'
client_idYesApplication identifier registered with authorization server
redirect_uriYesMust exactly match registered redirect URI
scopeNoSpace-separated list of requested scopes
stateYesCSRF protection – random value, verify it matches on callback
code_challengeNoPKCE: BASE64URL(SHA256(code_verifier)). Strongly recommended.
code_challenge_methodNoPKCE: must be S256. plain is deprecated.

Examples

Authorization request + token exchange
# Step 1: Redirect to authorization server
GET https://auth.example.com/authorize?
  response_type=code
  &client_id=app_abc
  &redirect_uri=https://app.example.com/callback
  &scope=read:profile+write:orders
  &state=xyzABC123randomCSRF

# Step 2: Callback received
https://app.example.com/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=xyzABC123randomCSRF

# Step 3: Token exchange (server-side)
POST https://auth.example.com/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https://app.example.com/callback
&client_id=app_abc
&client_secret=client_secret_here

When to use

Server-side web applications (Node.js, Python, Java, Ruby) where the client secret can be stored securely on the server. Never use this variant (without PKCE) for mobile or browser-based apps.

See Also