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
| Role | Description |
|---|---|
| Resource Owner | The user who owns the data (e.g., you) |
| Client | The third-party app accessing data (e.g., Spotify) |
| Authorization Server | Issues tokens (e.g., Google, Auth0) |
| Resource Server | API that hosts the user’s resources (e.g., api.example.com) |
Authorization Flows (Grant Types)
| Grant Type | Use Case |
|---|---|
| Authorization Code | Web apps with frontend + backend (most secure) |
| Client Credentials | Machine-to-machine (M2M) apps (no user) |
| Password Grant | Trusted apps (deprecated for public use) |
| Implicit Flow | Single-page apps (deprecated in favor of PKCE) |
| Authorization Code + PKCE | Recommended 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
- Client app redirects user to the Identity Provider with
openidscope:
GET https://auth.example.com/authorize?
response_type=code&
client_id=abc123&
redirect_uri=https://myapp.com/callback&
scope=openid profile email
- 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"
}
- The access_token → used to call APIs. The id_token → used to authenticate the user (who they are).
OAuth 2.0 vs OIDC
| Feature | OAuth 2.0 | OpenID Connect (OIDC) |
|---|---|---|
| Purpose | Authorization (what app can do) | Authentication + Authorization |
| Tokens Returned | Access Token (and Refresh Token) | Access Token + ID Token |
| Identity Info | ❌ Not included | ✅ Provided in ID Token |
| Example Use Case | Allow app to access Google Drive | Login 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
- Header
Defines metadata: algorithm & type. (Base64 encoded JSON)
{
"alg": "HS256",
"typ": "JWT"
}
- 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
- Signature
Ensures the token isn’t tampered with.
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret )
Best Practices
- Keep JWTs short-lived (
expclaim). - Use refresh tokens for long sessions.
- Always send via
Authorization: Bearerheader (not query params). - Sign with strong algorithms (HS256, RS256).
- Validate issuer (
iss), audience (aud), and expiry (exp).