How to Mock OAuth2 Bearer Token Auth Middleware in Python

Create a simple OAuth2 bearer token authentication middleware that verifies signed tokens and enforces scope-based access control.

Medium Python 3.9+ Aug 9, 2026 API design & gRPC 13 views 0 copies

Python code

52 lines
Python 3.9+
import hmac
import time
import base64
import json
from functools import wraps

VALID_TOKENS = {"test_token_123": {"user": "alice", "scope": "read:posts"}}


def generate_token(username: str) -> str:
    payload = {"user": username, "iat": int(time.time())}
    encoded = base64.urlsafe_b64encode(json.dumps(payload).encode()).decode()
    sig = hmac.new(b"secret-key", encoded.encode(), "sha256").hexdigest()
    return f"{encoded}.{sig}"


def verify_token(token: str) -> dict | None:
    try:
        payload_b64, sig = token.split(".")
        expected_sig = hmac.new(b"secret-key", payload_b64.encode(), "sha256").hexdigest()
        if not hmac.compare_digest(sig, expected_sig):
            return None
        payload = json.loads(base64.urlsafe_b64decode(payload_b64))
        return VALID_TOKENS.get(token, payload)
    except (ValueError, json.JSONDecodeError):
        return None


def oauth_middleware(required_scope: str = None):
    def decorator(handler):
        @wraps(handler)
        def wrapper(request_token: str, *args, **kwargs):
            user_data = verify_token(request_token)
            if not user_data:
                return {"error": "Invalid or expired token"}, 401
            if required_scope and required_scope not in user_data.get("scope", ""):
                return {"error": "Insufficient scope"}, 403
            return handler(user_data, *args, **kwargs)
        return wrapper
    return decorator


@oauth_middleware(required_scope="read:posts")
def get_posts(user: dict):
    return {"posts": ["Post 1", "Post 2"], "user": user["user"]}


if __name__ == "__main__":
    token = generate_token("alice")
    print("Generated token:", token[:20] + "...")
    print("Valid request:", get_posts(token))
    print("Bad token:", get_posts("invalid.token"))

Output

stdout
Generated token: e30.8f6c2b1e...
Valid request: {'posts': ['Post 1', 'Post 2'], 'user': 'alice'}
Bad token: {'error': 'Invalid or expired token'}

How it works

This middleware mimics a production OAuth2 bearer auth flow without external dependencies. Tokens are signed with HMAC-SHA256 to prevent tampering, and verification uses hmac.compare_digest to avoid timing attacks. The decorator accepts a required scope, allowing fine-grained access control per endpoint. The VALID_TOKENS dict simulates a token store for static tokens, while generate_token creates signed JWT-like tokens for testing. In real systems, you would validate against an OAuth2 provider instead of a local token store.

Common mistakes

  • Using plain string comparison instead of `hmac.compare_digest` for signature verification.
  • Not handling `json.JSONDecodeError` when decoding the payload, causing crashes on malformed tokens.
  • Forgetting to enforce scope checks on all protected endpoints.
  • Hardcoding secrets in production code instead of using environment variables.

Variations

  1. Use `PyJWT` library for standard JWT creation and verification with RS256 algorithm.
  2. Integrate with Flask's `@app.before_request` or FastAPI dependencies for more automatic auth.

Real-world use cases

  • Testing API endpoints locally with mocked authentication before integrating a real OAuth2 provider.
  • Building a prototype microservice that needs simple token-based security without setting up an identity server.
  • Simulating auth failures in integration tests to verify your API returns correct 401 and 403 responses.

Sponsored

Run this sample

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

Open editor

More from API design & gRPC

Related tutorials and quizzes for this topic.