Skip to main content
Glama

OAuth MCP Server

by jaysunmah
OAUTH_README.md14.1 kB
# OAuth 2.1 Full Server Implementation for FastMCP This project implements a complete OAuth 2.1 server for FastMCP, following the pattern documented at https://gofastmcp.com/servers/auth/full-oauth-server ## ⚠️ Important Security Warning **This is an extremely advanced pattern that requires deep security expertise.** The FastMCP documentation strongly recommends against implementing your own OAuth server unless you have: - Deep expertise in authentication protocols and cryptography - Security monitoring and incident response capabilities - Compliance and audit requirements - A compelling reason external identity providers cannot meet **For most use cases, use Remote OAuth or OAuth Proxy instead.** ## Architecture ### Components 1. **`oauth_provider.py`** - Full OAuth 2.1 server implementation - Extends `OAuthProvider` from FastMCP - Implements all required abstract methods - Uses in-memory storage (replace with database for production) 2. **`main.py`** - FastMCP server with OAuth authentication - Registers demo OAuth client on startup - Defines authenticated tools - Runs the MCP server with OAuth enabled 3. **`oauth_client_example.py`** - Complete OAuth flow demonstration - Shows PKCE implementation - Demonstrates authorization code flow - Handles token refresh ## OAuth 2.1 Flow ``` ┌─────────┐ ┌─────────┐ │ │ │ │ │ Client │ │ Server │ │ │ │ │ └────┬────┘ └────┬────┘ │ │ │ 1. Request Authorization URL │ │ (with PKCE challenge) │ │───────────────────────────────────────────>│ │ │ │ 2. User visits URL, logs in, approves │ │ │ │ 3. Redirect with authorization code │ │<───────────────────────────────────────────│ │ │ │ 4. Exchange code for token │ │ (with PKCE verifier) │ │───────────────────────────────────────────>│ │ │ │ 5. Return access + refresh tokens │ │<───────────────────────────────────────────│ │ │ │ 6. Call tools with Bearer token │ │───────────────────────────────────────────>│ │ │ │ 7. When expired, refresh token │ │───────────────────────────────────────────>│ │ │ │ 8. New access + refresh tokens │ │<───────────────────────────────────────────│ │ │ ``` ## Implementation Details ### Required Abstract Methods The `InMemoryOAuthProvider` implements all 10 required methods: #### Client Management - `get_client()` - Retrieve OAuth client by ID - `register_client()` - Store new OAuth client #### Authorization Flow - `authorize()` - Handle authorization request, show login/consent - `load_authorization_code()` - Validate and load authorization code #### Token Management - `exchange_authorization_code()` - Exchange code for tokens - `load_refresh_token()` - Validate and load refresh token - `exchange_refresh_token()` - Exchange refresh for new access token - `load_access_token()` - Load access token for verification - `revoke_token()` - Mark token as revoked - `verify_token()` - Verify bearer token on each request ### Security Features Implemented ✅ **PKCE (RFC 7636)** - Proof Key for Code Exchange - Code verifier/challenge generation - SHA-256 challenge method - Protection against authorization code interception ✅ **Token Expiration** - Access tokens: 1 hour - Refresh tokens: 30 days - Authorization codes: 10 minutes ✅ **Token Revocation** - Tracks revoked tokens - Prevents reuse of revoked tokens - Automatic cleanup of expired tokens ✅ **State Parameter** - CSRF protection for authorization requests - State validation on callback ✅ **Refresh Token Rotation** - New refresh token issued on each refresh - Old refresh token automatically revoked - Prevents token replay attacks ✅ **Client Validation** - Client ID/secret verification - Redirect URI validation - Scope validation ### Storage **Current Implementation:** In-memory storage - All data lost on server restart - Suitable for development/testing only **Production Requirements:** - PostgreSQL, MySQL, or MongoDB for token/client storage - Redis for short-lived authorization codes - Encrypted storage for sensitive data - Regular cleanup of expired tokens ## Usage ### 1. Start the Server ```bash python main.py ``` This will: - Register a demo OAuth client - Start the FastMCP server on http://localhost:8000 - Print demo credentials ### 2. Demo Credentials **OAuth Client:** - Client ID: `demo_client` - Client Secret: `demo_secret` - Redirect URI: `http://localhost:3000/callback` **Demo User:** - Username: `demo_user` - Password: `demo_password` - Scopes: `["read", "write"]` ### 3. Run OAuth Flow Demo In a new terminal: ```bash python oauth_client_example.py ``` This demonstrates: 1. PKCE code generation 2. Authorization URL construction 3. Authorization code exchange 4. Authenticated tool calls 5. Token refresh ### 4. Manual Testing You can also test manually using curl: #### Get Authorization Code ```bash # Visit this URL in a browser (or curl with -L to follow redirects) curl -L "http://localhost:8000/oauth/authorize?response_type=code&client_id=demo_client&redirect_uri=http://localhost:3000/callback&code_challenge=YOUR_CHALLENGE&code_challenge_method=S256" ``` #### Exchange Code for Token ```bash curl -X POST http://localhost:8000/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=authorization_code" \ -d "code=YOUR_CODE" \ -d "redirect_uri=http://localhost:3000/callback" \ -d "client_id=demo_client" \ -d "client_secret=demo_secret" \ -d "code_verifier=YOUR_VERIFIER" ``` #### Call Authenticated Tool ```bash curl -X POST http://localhost:8000/tools/greet \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "World"}' ``` #### Refresh Token ```bash curl -X POST http://localhost:8000/oauth/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=refresh_token" \ -d "refresh_token=YOUR_REFRESH_TOKEN" \ -d "client_id=demo_client" \ -d "client_secret=demo_secret" ``` ## Production Considerations ### 🔒 Security Hardening 1. **Database Storage** - Replace in-memory storage with PostgreSQL/MySQL - Use connection pooling - Enable encryption at rest 2. **Password Security** - Use bcrypt or argon2 for password hashing - Implement password complexity requirements - Add rate limiting on login attempts 3. **Token Security** - Use cryptographically secure random token generation - Consider JWT tokens with RSA/ECDSA signing - Implement token binding to client 4. **HTTPS Only** - Enforce HTTPS in production - Use HSTS headers - Proper TLS certificate management 5. **Rate Limiting** - Limit token endpoint requests - Prevent brute force attacks - Implement exponential backoff 6. **Logging & Monitoring** - Log all authentication events - Monitor for suspicious patterns - Alert on security incidents 7. **Scope Management** - Implement fine-grained scopes - Validate scopes on every request - Allow scope-based access control 8. **User Consent** - Implement proper consent UI - Store user consent decisions - Allow users to revoke access ### 📊 Database Schema Example ```sql -- OAuth Clients CREATE TABLE oauth_clients ( client_id VARCHAR(255) PRIMARY KEY, client_secret_hash VARCHAR(255) NOT NULL, redirect_uris TEXT[] NOT NULL, grant_types VARCHAR(100)[] NOT NULL, response_types VARCHAR(100)[] NOT NULL, scope VARCHAR(255)[] NOT NULL, created_at TIMESTAMP DEFAULT NOW() ); -- Authorization Codes CREATE TABLE authorization_codes ( code VARCHAR(255) PRIMARY KEY, client_id VARCHAR(255) REFERENCES oauth_clients(client_id), user_id VARCHAR(255) NOT NULL, redirect_uri TEXT NOT NULL, scope VARCHAR(255)[] NOT NULL, code_challenge VARCHAR(255), code_challenge_method VARCHAR(10), expires_at TIMESTAMP NOT NULL, created_at TIMESTAMP DEFAULT NOW() ); -- Access Tokens CREATE TABLE access_tokens ( token VARCHAR(255) PRIMARY KEY, client_id VARCHAR(255) REFERENCES oauth_clients(client_id), user_id VARCHAR(255) NOT NULL, scope VARCHAR(255)[] NOT NULL, expires_at TIMESTAMP NOT NULL, revoked BOOLEAN DEFAULT FALSE, created_at TIMESTAMP DEFAULT NOW() ); -- Refresh Tokens CREATE TABLE refresh_tokens ( token VARCHAR(255) PRIMARY KEY, client_id VARCHAR(255) REFERENCES oauth_clients(client_id), user_id VARCHAR(255) NOT NULL, scope VARCHAR(255)[] NOT NULL, expires_at TIMESTAMP NOT NULL, revoked BOOLEAN DEFAULT FALSE, created_at TIMESTAMP DEFAULT NOW() ); -- Indexes for performance CREATE INDEX idx_auth_codes_expires ON authorization_codes(expires_at); CREATE INDEX idx_access_tokens_expires ON access_tokens(expires_at); CREATE INDEX idx_refresh_tokens_expires ON refresh_tokens(expires_at); ``` ## Testing ### Unit Tests Create tests for each OAuth method: - Client registration and retrieval - Authorization code generation and validation - Token exchange and refresh - Token revocation - Scope validation ### Integration Tests Test the complete OAuth flow: - Authorization code flow with PKCE - Token refresh flow - Error cases (invalid codes, expired tokens, etc.) - Scope restrictions ### Security Tests - PKCE validation - State parameter validation - Redirect URI validation - Token replay prevention - Scope escalation prevention ## Common Issues ### "Invalid redirect_uri" Make sure the redirect URI in the authorization request exactly matches one of the registered redirect URIs for the client. ### "Invalid code_verifier" The code verifier sent in the token exchange must match the code challenge used in the authorization request (SHA-256 hash). ### "Token expired" Access tokens expire after 1 hour. Use the refresh token to get a new access token. ### "Invalid client" Client ID and secret must match the registered client credentials. ## New Endpoints (Recently Added) ### OAuth 2.0 Authorization Server Metadata (RFC 8414) **Endpoint:** `GET /.well-known/oauth-authorization-server` Provides clients with OAuth server configuration for automatic discovery: ```bash curl http://localhost:8000/.well-known/oauth-authorization-server ``` Returns metadata including all supported endpoints, grant types, and authentication methods. ### Token Revocation (RFC 7009) **Endpoint:** `POST /oauth/revoke` Allows clients to revoke access or refresh tokens: ```bash # Using Basic auth curl -X POST http://localhost:8000/oauth/revoke \ -u "demo_client:demo_secret" \ -d "token=YOUR_TOKEN&token_type_hint=access_token" # Using form data curl -X POST http://localhost:8000/oauth/revoke \ -d "token=YOUR_TOKEN" \ -d "client_id=demo_client" \ -d "client_secret=demo_secret" ``` ### Token Introspection (RFC 7662) **Endpoint:** `POST /oauth/introspect` Allows resource servers to validate tokens and get metadata: ```bash curl -X POST http://localhost:8000/oauth/introspect \ -u "demo_client:demo_secret" \ -d "token=YOUR_TOKEN&token_type_hint=access_token" ``` Returns token status and metadata: ```json { "active": true, "scope": "read write", "client_id": "demo_client", "username": "demo_user", "exp": 1735432800 } ``` ### UserInfo Endpoint **Endpoint:** `GET /userinfo` Returns authenticated user's profile information: ```bash curl http://localhost:8000/userinfo \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` Returns user profile based on token scopes: ```json { "sub": "demo_user", "name": "demo_user", "preferred_username": "demo_user", "email": "demo_user@example.com", "scope": "read write profile email" } ``` ## References - FastMCP OAuth Documentation: https://gofastmcp.com/servers/auth/full-oauth-server - OAuth 2.1 Specification: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1 - PKCE Specification (RFC 7636): https://datatracker.ietf.org/doc/html/rfc7636 - Dynamic Client Registration (RFC 7591): https://datatracker.ietf.org/doc/html/rfc7591 - OAuth 2.0 Authorization Server Metadata (RFC 8414): https://datatracker.ietf.org/doc/html/rfc8414 - OAuth 2.0 Token Revocation (RFC 7009): https://datatracker.ietf.org/doc/html/rfc7009 - OAuth 2.0 Token Introspection (RFC 7662): https://datatracker.ietf.org/doc/html/rfc7662 - OAuth 2.0 Protected Resource Metadata (RFC 9470): https://datatracker.ietf.org/doc/html/rfc9470 - OAuth 2.0 Security Best Practices: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics ## License Copyright Anysphere Inc.

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jaysunmah/oauth_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server