OAuth 2.1 Implementation

OAuth 2.1 Implementation

Complete implementations of the OAuth 2.1 authorization code flow with PKCE in both Go and Python, designed for educational purposes.

Overview

This project demonstrates OAuth 2.1 through three interconnected applications that communicate using standard OAuth protocols. It’s designed to provide hands-on learning about OAuth security mechanisms, message exchanges, and implementation patterns.

What You’ll Learn

  • OAuth 2.1 authorization code flow with mandatory PKCE
  • Three-component OAuth architecture
  • Security best practices and mechanisms
  • Real-world implementation patterns
  • Differences between OAuth 2.0 and 2.1

Available Implementations

Go Implementation

The Go implementation provides:

  • Clean HTTP server implementation
  • Session management with cookies
  • Bcrypt password hashing
  • Detailed console logging
  • Browser-based testing interface

View Go implementation →

Python Implementation

The Python implementation features:

  • FastAPI with async/await patterns
  • Pydantic models for validation
  • Jinja2 templates
  • Automated testing scripts
  • Multi-server management tools

View Python implementation →

Quick Start

Go Version

# Clone and setup
git clone https://github.com/hardwaylabs/learn-oauth-go
cd learn-oauth-go
go mod tidy

# Start all three servers (in separate terminals)
go run cmd/auth-server/main.go     # Port 8081
go run cmd/resource-server/main.go # Port 8082
go run cmd/client/main.go          # Port 8080

# Open browser to http://localhost:8080

Python Version

# Clone and setup
git clone https://github.com/hardwaylabs/learn-oauth-python
cd learn-oauth-python

# Install dependencies
uv sync  # or pip install -r requirements.txt

# Start all servers
python scripts/start_all.py

# Open browser to http://localhost:8080

Demo Accounts

Both implementations include these test accounts:

  • alice / password123
  • bob / secret456
  • carol / mypass789

OAuth 2.1 Flow Walkthrough

Step 1: Authorization Request

The client generates a PKCE challenge and redirects to the authorization server:

GET /authorize?
  client_id=demo-client&
  redirect_uri=http://localhost:8080/callback&
  scope=read&
  state=demo-state-123&
  code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&
  code_challenge_method=S256&
  response_type=code

Step 2: User Authentication

User logs in at the authorization server. The server validates credentials against bcrypt-hashed passwords.

Step 3: Authorization Grant

After successful authentication, the server redirects back with an authorization code:

GET /callback?
  code=abc123xyz&
  state=demo-state-123

Step 4: Token Exchange

The client exchanges the code + PKCE verifier for an access token:

POST /token
  grant_type=authorization_code&
  code=abc123xyz&
  redirect_uri=http://localhost:8080/callback&
  client_id=demo-client&
  code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

Step 5: Resource Access

The client uses the Bearer token to access protected resources:

GET /protected
Authorization: Bearer def456...

Key Security Features

PKCE (Proof Key for Code Exchange)

Prevents authorization code interception attacks:

  1. Client generates random 43-character verifier
  2. Client sends SHA256 hash as challenge
  3. Client proves possession of verifier during token exchange
  4. Server only issues token if PKCE verification succeeds

Additional Security

  • State parameter: CSRF protection
  • Code expiration: 10-minute lifetime
  • One-time use: Codes invalidated after exchange
  • Bcrypt hashing: Secure password storage

OAuth 2.1 vs OAuth 2.0

Key improvements in OAuth 2.1:

FeatureOAuth 2.0OAuth 2.1
PKCEOptional for public clientsMandatory for all clients
Implicit flowSupportedRemoved (security risk)
Password grantSupportedRemoved (security risk)
Security defaultsVarious optionalMandatory protections

Architecture

┌─────────────────┐    ┌──────────────────────┐    ┌─────────────────┐
│   Client App    │    │ Authorization Server │    │ Resource Server │
│   Port 8080     │◄──►│     Port 8081        │    │    Port 8082    │
│                 │    │                      │    │                 │
│ • PKCE Gen      │    │ • User Auth          │    │ • Token Valid   │
│ • Token Storage │    │ • Code Generation    │    │ • Protected Res │
│ • Resource Req  │    │ • Token Issuance     │    │ • User Info API │
└─────────────────┘    └──────────────────────┘    └─────────────────┘

Advanced Features

Dynamic Client Registration

Both implementations support RFC 7591 dynamic client registration:

curl -X POST http://localhost:8081/register \
  -H "Content-Type: application/json" \
  -d '{
    "redirect_uris": ["http://localhost:3000/callback"],
    "client_name": "My OAuth Client"
  }'

OAuth Discovery

Discovery endpoints provide automatic configuration:

curl http://localhost:8081/.well-known/oauth-authorization-server

Real-World Applications

Web Applications

  • Browser-based flows with PKCE
  • Session management
  • Automatic token refresh

CLI Applications

  • Device authorization grant (RFC 8628)
  • Local callback servers
  • Secure token storage

Mobile Applications

  • Native app flows
  • Custom URL schemes
  • Biometric protection

Troubleshooting

Common Issues

“Invalid credentials”: Check password hashes match demo accounts

“PKCE verification failed”: Ensure verifier is properly stored between requests

Port conflicts: Kill existing processes or change ports in configuration

“Code not found”: Complete flow within 10-minute expiration

Extensions

After mastering the basics, try:

  1. Add refresh tokens with rotation
  2. Implement token introspection (RFC 7662)
  3. Add scopes and permissions
  4. Build client authentication
  5. Create a single sign-on system

Resources

Support