A comprehensive OAuth 2.1 proxy server implemented in Go that provides OAuth authorization server functionality with PostgreSQL storage. This proxy supports multiple OAuth providers (Google, Microsoft) and can proxy requests to MCP servers with user context headers.
- OAuth 2.1 Compliance: Implements OAuth 2.1 best practices including short-lived access tokens, refresh token rotation, and token revocation
- Multiple Provider Support: Supports Google and Microsoft OAuth providers
- PostgreSQL Storage: Uses PostgreSQL for storing clients, grants, authorization codes, and tokens
- JWT Token Management: Generates and validates JWT tokens with embedded user properties
- MCP Proxy: Proxies requests to MCP servers with user context headers
- CORS Support: Configurable CORS headers for cross-origin requests
- Rate Limiting: Built-in rate limiting to prevent abuse
- PKCE Support: Supports PKCE (Proof Key for Code Exchange) for enhanced security
The OAuth proxy follows the Cloudflare Workers OAuth Provider pattern but is implemented in Go with PostgreSQL storage:
- Authorization Flow: Clients request authorization, users approve, and authorization codes are generated
- Token Exchange: Authorization codes are exchanged for access and refresh tokens
- Token Validation: JWT tokens are validated and user properties are extracted
- MCP Proxying: Requests to MCP endpoints are proxied with user context headers
The proxy uses PostgreSQL with the following tables:
clients
: OAuth client registrationsgrants
: Authorization grants with user propertiesauthorization_codes
: Single-use authorization codesaccess_tokens
: Access and refresh tokens with grant references
The application can be configured using environment variables:
DATABASE_DSN
: PostgreSQL connection stringSCOPES_SUPPORTED
: Comma-separated list of supported OAuth scopes (e.g., "openid,profile,email")MCP_SERVER_URL
: URL of the MCP server to proxy requests toOAUTH_CLIENT_ID
: OAuth client ID from your OAuth providerOAUTH_CLIENT_SECRET
: OAuth client secret from your OAuth providerOAUTH_AUTHORIZE_URL
: Authorization endpoint URL from your OAuth provider
ENCRYPTION_KEY
: Base64-encoded 32-byte AES-256 key for encrypting sensitive data
# Example for Google OAuth
DATABASE_DSN="postgres://oauth_user:oauth_password@localhost:5432/oauth_proxy?sslmode=disable"
SCOPES_SUPPORTED="openid,profile,email"
OAUTH_CLIENT_ID="your-google-client-id.apps.googleusercontent.com"
OAUTH_CLIENT_SECRET="your-google-client-secret"
OAUTH_AUTHORIZE_URL="https://accounts.google.com"
MCP_SERVER_URL="http://localhost:3000"
ENCRYPTION_KEY="base64-encoded-32-byte-aes-256-key"
# Example for Microsoft Azure AD
# SCOPES_SUPPORTED="openid,profile,email,User.Read"
# OAUTH_AUTHORIZE_URL="https://login.microsoftonline.com/common/v2.0"
# Example for GitHub
# SCOPES_SUPPORTED="read:user,user:email"
# OAUTH_AUTHORIZE_URL="https://github.com/login/oauth"
-
Create a Google Cloud Project:
- Go to Google Cloud Console
- Create a new project or select an existing one
-
Enable OAuth 2.0 API:
- Go to "APIs & Services" > "Library"
- Search for "Google+ API" or "OAuth 2.0" and enable it
-
Create OAuth 2.0 Credentials:
- Go to "APIs & Services" > "Credentials"
- Click "Create Credentials" > "OAuth 2.0 Client IDs"
- Choose "Web application" as the application type
- Add authorized redirect URIs:
http://localhost:8080/callback
(for development) - Note down the Client ID and Client Secret
-
Environment Variables:
OAUTH_CLIENT_ID="your-google-client-id.apps.googleusercontent.com" OAUTH_CLIENT_SECRET="your-google-client-secret" OAUTH_AUTHORIZE_URL="https://accounts.google.com" SCOPES_SUPPORTED="openid,profile,email"
-
Register an Application:
- Go to Azure Portal
- Navigate to "Azure Active Directory" > "App registrations"
- Click "New registration"
- Enter a name for your application
- Set redirect URI to
http://localhost:8080/callback
(for development)
-
Configure Permissions:
- Go to "API permissions"
- Add "Microsoft Graph" > "Delegated permissions"
- Select:
User.Read
,openid
,profile
,email
- Click "Grant admin consent"
-
Get Client Credentials:
- Go to "Certificates & secrets"
- Create a new client secret
- Note down the Application (client) ID and the secret value
-
Environment Variables:
OAUTH_CLIENT_ID="your-azure-client-id" OAUTH_CLIENT_SECRET="your-azure-client-secret" OAUTH_AUTHORIZE_URL="https://login.microsoftonline.com/common/v2.0" SCOPES_SUPPORTED="openid,profile,email,User.Read"
-
Create a GitHub OAuth App:
- Go to GitHub Settings
- Click "New OAuth App"
- Fill in the application details:
- Application name: Your app name
- Homepage URL:
http://localhost:8080
(for development) - Authorization callback URL:
http://localhost:8080/callback
-
Get Client Credentials:
- After creating the app, you'll see the Client ID
- Click "Generate a new client secret" to get the Client Secret
-
Environment Variables:
OAUTH_CLIENT_ID="your-github-client-id" OAUTH_CLIENT_SECRET="your-github-client-secret" OAUTH_AUTHORIZE_URL="https://github.com/login/oauth" SCOPES_SUPPORTED="read:user,user:email"
When configuring your OAuth provider, use these redirect URIs:
- Development:
http://localhost:8080/callback
- Production:
https://yourdomain.com/callback
The proxy will automatically handle the OAuth flow and redirect users back to your application.
openid
: Required for OpenID Connect authenticationprofile
: Access to user's basic profile information (name, picture)email
: Access to user's email address
openid
: Required for OpenID Connect authenticationprofile
: Access to user's basic profile informationemail
: Access to user's email addressUser.Read
: Access to read user's profile and basic information
read:user
: Access to read user's profile informationuser:email
: Access to read user's email addresses
You can customize the scopes based on your needs. Common additional scopes include:
offline_access
: For refresh tokens (Microsoft)https://www.googleapis.com/auth/userinfo.profile
: Extended Google profile accessrepo
: GitHub repository access (if needed)
-
Pull the Docker image:
docker pull ghcr.io/YOUR_USERNAME/mcp-oauth-proxy:latest
-
Run with environment variables:
docker run -d \ --name oauth-proxy \ -p 8080:8080 \ -e DATABASE_DSN="postgres://oauth_user:oauth_password@localhost:5432/oauth_proxy?sslmode=disable" \ -e BASE_URL="http://localhost:8080" \ -e SCOPES_SUPPORTED="openid,profile,email" \ -e GOOGLE_CLIENT_ID="your-google-client-id" \ -e GOOGLE_CLIENT_SECRET="your-google-client-secret" \ -e MCP_SERVER_URL="http://localhost:3000" \ -e ENCRYPTION_KEY="your-base64-encoded-32-byte-key" \ ghcr.io/YOUR_USERNAME/mcp-oauth-proxy:latest
-
Create a docker-compose.yml file:
version: "3.8" services: postgres: image: postgres:15 environment: POSTGRES_DB: oauth_proxy POSTGRES_USER: oauth_user POSTGRES_PASSWORD: oauth_password volumes: - postgres_data:/var/lib/postgresql/data ports: - "5432:5432" oauth-proxy: image: ghcr.io/obot-platform/mcp-oauth-proxy:master environment: DATABASE_DSN: "postgres://oauth_user:oauth_password@postgres:5432/oauth_proxy?sslmode=disable" SCOPES_SUPPORTED: "openid,profile,email" OAUTH_CLIENT_ID: "your-oauth-client-id" OAUTH_CLIENT_SECRET: "your-oauth-client-secret" OAUTH_AUTHORIZE_URL: "https://your-oauth-provider.com/oauth/authorize" MCP_SERVER_URL: "http://localhost:3000/mcp" ENCRYPTION_KEY: "your-base64-encoded-32-byte-key" ports: - "8080:8080" depends_on: - postgres volumes: postgres_data:
-
Start the services:
docker-compose up -d
-
Start PostgreSQL:
docker-compose up -d postgres
-
Create a test client:
go run scripts/create_client.go "postgres://oauth_user:oauth_password@localhost:5432/oauth_proxy?sslmode=disable"
-
Start the OAuth proxy:
go run main.go
GET /authorize
- OAuth authorization endpointPOST /token
- OAuth token endpointPOST /revoke
- OAuth token revocation endpoint
GET /.well-known/oauth-authorization-server
- OAuth server metadataGET /.well-known/oauth-protected-resource
- Protected resource metadata
ANY /mcp/*
- Proxies requests to MCP server with user context headers
- Authorization Request: Client redirects user to
/authorize
with OAuth parameters - User Approval: User approves the authorization request
- Authorization Code: Server generates and returns an authorization code
- Token Exchange: Client exchanges authorization code for access and refresh tokens
- API Access: Client uses access token to access protected resources
The proxy forwards requests to the configured MCP server with the following headers:
X-Forwarded-User
: User ID from the tokenX-Forwarded-Email
: User email from token propsX-Forwarded-Name
: User name from token propsX-Forwarded-Access-Token
: Original access token from external provider
Run the test script to test the OAuth flow:
chmod +x test_oauth.sh
./test_oauth.sh
The code is based on the Cloudflare Workers OAuth Provider.
- Short-lived Access Tokens: Access tokens expire after 1 hour by default
- Refresh Token Rotation: New refresh tokens are issued with each use
- Token Revocation: Tokens can be revoked via the revocation endpoint
- PKCE Support: Supports PKCE for enhanced security in public clients
- Rate Limiting: Built-in rate limiting to prevent abuse
- CORS Configuration: Configurable CORS headers for security
The proxy supports any OAuth 2.0/OpenID Connect provider through automatic endpoint discovery. It will:
-
Discover Endpoints: Automatically discover OAuth endpoints using well-known paths:
/.well-known/oauth-authorization-server
/.well-known/openid-configuration
-
Use Discovered Endpoints: Use the discovered authorization, token, and userinfo endpoints
-
Fallback: If discovery fails, use the provided authorization URL with default endpoint assumptions
The proxy supports standard OAuth scopes:
openid
profile
email
Set these environment variables to configure your OAuth provider:
OAUTH_CLIENT_ID
: Your OAuth client IDOAUTH_CLIENT_SECRET
: Your OAuth client secretOAUTH_AUTHORIZE_URL
: The authorization endpoint URL from your provider
To add a new OAuth provider:
- Implement the
Provider
interface inproviders/provider.go
- Create a new provider file (e.g.,
providers/github.go
) - Register the provider in
main.go
The database schema is automatically created when the application starts. For production deployments, consider using proper database migration tools.
The project includes a GitHub Actions workflow that automatically builds and pushes Docker images to GitHub Container Registry (GHCR) on:
- Push to
main
ormaster
branch - Push of tags starting with
v
(e.g.,v1.0.0
) - Pull requests to
main
ormaster
branch (builds but doesn't push)
To build the Docker image locally:
docker build -t mcp-oauth-proxy .
The workflow creates images with the following tags:
ghcr.io/mcp-oauth-proxy/mcp-oauth-proxy:master
- Latest from master branchghcr.io/mcp-oauth-proxy/mcp-oauth-proxy:master-abc123
- Branch-specific builds
This project is licensed under the MIT License.