Authorization Code
RFC 6749 §4.1Client 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
Client redirects to /authorize?response_type=code&client_id=...&redirect_uri=...&scope=...&state=...
- 2
User authenticates and grants permission at authorization server UI
- 3
Authorization server redirects to redirect_uri?code=abc123&state=...
- 4
Client validates state (CSRF check), then POSTs code to /token with client_secret
- 5
Authorization server returns access_token, refresh_token, expires_in
- 6
Client stores refresh_token server-side; uses access_token for API calls
Parameters
| Parameter | Required | Description |
|---|---|---|
| response_type | Yes | Must be 'code' |
| client_id | Yes | Application identifier registered with authorization server |
| redirect_uri | Yes | Must exactly match registered redirect URI |
| scope | No | Space-separated list of requested scopes |
| state | Yes | CSRF protection – random value, verify it matches on callback |
| code_challenge | No | PKCE: BASE64URL(SHA256(code_verifier)). Strongly recommended. |
| code_challenge_method | No | PKCE: must be S256. plain is deprecated. |
Examples
# 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.