Oauth_jwt
Chapter 37: OAuth 2.0 & JWT
Section titled “Chapter 37: OAuth 2.0 & JWT”Modern Authentication & Authorization
Section titled “Modern Authentication & Authorization”37.1 OAuth 2.0 Overview
Section titled “37.1 OAuth 2.0 Overview”OAuth 2.0 is the industry standard for authorization - allowing third-party applications to access user resources without sharing passwords.
The Problem OAuth Solves =======================
Before OAuth: ────────────────── "Login with Facebook"
User enters Facebook password MyApp sees: password
Problems: • MyApp has full account access • If MyApp is breached, password stolen • Can't revoke access without changing password
─────────────────────────────────────────
With OAuth 2.0: ────────────────── "Login with Facebook"
Facebook shows: "MyApp wants to access your name and email"
User approves
MyApp gets: limited access token
Benefits: • MyApp never sees password • User can revoke access anytime • Limited permissions37.2 OAuth 2.0 Flows
Section titled “37.2 OAuth 2.0 Flows”Authorization Code Flow (Web Apps)
Section titled “Authorization Code Flow (Web Apps)” Authorization Code Flow =====================
┌──────────┐ ┌──────────────┐ │ User │ │ Auth │ │(Browser) │ │ Server │ └────┬─────┘ │ (Google, │ │ │ Facebook) │ │ 1. Click "Login with Google" │ │ │────────────────────────────────▶│ │ │ 2. Show │ │ 3. Redirect │ consent │ │◀────────────────────────────────│ screen │ │ (consent screen) │ │ │ │ │ │ 4. User grants permission │ │ │────────────────────────────────▶│ │ │ │ │ │ 5. Redirect with code │ │ │◀────────────────────────────────│ ?code= │ │ code=abc123 │ abc123 │ │ │ │ │ │ │ │ 6. Exchange code for tokens │ │ │────────────────────────────────▶│ │ │ │ │ │ 7. Return tokens │ │ │◀────────────────────────────────│ { │ │ {access_token, │ access_ │ │ refresh_token} │ token:.. │ │ │ } │Client Credentials Flow (Machine-to-Machine)
Section titled “Client Credentials Flow (Machine-to-Machine)” Client Credentials Flow =====================
Used for server-to-server communication
┌──────────────┐ ┌──────────────┐ │ My Server │ │ Auth Server │ └───────┬──────┘ └──────┬───────┘ │ │ │ POST /oauth/token │ │ Content-Type: application/x-www-form │ │ │ │ grant_type=client_credentials │ │ &client_id=myapp │ │ &client_secret=secret123 │ │────────────────────────────────────────▶│ │ │ │ { │ │ "access_token": "eyJhbG...", │ │ "token_type": "Bearer", │ │ "expires_in": 3600 │ │ } │ │◀────────────────────────────────────────│PKCE Flow (Mobile/SPA)
Section titled “PKCE Flow (Mobile/SPA)” PKCE (Proof Key for Code Exchange) ==================================
Adds security for public clients (no client secret)
┌─────────────────────────────────────────────────────────────┐ │ 1. Generate random string (code_verifier) │ │ code_verifier = dBjftJeZ4CVP-mB92K27uhbUJU1p1r │ │ │ │ 2. Create hash (code_challenge) │ │ code_challenge = BASE64URL(SHA256(code_verifier)) │ │ │ │ 3. Authorization request includes code_challenge │ │ │ │ 4. Auth server stores code_challenge │ │ │ │ 5. Token request includes code_verifier │ │ │ │ 6. Auth server verifies code_verifier matches │ │ original code_challenge │ └─────────────────────────────────────────────────────────────┘
This prevents authorization code interception attacks!37.3 JWT Deep Dive
Section titled “37.3 JWT Deep Dive”JWT Structure
Section titled “JWT Structure” JWT = Header.Payload.Signature ═══════════════════════════════
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c ════════════════════════╬═══════════════════════════════════╬═══════════════════════════════════════════════════════ Header Payload Signature
─────────────────────────────────────────────────────────────
HEADER: Algorithm and token type ─────────────────────────────── { "alg": "HS256", // HMAC using SHA-256 "typ": "JWT" }
─────────────────────────────────────────────────────────────
PAYLOAD: Claims (data) ───────────────────── { "iss": "https://auth.example.com", // Issuer "sub": "user-123", // Subject (user ID) "aud": "my-api", // Audience "exp": 1700000000, // Expiration "iat": 1699999999, // Issued at "nbf": 1699999999, // Not before "jti": "unique-token-id", // JWT ID
// Custom claims "name": "John Doe", "role": "admin", "permissions": ["read", "write"] }
─────────────────────────────────────────────────────────────
SIGNATURE: Verify token wasn't tampered ────────────────────────────────────────── HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret_key )JWT Signing Algorithms
Section titled “JWT Signing Algorithms”| Algorithm | Type | Use Case |
|---|---|---|
| HS256 | Symmetric | Simple apps, same server |
| RS256 | Asymmetric | Distributed systems, microservices |
| ES256 | Elliptic Curve | Mobile apps, smaller tokens |
# HS256 (Symmetric - same key for sign/verify)import jwt
secret = "my_secret_key"
# Create tokentoken = jwt.encode( {"user_id": "123", "role": "admin"}, secret, algorithm="HS256")
# Verify tokendecoded = jwt.decode(token, secret, algorithms=["HS256"])print(decoded) # {'user_id': '123', 'role': 'admin'}
# RS256 (Asymmetric - private key sign, public key verify)import jwtfrom cryptography.hazmat.primitives import serializationfrom cryptography.hazmat.backends import default_backend
# Load keyswith open("private_key.pem", "rb") as f: private_key = serialization.load_pem_private_key( f.read(), password=None, backend=default_backend() )
with open("public_key.pem", "rb") as f: public_key = serialization.load_pem_public_key( f.read(), backend=default_backend() )
# Create token with private keytoken = jwt.encode( {"user_id": "123"}, private_key, algorithm="RS256")
# Verify with public keydecoded = jwt.decode(token, public_key, algorithms=["RS256"])37.4 OAuth Scopes
Section titled “37.4 OAuth Scopes”Scopes limit what the access token can do.
OAuth Scopes ===========
Request: ───────────────────────────────────────── GET /oauth/authorize? client_id=myapp& redirect_uri=https://myapp.com/callback& response_type=code& scope=read:profile write:profile read:email
Available scopes (defined by auth server): ───────────────────────────────────────── ┌─────────────────┬──────────────────────────────────┐ │ Scope │ Description │ ├─────────────────┼──────────────────────────────────┤ │ read:profile │ Read user profile info │ │ write:profile │ Update user profile │ │ read:email │ Read email address │ │ read:contacts │ Read contacts list │ │ publish │ Publish content │ └─────────────────┴──────────────────────────────────┘
User Consent Screen: ───────────────────────────────────────── "MyApp wants to access your account:"
☑ Read your profile ☑ Update your profile ☑ Read your email
[Allow] [Cancel]37.5 Token Management
Section titled “37.5 Token Management”Access vs Refresh Tokens
Section titled “Access vs Refresh Tokens” Token Types Comparison =====================
┌─────────────────────────────────┬─────────────────────────────────┐ │ Access Token │ Refresh Token │ ├─────────────────────────────────┼─────────────────────────────────┤ │ Short-lived (15 min - 1 hour) │ Long-lived (days - weeks) │ │ │ │ │ Included in API requests │ Used to get new access tokens │ │ │ │ │ Never stored long-term │ Stored securely server-side │ │ │ │ │ If stolen: limited damage │ If stolen: can get new access │ │ │ (but can be revoked) │ └─────────────────────────────────┴─────────────────────────────────┘
Token Lifecycle: ─────────────────────────────────────────
1. User logs in │ ▼ 2. Receive: access_token + refresh_token │ ▼ 3. Use access_token for API calls │ ▼ 4. Access token expires (e.g., 1 hour) │ ▼ 5. Use refresh_token to get new access_token │ ▼ 6. Repeat 3-5 until refresh_token expires │ ▼ 7. User must log in againRefresh Token Flow
Section titled “Refresh Token Flow” Refreshing Tokens =================
┌──────────┐ ┌──────────────┐ │ Client │ │ Auth Server │ └────┬─────┘ └──────┬───────┘ │ │ │ POST /oauth/token │ │ Content-Type: application/x-www-form │ │ │ │ grant_type=refresh_token │ │ &refresh_token=rt_abc123 │ │ &client_id=myapp │ │────────────────────────────────────────▶│ │ │ │ Validate refresh token: │ │ - Not expired? │ │ - Not revoked? │ │ - Belongs to this client? │ │ │ │ { │ │ "access_token": "eyJhbG...", │ │ "token_type": "Bearer", │ │ "expires_in": 3600, │ │ "refresh_token": "rt_xyz789", ← New refresh token │ "scope": "read:profile" │ │ } │ │◀────────────────────────────────────────│37.6 Security Best Practices
Section titled “37.6 Security Best Practices” OAuth & JWT Security Checklist =============================
✓ Use HTTPS for all OAuth endpoints ✓ Use PKCE for mobile/SPA apps ✓ Validate all tokens server-side ✓ Short-lived access tokens (< 1 hour) ✓ Long-lived refresh tokens (with rotation) ✓ Store refresh tokens securely ✓ Implement token revocation ✓ Validate audience (aud claim) ✓ Check expiration (exp claim) ✓ Use RS256 for distributed systemsSummary
Section titled “Summary”- OAuth 2.0 - Authorization framework for delegated access
- Authorization Code Flow - Web apps with user involvement
- Client Credentials - Machine-to-machine
- PKCE - Mobile/SPA security
- JWT - Compact, URL-safe tokens
- Access tokens - Short-lived, for API calls
- Refresh tokens - Long-lived, for getting new access tokens
- Scopes - Limit permissions