Skip to main content

MCP OAuth Dynamic Client Registration Server - OAuth 2.1 and RFC 7591 compliant

Project description

mcp-oauth-dynamicclient

A production-ready OAuth 2.1 library with Dynamic Client Registration (RFC 7591/7592) support, designed for Model Context Protocol (MCP) integration. This package provides the core OAuth implementation used by the MCP OAuth Gateway.

Overview

This library implements:

  • OAuth 2.1: Full authorization server implementation with PKCE
  • RFC 7591: Dynamic client registration for self-service OAuth clients
  • RFC 7592: Client configuration management endpoints
  • GitHub Integration: Built-in GitHub OAuth provider support
  • JWT Tokens: Secure token generation with customizable claims
  • Redis Backend: Scalable storage for tokens and client data

Key Features

  • 🔐 Complete OAuth 2.1 Implementation: Authorization code flow with PKCE
  • 📝 Dynamic Client Registration: Self-service client onboarding via RFC 7591
  • 🔧 Client Management API: Full CRUD operations via RFC 7592
  • 🎫 JWT Token Generation: HS256-signed tokens with configurable lifetime
  • 🌐 GitHub OAuth Integration: Pre-configured GitHub provider support
  • 📦 Redis Storage: Production-ready persistence layer
  • 🔒 ForwardAuth Support: Token validation for reverse proxies
  • 📚 Metadata Discovery: RFC 8414 compliant server metadata

Installation

# Via pixi (recommended)
pixi add mcp-oauth-dynamicclient

# Or from source
cd mcp-oauth-dynamicclient
pixi install -e .

Quick Start

1. Environment Configuration

Create a .env file with required settings:

# GitHub OAuth App credentials
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret

# JWT signing secret (minimum 32 characters)
GATEWAY_JWT_SECRET=your-secret-key-at-least-32-chars

# Redis connection
REDIS_URL=redis://redis:6379/0

# Optional: Access control
ALLOWED_GITHUB_USERS=user1,user2,user3

# Optional: Client lifetime (seconds, 0 = eternal)
CLIENT_LIFETIME=7776000  # 90 days default

2. Using as a Library

from mcp_oauth_dynamicclient import create_app, Settings

# Create FastAPI application
settings = Settings()  # Loads from .env
app = create_app(settings)

# Run with uvicorn
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

3. Using the CLI

# Start OAuth server
pixi run mcp-oauth-server

# Generate GitHub token (for gateway's own use)
pixi run mcp-oauth-token

Architecture

Module Structure

mcp_oauth_dynamicclient/
├── config.py              # Pydantic settings management
├── models.py              # Data models and schemas
├── keys.py                # RSA key generation utilities
├── routes.py              # FastAPI route definitions
├── auth_authlib.py        # Authlib OAuth server setup
├── resource_protector.py  # Token validation
├── async_resource_protector.py  # Async token validation
├── redis_client.py        # Redis storage operations
├── rfc7592.py            # Client management endpoints
├── server.py             # FastAPI app factory
└── cli.py                # Command-line interface

Core Components

  1. OAuth Server (Authlib)

    • Authorization code grant with PKCE
    • Refresh token support
    • Token introspection
  2. Dynamic Registration

    • Public /register endpoint
    • Automatic client_id/secret generation
    • Optional expiration support
  3. Client Management (RFC 7592)

    • Bearer token protected endpoints
    • GET/PUT/DELETE operations
    • Registration access tokens
  4. Storage Layer

    • Redis for all persistent data
    • Configurable TTLs
    • Atomic operations

API Reference

OAuth 2.1 Endpoints

POST /register - Dynamic Client Registration

curl -X POST https://auth.example.com/register \
  -H "Content-Type: application/json" \
  -d '{
    "redirect_uris": ["https://app.example.com/callback"],
    "client_name": "My MCP Client",
    "scope": "read write"
  }'

Response includes:

  • client_id: Unique client identifier
  • client_secret: Client authentication secret
  • registration_access_token: Token for managing this registration
  • registration_client_uri: URI for client management

GET /authorize - Authorization Endpoint

Initiates OAuth flow with PKCE:

https://auth.example.com/authorize?
  client_id=client_xxxxx&
  redirect_uri=https://app.example.com/callback&
  response_type=code&
  state=random_state&
  code_challenge=challenge&
  code_challenge_method=S256

POST /token - Token Exchange

curl -X POST https://auth.example.com/token \
  -d "grant_type=authorization_code" \
  -d "code=auth_code" \
  -d "client_id=client_xxxxx" \
  -d "client_secret=secret_xxxxx" \
  -d "code_verifier=verifier"

Client Management (RFC 7592)

GET /register/{client_id}

curl -H "Authorization: Bearer {registration_access_token}" \
  https://auth.example.com/register/{client_id}

PUT /register/{client_id}

curl -X PUT https://auth.example.com/register/{client_id} \
  -H "Authorization: Bearer {registration_access_token}" \
  -H "Content-Type: application/json" \
  -d '{"client_name": "Updated Name"}'

DELETE /register/{client_id}

curl -X DELETE https://auth.example.com/register/{client_id} \
  -H "Authorization: Bearer {registration_access_token}"

Metadata Discovery

GET /.well-known/oauth-authorization-server

Returns server capabilities and endpoint URLs following RFC 8414.

Token Validation

GET /verify - ForwardAuth Endpoint

Used by reverse proxies to validate tokens:

curl -H "Authorization: Bearer {access_token}" \
  https://auth.example.com/verify

Returns headers:

  • X-User-Id: GitHub user ID
  • X-User-Name: GitHub username
  • X-Auth-Token: Token identifier

Integration Examples

With FastAPI Services

from mcp_oauth_dynamicclient import verify_token, get_current_user
from fastapi import Depends

@app.get("/protected")
async def protected_route(user = Depends(get_current_user)):
    return {"user": user.name}

With Traefik

labels:
  - "traefik.http.middlewares.auth.forwardauth.address=http://auth:8000/verify"
  - "traefik.http.middlewares.auth.forwardauth.authResponseHeaders=X-User-Id,X-User-Name"

Security Considerations

Token Security

  • JWT tokens signed with HS256
  • Configurable expiration (default: 30 days)
  • Unique JTI for tracking/revocation
  • Stored in Redis with TTL

Client Security

  • Cryptographically secure client secrets
  • Optional client expiration
  • Registration access tokens for management
  • Redirect URI validation

PKCE Implementation

  • S256 challenge method required
  • 43-128 character verifiers
  • One-time authorization codes
  • 5-minute code expiration

Configuration Reference

Variable Description Default Required
GITHUB_CLIENT_ID GitHub OAuth App ID - Yes
GITHUB_CLIENT_SECRET GitHub OAuth App Secret - Yes
GATEWAY_JWT_SECRET JWT signing secret - Yes
GATEWAY_JWT_ALGORITHM JWT algorithm HS256 No
GATEWAY_JWT_EXPIRE_MINUTES Token lifetime 43200 No
REDIS_URL Redis connection URL redis://redis:6379/0 No
ALLOWED_GITHUB_USERS Whitelist (comma-separated) - No
CLIENT_LIFETIME Client registration lifetime 7776000 No
MCP_PROTOCOL_VERSION MCP protocol version 2025-06-18 No

Development

# Clone repository
git clone https://github.com/atrawog/mcp-oauth-gateway
cd mcp-oauth-gateway/mcp-oauth-dynamicclient

# Install with dev dependencies
pixi install -e .

# Run tests
pixi run pytest tests/ -v

# Run with auto-reload
pixi run uvicorn mcp_oauth_dynamicclient.server:create_app --factory --reload

Testing

The package includes comprehensive tests:

# Unit tests
pixi run pytest tests/test_models.py -v

# Integration tests (requires Redis)
pixi run pytest tests/test_oauth_flow.py -v

# RFC compliance tests
pixi run pytest tests/test_rfc7592.py -v

Redis Key Structure

oauth:state:{state}              # OAuth state (5 min TTL)
oauth:code:{code}                # Auth codes (5 min TTL)
oauth:token:{jti}                # Access tokens (30 day TTL)
oauth:refresh:{token}            # Refresh tokens (1 year TTL)
oauth:client:{client_id}         # Client registrations
oauth:registration_token:{token} # Registration access tokens
oauth:user_tokens:{username}     # User token index

License

Apache License 2.0 - see LICENSE file for details.

Author

Andreas Trawoeger

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_oauth_dynamicclient-0.1.2.tar.gz (29.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_oauth_dynamicclient-0.1.2-py3-none-any.whl (30.8 kB view details)

Uploaded Python 3

File details

Details for the file mcp_oauth_dynamicclient-0.1.2.tar.gz.

File metadata

  • Download URL: mcp_oauth_dynamicclient-0.1.2.tar.gz
  • Upload date:
  • Size: 29.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.11

File hashes

Hashes for mcp_oauth_dynamicclient-0.1.2.tar.gz
Algorithm Hash digest
SHA256 50ffee3ea8515b8df1a1debc77c65072f68734de36b76e87905776b64a2cc100
MD5 f9cb90e70f531e4718f04715629d40d1
BLAKE2b-256 a55311cb629ff8569852c85cca7c0de6799ecfe1f3d2b61426cfbb19aee1416c

See more details on using hashes here.

File details

Details for the file mcp_oauth_dynamicclient-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for mcp_oauth_dynamicclient-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 8282b0a71aadd15a7894bd32479ec006835bfd164b58aadf871945d8656cbc6d
MD5 9bccebc7b04944b5504c151553a8cc6a
BLAKE2b-256 5228b0d0c5995c1d7d03da09e70be42908c388c998ff74319b523edb41a5b2b7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page