OAuth2 authorization code flow mock in Python

A minimal HTTP server that mocks the OAuth2 authorization code flow, issuing codes via /authorize and exchanging them for tokens at /token.

Medium Python 3.9+ Aug 9, 2026 Auth & security at scale 14 views 0 copies

Python code

50 lines
Python 3.9+
import json
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import urlparse, parse_qs

AUTH_CODE_STORE = {}
CLIENT_ID = "demo-client"
REDIRECT_URI = "http://localhost:8000/callback"

class OAuthHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        parsed = urlparse(self.path)
        if parsed.path == "/authorize":
            params = parse_qs(parsed.query)
            if params.get("client_id", [None])[0] == CLIENT_ID:
                code = "auth_code_123"
                AUTH_CODE_STORE[code] = params["redirect_uri"][0]
                self.send_response(302)
                self.send_header("Location", f"{params['redirect_uri'][0]}?code={code}")
                self.end_headers()
            else:
                self.send_response(400)
                self.end_headers()
                self.wfile.write(b"Invalid client_id")
        elif parsed.path == "/token":
            length = int(self.headers.get("Content-Length", 0))
            body = self.rfile.read(length).decode()
            params = parse_qs(body)
            code = params.get("code", [None])[0]
            if code in AUTH_CODE_STORE and params.get("redirect_uri", [None])[0] == AUTH_CODE_STORE[code]:
                token = {"access_token": "access_xyz", "token_type": "Bearer", "expires_in": 3600}
                self.send_response(200)
                self.send_header("Content-Type", "application/json")
                self.end_headers()
                self.wfile.write(json.dumps(token).encode())
            else:
                self.send_response(400)
                self.end_headers()
                self.wfile.write(b"Invalid code or redirect_uri")
        else:
            self.send_response(404)
            self.end_headers()

    def log_message(self, format, *args):
        pass

if __name__ == "__main__":
    server = HTTPServer(("localhost", 8000), OAuthHandler)
    print("Mock OAuth2 server running on http://localhost:8000")
    print(f"Authorize: http://localhost:8000/authorize?client_id={CLIENT_ID}&redirect_uri={REDIRECT_URI}")
    server.serve_forever()

Output

stdout
Mock OAuth2 server running on http://localhost:8000
Authorize: http://localhost:8000/authorize?client_id=demo-client&redirect_uri=http://localhost:8000/callback

How it works

This mock server implements the two key endpoints of the OAuth2 authorization code flow. The /authorize endpoint validates the client_id, stores the redirect_uri paired with a generated code, and issues a 302 redirect carrying the code. The /token endpoint reads the form-encoded body, checks that the code exists and the redirect_uri matches what was stored during authorization, then returns a JSON access token. AUTH_CODE_STORE is a simple in-memory dict that mimics how a real authorization server tracks codes before they are exchanged. This pattern lets you test OAuth2 clients locally without relying on an external identity provider.

Common mistakes

  • Not checking that the redirect_uri matches exactly what was stored at /authorize time
  • Using a fixed code like 'auth_code_123' instead of generating unique values per request
  • Forgetting to read Content-Length and decoding the request body properly
  • Returning 302 without setting the Location header correctly

Variations

  1. Use secrets.token_urlsafe(32) instead of a hardcoded code for better uniqueness
  2. Add an expire timestamp to codes and a cleanup routine to remove used codes

Real-world use cases

  • Testing an OAuth2 client library locally without needing a real identity provider or network access.
  • Simulating authorization flows in integration tests to validate redirect and token exchange logic.
  • Prototyping an API that consumes OAuth2-protected resources before the production auth service is ready.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Auth & security at scale

Related tutorials and quizzes for this topic.