Skip to content

A bare minimum implementation of OAuth 2.1 for MCP which support DCR (Dynamic Client Registration)

License

Notifications You must be signed in to change notification settings

gavinHuang/MCP-OAuth

Repository files navigation

MCP-OAuth

Background

Most MCP server requires integration with authentication server, while the OAuth 2.1 protocol is still dynamic on it's own, a bare minimium implemention of it to secure your MCP remote server is crutial!

This is a complete, production-ready OAuth 2.0 server implementation with:

  • Dynamic Client Registration (DCR) - RFC 7591 compliant
  • Google OAuth Integration - Seamless Google authentication
  • JWT Token Management - Secure access and refresh tokens
  • Well-known Endpoints - OAuth 2.0 and OpenID Connect discovery
  • CORS Support - Cross-origin resource sharing
  • Supabase Storage - Scalable client and user data storage
  • FastMCP Integration - Easy integration with MCP servers

Features

  • ✅ OAuth 2.0 Authorization Code Flow
  • ✅ Dynamic Client Registration (DCR)
  • ✅ Google OAuth 2.0 Integration
  • ✅ JWT Access & Refresh Tokens
  • ✅ Token Introspection & Revocation
  • ✅ OpenID Connect Support
  • ✅ Well-known Discovery Endpoints
  • ✅ CORS Middleware
  • ✅ User Context Management
  • ✅ Supabase Database Integration
  • ✅ FastMCP Server Integration

Quick Start

1. Installation

pip install -e .

2. Environment Setup

Create a .env file:

# Supabase Configuration
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your-supabase-anon-key

# Google OAuth Configuration
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret

# OAuth Server Configuration
OAUTH_SERVER_URL=http://localhost:8080
JWT_SECRET=your-jwt-secret-key

# Token Lifetime Configuration (optional)
ACCESS_TOKEN_LIFETIME=604800    # 7 days in seconds
REFRESH_TOKEN_LIFETIME=2592000  # 30 days in seconds

3. Database Setup

Run the SQL schema in your Supabase project (see database_schema.sql).

4. Run the Server

Standalone Mode:

oauth-standalone

As a Service:

oauth-server

Usage

As a Standalone OAuth Server

from oauth_service.oauth_server import OAuthServer

# Start OAuth server
server = OAuthServer(host="0.0.0.0", port=8080)
server.run()

As Middleware for FastMCP

from fastmcp import FastMCP
from oauth_service.auth.mcp_integration import setup_oauth_for_mcp
from oauth_service.auth.middleware import AuthMiddleware

# Create MCP server
mcp = FastMCP("My MCP Server")

# Setup OAuth integration
oauth_integration = setup_oauth_for_mcp(
    mcp_instance=mcp,
    oauth_server_url="http://localhost:8080"
)

# Add authentication middleware
mcp.add_middleware(AuthMiddleware, public_paths=["/health"])

# Your MCP tools here...
@mcp.tool()
async def protected_tool():
    # This tool requires authentication
    pass

API Endpoints

Well-known Endpoints

  • GET /.well-known/oauth-authorization-server - OAuth 2.0 metadata
  • GET /.well-known/openid_configuration - OpenID Connect configuration
  • GET /.well-known/jwks.json - JSON Web Key Set

OAuth Endpoints

  • POST /oauth/register - Dynamic Client Registration
  • GET /oauth/authorize - Authorization endpoint
  • POST /oauth/token - Token endpoint
  • POST /oauth/revoke - Token revocation
  • POST /oauth/introspect - Token introspection
  • GET /oauth/userinfo - User information

Management Endpoints

  • GET /health - Health check

MCP Server Integration Examples

Example 1: Discovering OAuth Server Configuration

import aiohttp

async def discover_oauth_server(oauth_server_url: str):
    """Discover OAuth 2.0 server configuration."""
    discovery_url = f"{oauth_server_url}/.well-known/oauth-authorization-server"
    
    async with aiohttp.ClientSession() as session:
        async with session.get(discovery_url) as response:
            config = await response.json()
            return config

# Usage
oauth_config = await discover_oauth_server("http://localhost:8080")
authorization_endpoint = oauth_config["authorization_endpoint"]
token_endpoint = oauth_config["token_endpoint"]

Example 2: MCP Server with Protected Resource Metadata

from fastmcp import FastMCP
from oauth_service.auth.mcp_integration import setup_oauth_for_mcp
from oauth_service.auth.middleware import AuthMiddleware
from starlette.responses import JSONResponse

# Create MCP server
mcp = FastMCP("My Protected Server")

# Setup OAuth integration
setup_oauth_for_mcp(mcp, oauth_server_url="http://localhost:8080")
mcp.add_middleware(AuthMiddleware, public_paths=["/.well-known/oauth-protected-resource"])

# Expose protected resource metadata
@mcp.get("/.well-known/oauth-protected-resource")
async def oauth_protected_resource():
    return JSONResponse({
        "resource_description": "My MCP Server API",
        "scopes_supported": ["api:read", "api:write"],
        "bearer_methods_supported": ["header"],
        "authorization_server": "http://localhost:8080"
    })

# Protected tool
@mcp.tool()
async def protected_tool() -> dict:
    from oauth_service.auth.mcp_integration import user_context
    user = user_context.get()
    return {"message": f"Hello {user['name']}"}

Client Registration

Register a new OAuth client:

curl -X POST http://localhost:8080/oauth/register \
  -H "Content-Type: application/json" \
  -d '{
    "client_name": "My Application",
    "redirect_uris": ["http://localhost:3000/callback"],
    "scope": "openid profile email"
  }'

Authorization Flow

  1. Client Registration: Register your application
  2. Authorization: Redirect users to /oauth/authorize
  3. Token Exchange: Exchange authorization code for tokens
  4. API Access: Use access token for protected resources

Architecture

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   MCP Client    │───▶│  OAuth Server   │───▶│   Google OAuth  │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                               │
                               ▼
                       ┌─────────────────┐
                       │   Supabase DB   │
                       └─────────────────┘

Security Features

  • JWT Tokens: Cryptographically signed tokens
  • Token Expiration: Configurable token lifetimes
  • Secure Storage: Encrypted client secrets in Supabase
  • CORS Protection: Configurable origin restrictions
  • State Parameter: CSRF protection for authorization flow

License

MIT License - see LICENSE file for details.

About

A bare minimum implementation of OAuth 2.1 for MCP which support DCR (Dynamic Client Registration)

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published