Skip to main content

OAuth

OAuth 2.0 is a delegation protocol — it lets users authorize applications to act on their behalf, granting access to resources via access tokens.

Instead of apps storing user credentials, they request access tokens from an authorization server, which are then used to access protected APIs.

Core Roles

RoleDescription
Resource OwnerThe user who owns the data (e.g., you)
ClientThe third-party app accessing data (e.g., Spotify)
Authorization ServerIssues tokens (e.g., Google, Auth0)
Resource ServerAPI that hosts the user’s resources (e.g., api.example.com)

Authorization Flows (Grant Types)

Grant TypeUse Case
Authorization CodeWeb apps with frontend + backend (most secure)
Client CredentialsMachine-to-machine (M2M) apps (no user)
Password GrantTrusted apps (deprecated for public use)
Implicit FlowSingle-page apps (deprecated in favor of PKCE)
Authorization Code + PKCERecommended for mobile/SPAs (secure public clients)

Steps of OAuth

1. App Redirects User to Authorization Server

GET https://auth.example.com/oauth/authorize?
response_type=code
&client_id=abc123
&redirect_uri=https://app.example.com/callback
&scope=email profile
&state=xyz

User logs in and consents.

2. Authorization Server Redirects with Code

GET https://app.example.com/callback?code=AUTH_CODE&state=xyz

3. App Requests Token

POST https://auth.example.com/oauth/token
Content-Type: application/x-www-form-urlencoded

client_id=abc123
&client_secret=shhh
&code=AUTH_CODE
&grant_type=authorization_code
&redirect_uri=https://app.example.com/callback

Response:

{
"access_token": "eyJabc...xyz",
"refresh_token": "def456...",
"token_type": "Bearer",
"expires_in": 3600
}

4. App Uses Access Token to Call API

GET https://api.example.com/user/email
Authorization: Bearer eyJabc...xyz

Response:

{
"email": "user@example.com"
}

5. Refresh Access Token (When expired)

POST https://auth.example.com/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=def456...
&client_id=abc123
&client_secret=shhh

OpenID Connect

  • OpenID Connect is an identity layer built on top of OAuth 2.0.
  • It adds authentication — confirming who the user is.
  • In addition to access_token, OIDC issues an ID Token (a JWT) containing user identity information.

So:

  • OAuth 2.0 = Delegated Authorization (what app can do)
  • OIDC = Authentication + Authorization (who the user is + what app can do)

How OIDC Works

OIDC uses the same flows as OAuth 2.0 but adds the id_token.

ID Token

  • A JWT (JSON Web Token) signed by the Identity Provider.
  • Contains user claims:
{
"sub": "1234567890",
"name": "Masum Billah",
"email": "masum@example.com",
"iss": "https://auth.example.com/",
"aud": "abc123",
"exp": 1694200300
}

OIDC Flow

  1. Client app redirects user to the Identity Provider with openid scope:
GET https://auth.example.com/authorize?
response_type=code&
client_id=abc123&
redirect_uri=https://myapp.com/callback&
scope=openid profile email
  1. After login & consent → client exchanges code for tokens:
POST /oauth/token
grant_type=authorization_code
code=xyz789
client_id=abc123
client_secret=shhh456

Response:

{
"access_token": "eyJhbGciOiJIUzI1...",
"id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI...",
"expires_in": 3600,
"token_type": "Bearer"
}
  1. The access_token → used to call APIs. The id_token → used to authenticate the user (who they are).

OAuth 2.0 vs OIDC

FeatureOAuth 2.0OpenID Connect (OIDC)
PurposeAuthorization (what app can do)Authentication + Authorization
Tokens ReturnedAccess Token (and Refresh Token)Access Token + ID Token
Identity Info❌ Not included✅ Provided in ID Token
Example Use CaseAllow app to access Google DriveLogin with Google

JSON Web Tokens

A JWT (JSON Web Token) is a compact, URL-safe token format used to securely transmit information between a client and server.

It’s a string with 3 parts (separated by dots .):

header.payload.signature

It’s often used as a Bearer Token in REST APIs for authentication & authorization.

JWT Structure

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.
eyJzdWIiOiIxMjM0NTYiLCJuYW1lIjoiTWFzdW0gQmlsbGFoIiwiYWRtaW4iOnRydWV9
.
hTDiVfVhS5jqCmyFfXqS-H6vIbiV9TnQ7s02jjCddJY
  1. Header

Defines metadata: algorithm & type. (Base64 encoded JSON)

{
"alg": "HS256",
"typ": "JWT"
}
  1. Payload

Contains claims (the actual data). (Base64 encoded JSON)

{
"sub": "123456",
"name": "Masum Billah",
"admin": true,
"exp": 1736790400
}
  • sub: Subject (user ID)
  • exp: Expiry time (Unix timestamp)
  • name, admin: Custom claims
  1. Signature

Ensures the token isn’t tampered with.

HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )

Best Practices

  • Keep JWTs short-lived (exp claim).
  • Use refresh tokens for long sessions.
  • Always send via Authorization: Bearer header (not query params).
  • Sign with strong algorithms (HS256, RS256).
  • Validate issuer (iss), audience (aud), and expiry (exp).