Authorization Code Flow

02 Mins

The Authorization Code Flow is the most common OAuth/OIDC flow used by web applications.

This is the flow behind:

  • Login with Google
  • Login with GitHub
  • Login with Microsoft

It is designed to securely authenticate users without exposing credentials to your application.


High-Level Flow

[Your App]
  → Redirect user to Google login

[Google]
  → User logs in and grants permissions
  → Google returns authorization code

[Your Backend]
  → Exchanges code for tokens
  → Verifies ID token
  → Creates session/JWT in your system

At a high level:

  1. User authenticates with Google
  2. Google proves identity using tokens
  3. Your backend establishes its own authenticated session

Step 1 - Redirect User to Provider

Your backend redirects the user to Google’s authorization endpoint.

Example:

https://accounts.google.com/o/oauth2/v2/auth
?client_id=...
&redirect_uri=...
&response_type=code
&scope=openid email profile

Important query parameters:

ParameterPurpose
client_idIdentifies your application
redirect_uriWhere Google sends the user back
response_type=codeEnables Authorization Code Flow
scopeDefines requested permissions

The openid scope is especially important because it enables OpenID Connect (OIDC). Without openid, you get OAuth authorization only - not authentication. Additional scopes like: email profile allow access to user profile information.


Google shows:

  • login screen
  • account selection
  • permissions consent screen

After successful authentication, Google redirects the user back to your backend:

redirect_uri?code=XYZ123

The code is a temporary authorization code.

Important properties:

  • short-lived
  • one-time use
  • exchanged server-side for tokens

The code itself is not the final authentication token.


Step 3 - Backend Exchanges Code for Tokens

Your backend sends the authorization code to Google’s token endpoint.

Example request:

POST https://oauth2.googleapis.com/token

Example body:

{
  "code": "...",
  "client_id": "...",
  "client_secret": "...",
  "redirect_uri": "...",
  "grant_type": "authorization_code"
}

Google responds with tokens:

{
  "access_token": "...",
  "id_token": "...",
  "refresh_token": "...",
  "expires_in": 3600
}

Understanding the Tokens

TokenPurpose
access_tokenAccess Google APIs
id_tokenAuthenticate the user
refresh_tokenObtain new access tokens

Access Token

Used when your app needs to call Google APIs.

Example:

GET https://www.googleapis.com/calendar/v3/...
Authorization: Bearer <access_token>

ID Token

The ID token is the most important token for authentication. It is usually a JWT containing identity information such as:

  • user ID (sub)
  • email
  • issuer
  • expiration time

The ID token proves:

“Google successfully authenticated this user.”

Refresh Token

Refresh tokens are long-lived credentials used to obtain new access tokens.

They are typically issued only when:

  • offline access is requested
  • the provider allows persistent access

PKCE (Proof Key for Code Exchange)

Many providers now require PKCE even for server-side flows. PKCE binds the authorization code to a one-time secret generated by your app, preventing interception attacks.


Step 4 - Backend Verifies ID Token

Your backend must verify the ID token before trusting it.

Verification usually includes:

  • verifying the JWT signature
  • checking the issuer (iss)
  • checking the audience (aud)
  • checking expiration (exp)

If verification succeeds: User identity is trusted

This step is critical.

Anyone can decode a JWT, but only properly signed tokens should be accepted as valid.


Step 5 - Backend Creates Its Own Session

Google authenticates the user, but Google does not manage your application’s session system.

Your backend still needs to:

  • find or create the user
  • create internal user records
  • establish authentication state
  • issue your own JWT or session cookie

Typical flow:

Google authenticates user
  → Your backend verifies identity
  → Your app creates its own session

This distinction is extremely important.

OAuth/OIDC handles external authentication. Your application still controls sessions, permissions, and authorization.


Why This Flow Is Secure

The Authorization Code Flow is designed so that:

  • user credentials never reach your app
  • sensitive token exchange happens server-side
  • tokens are issued only after successful authentication
  • ID tokens can be cryptographically verified

This makes it safer than directly handling user passwords in third-party integrations.