Back to Grant Types
Confidential ClientsID: authorization_code

Authorization Code Flow

The foundational OAuth 2.0 flow designed for confidential clients that can safely store credentials on a backend server.

#oauth2#authorization-code#oidc#web-app#confidential-client#server-side

Overview

The Authorization Code Flow is the primary OAuth 2.0 flow designed for server-side web applications where application code runs on a secure web server and the client secret can be protected from end-users.

In this flow, the resource owner (user) is directed to the identity provider to log in and approve permissions. Upon successful authorization, the authorization server redirects the user back to the client application with a single-use authorization code. The client application then exchanges this temporary code for access and refresh tokens directly with the authorization server over a secure back-channel, authenticating using its client credentials.

Because tokens are delivered directly from the authorization server to the backend web server, the user agent (browser) never has direct access to the access token, making this pattern highly resilient against browser-side token theft.

Quick Specifications

Flow Status
standard
Recommended For
Web Application
Token Auth Methods
Client Secret BasicClient Secret PostMutual TLS
Primary Standard
RFC 6749 Section 4.1

Sequence Diagram

Visual sequence illustrating entity interactions and protocol steps

Sequence Diagram
Interactive Diagram
sequenceDiagram
    autonumber
    actor U as User
    participant B as Browser
    participant C as Client App (Backend)
    participant AS as Authorization Server
    participant RS as Resource Server (API)

    U->>B: Access Application / Click "Login"
    B->>C: GET /login
    C-->>B: 302 Redirect to Authorization Server /authorize
    B->>AS: GET /authorize (client_id, redirect_uri, response_type=code, scope, state)
    AS->>U: Display Login & Consent Screen
    U->>AS: Submit Credentials & Approve Permissions
    AS-->>B: 302 Redirect to redirect_uri with ?code=AUTH_CODE&state=STATE
    B->>C: GET /callback?code=AUTH_CODE&state=STATE
    C->>AS: POST /oauth/token (grant_type=authorization_code, code, redirect_uri, client_secret)
    AS-->>C: 200 OK (access_token, token_type, expires_in, refresh_token, id_token)
    C-->>B: Set secure HTTP-only session cookie & redirect to Dashboard
    B->>C: GET /dashboard (with session cookie)
    C->>RS: GET /api/data (Authorization: Bearer ACCESS_TOKEN)
    RS-->>C: 200 OK (Protected Data)
    C-->>B: Render Dashboard

Step-by-Step Flow Breakdown

Detailed breakdown of every message exchange, query parameter, and HTTP payload

1

User Initiates Login

User→Browser

The user clicks the "Log In" button or navigates to a protected route in the web application.

2

Request Login Endpoint

Browser→Client App (Backend)

The browser sends a request to the web application backend endpoint that initiates the OAuth flow.

Browser initiates authentication
GET /login HTTP/1.1
Host: myapp.com
3

Redirect to Authorization Server

Client App (Backend)→Browser

The backend generates an unguessable CSRF state parameter and redirects the user browser to the Authorization Server authorization endpoint with query parameters.

HTTP 302 Redirect
HTTP/1.1 302 Found
Location: https://auth.example.com/authorize?
    response_type=code
    &client_id=my_client_id_123
    &redirect_uri=https%3A%2F%2Fmyapp.com%2Fcallback
    &scope=openid%20profile%20email
    &state=c29tZV9yYW5kb21fc3RhdGU=
4

Authorization Request

Browser→Authorization Server

The browser follows the redirect and issues the GET request to the Authorization Server authorization endpoint.

Authorization Request
GET /authorize?response_type=code&client_id=my_client_id_123&redirect_uri=https%3A%2F%2Fmyapp.com%2Fcallback&scope=openid%20profile%20email&state=c29tZV9yYW5kb21fc3RhdGU= HTTP/1.1
Host: auth.example.com
5

User Authentication & Consent

Authorization Server→User

The Authorization Server prompts the user for credentials (username/password, MFA, WebAuthn) and displays a consent prompt describing requested scopes.

6

User Approval

User→Authorization Server

The user enters their credentials and confirms permission for the application to access the requested data.

7

Redirect Back with Authorization Code

Authorization Server→Browser

The Authorization Server generates a short-lived, single-use authorization code and redirects the browser back to the registered callback URI.

IdP Redirect with Code
HTTP/1.1 302 Found
Location: https://myapp.com/callback?
    code=SplxlOBeZQQYbYS6WxSbIA
    &state=c29tZV9yYW5kb21fc3RhdGU=
8

Deliver Authorization Code to Backend

Browser→Client App (Backend)

The browser follows the redirect and delivers the authorization code and state parameter to the application backend.

Callback Request
GET /callback?code=SplxlOBeZQQYbYS6WxSbIA&state=c29tZV9yYW5kb21fc3RhdGU= HTTP/1.1
Host: myapp.com
9

Exchange Authorization Code for Tokens

Client App (Backend)→Authorization Server

The backend verifies that the received state matches the stored session state, then sends a POST request to the token endpoint with the authorization code and confidential client credentials.

Token Exchange Request
POST /oauth/token HTTP/1.1
Host: auth.example.com
Authorization: Basic bXlfY2xpZW50X2lkXzEyMzpteV9jbGllbnRfc2VjcmV0Xzc4OQ==
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fmyapp.com%2Fcallback
10

Tokens Returned

Authorization Server→Client App (Backend)

The Authorization Server verifies the authorization code and client secret, ensures the code has not expired or been reused, and returns access, ID, and refresh tokens.

Token Response
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
  "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjE2In0..."
}
11

Establish Authenticated Session

Client App (Backend)→Browser

The application backend stores tokens securely on the server and issues an encrypted, HTTP-only, SameSite session cookie to the browser.

Session Cookie Set
HTTP/1.1 302 Found
Location: /dashboard
Set-Cookie: session_id=s%3A9f8a7e6d5c4b3a...; Path=/; HttpOnly; Secure; SameSite=Lax
12

Authorized API Request

Client App (Backend)→Resource Server (API)

When data is needed, the backend uses the Bearer access token to request protected resources from downstream APIs.

API Request with Bearer Token
GET /api/v1/profile HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

Security Considerations

Critical safeguards, threat mitigations, and implementation best practices

Always Validate the State Parameter

A unique cryptographically random state parameter must be created for every authorization request to prevent Cross-Site Request Forgery (CSRF). Verify the returned state matches the stored session before redeeming the authorization code.

Protect the Client Secret

Client secrets must only be stored and used in backend environments. Never embed client secrets in client-side code, mobile binaries, or browser apps.

Strict Redirect URI Matching

The authorization server must enforce exact string matching for redirect URIs. Wildcards or permissive pattern matching can lead to authorization code theft.

Add PKCE for Defense in Depth

Even confidential clients benefit from PKCE (Proof Key for Code Exchange) to prevent authorization code injection attacks. OAuth 2.1 recommends PKCE for all client types.

Specifications & Standards

Official IETF RFCs and OpenID Foundation standards defining this flow

Client Templates using this Grant Type

Explore ready-to-use client configurations supporting Authorization Code

All templates

Other OAuth 2.0 Grant Types

Compare with other authentication and authorization flows