OAuth认证网关

MCP OAuth网关是一个实现了OAuth 2.1协议的授权服务器,为Model Context Protocol(MCP)服务提供透明的认证和授权功能。

  • by akshay5995
  • Python
  • 本地部署
  • 3 星标
  • 更新于
在 GitHub 查看 akshay5995/mcp-oauth-gateway

使用说明

MCP OAuth网关

[⚠️⚠️⚠️ 概念验证(PoC)不适合生产使用⚠️⚠️⚠️]

OAuth 2.1授权服务器,为模型上下文协议(MCP)服务提供透明的身份验证和授权。

特性

  • 透明MCP访问:用户通过简单的URL访问MCP服务,无需手动设置OAuth
  • 单一OAuth提供者:为所有服务(Google、GitHub、Okta或自定义)使用一个OAuth提供程序
  • 完全符合MCP:使用OAuth 2.1实现完整的MCP授权规范
  • 动态客户端注册:根据RFC 7591自动注册客户端
  • 用户上下文注入:后端MCP服务的无缝用户上下文标头
  • 资源特定令牌:RFC 8707受众绑定防止令牌滥用
  • 可配置存储:内存(开发)、Redis(生产)、Vault(企业)后端
  • 生产就绪:全面的测试、Docker支持、可扩展的架构

📖 查看详细架构 | 📚 开发者指南

Docker快速入门(推荐)

预构建图像

使用GitHub容器注册表中的预构建Docker镜像:

# Run with memory storage (development)
docker run -p 8080:8080 \
  -v $(pwd)/config.yaml:/app/config.yaml \
  -e GOOGLE_CLIENT_ID="your-google-client-id" \
  -e GOOGLE_CLIENT_SECRET="your-google-client-secret" \
  ghcr.io/akshay5995/mcp-oauth-gateway:latest

Docker Compose(全栈)

# Copy environment template
cp .env.example .env
# Edit .env with your OAuth credentials

# Start all services (gateway + Redis + demo calculator)
docker-compose up -d

# Test the setup
curl http://localhost:8080/health
curl http://localhost:8080/calculator/mcp  # Should return 401 with OAuth info

地方发展设置

1.安装依赖项

pip install -r requirements.txt

# Optional: For Redis storage backend with modern library
pip install -r requirements-redis.txt

2.配置OAuth提供程序

重要:每个网关实例仅配置一个OAuth提供程序。

为Google OAuth设置环境变量:

export GOOGLE_CLIENT_ID="your-google-client-id"
export GOOGLE_CLIENT_SECRET="your-google-client-secret"

📚 其他供应商:参见 配置指南 适用于GitHub、Okta和自定义OAuth提供商

3.创建基本配置

创建 config.yaml 文件:

# Gateway settings
host: "localhost"
port: 8080
issuer: "http://localhost:8080"
session_secret: "your-dev-secret-change-in-production"
debug: true

# OAuth provider
oauth_providers:
  google:
    client_id: "${GOOGLE_CLIENT_ID}"
    client_secret: "${GOOGLE_CLIENT_SECRET}"
    scopes: ["openid", "email", "profile"]

# Example service (replace with your MCP service)
mcp_services:
  calculator:
    name: "Calculator Service"
    url: "http://localhost:3001"
    oauth_provider: "google"
    auth_required: true
    scopes: ["read", "calculate"]

4.运行网关

python -m src.gateway --config config.yaml --debug

5.测试设置

访问您的服务以验证其是否正常工作:

curl http://localhost:8080/calculator/mcp
# Should return 401 with OAuth authentication info

6.添加您的服务

更换中的示例服务 config.yaml 使用您的实际MCP服务。所有服务必须使用相同的OAuth提供程序。

📚 完整配置指南 -详细的服务配置选项

MCP客户端集成

1.发现

MCP客户端首先访问服务端点:

GET /calculator/mcp HTTP/1.1
Host: localhost:8080

网关使用OAuth元数据进行响应:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="http://localhost:8080/.well-known/oauth-protected-resource"

2.元数据检索

客户端获取OAuth元数据:

curl http://localhost:8080/.well-known/oauth-authorization-server
curl http://localhost:8080/.well-known/oauth-protected-resource

3.动态客户端注册

客户端自动注册:

curl -X POST http://localhost:8080/oauth/register \
  -d "client_name=My MCP Client" \
  -d "redirect_uris=http://localhost:8080/callback"

4.授权流程

客户端遵循标准OAuth 2.1和PKCE:

  1. 带有资源参数的授权请求
  2. 通过配置的提供程序进行用户身份验证
  3. 访问令牌的授权码交换
  4. 经过身份验证的MCP请求

配置

网关设置

host: "0.0.0.0"
port: 8080
issuer: "https://mcp-gateway.example.com"
session_secret: "production-secret-key"
debug: false

CORS配置

为web客户端配置跨源资源共享(CORS):

cors:
  allow_origins: ["*"]         # Allowed origins (use specific domains in production)
  allow_credentials: true      # Allow credentials in CORS requests
  allow_methods:               # Allowed HTTP methods
    - "GET"
    - "POST"
    - "PUT"
    - "DELETE"
    - "OPTIONS"
  allow_headers: ["*"]         # Allowed headers (use specific headers in production)

对于生产部署,限制CORS设置:

cors:
  allow_origins: 
    - "https://myapp.example.com"
    - "https://dashboard.example.com"
  allow_credentials: true
  allow_methods: ["GET", "POST", "OPTIONS"]
  allow_headers: 
    - "Authorization"
    - "Content-Type"
    - "MCP-Protocol-Version"

OAuth提供程序配置

重要:由于OAuth 2.1资源参数限制,每个网关实例只配置一个OAuth提供程序。

oauth_providers:
  google:
    client_id: "${GOOGLE_CLIENT_ID}"
    client_secret: "${GOOGLE_CLIENT_SECRET}"
    scopes: ["openid", "email", "profile"]

📚 替代供应商:参见 配置指南 GitHub、Okta和自定义OAuth提供者示例

MCP服务

mcp_services:
  calculator:
    name: "Calculator Service"
    url: "http://calculator:3001"
    oauth_provider: "google"  # Must match the configured OAuth provider
    auth_required: true
    scopes: ["read", "calculate"]
    timeout: 30000
  
  # All authenticated services must use the same OAuth provider
  weather:
    name: "Weather Service"
    url: "http://weather:3002"
    oauth_provider: "google"  # Same as above
    auth_required: true
    scopes: ["read"]

后端服务集成

后端MCP服务接收带有用户上下文标头的请求:

GET /mcp HTTP/1.1
Host: calculator:3001
x-user-id: google_user_123456
x-user-email: user@example.com
x-user-name: John Doe
x-user-provider: google
x-user-avatar: https://example.com/avatar.jpg

服务可以将这些标头用于:

  • 用户身份和授权
  • 审核日志记录
  • 个性化响应
  • 用户特定的数据访问

高级Docker部署

从源代码构建

# Build image locally
docker build -t mcp-oauth-gateway .

# Run with custom build
docker run -p 8080:8080 \
  -v $(pwd)/config.yaml:/app/config.yaml \
  -e GOOGLE_CLIENT_ID="your-google-client-id" \
  -e GOOGLE_CLIENT_SECRET="your-google-client-secret" \
  mcp-oauth-gateway

使用Redis存储进行生产

# Start Redis container
docker run -d --name redis \
  -p 6379:6379 \
  redis:alpine redis-server --requirepass mypassword

# Update config.yaml for Redis
cat >> config.yaml << EOF
storage:
  type: "redis"
  redis:
    host: "host.docker.internal"  # or Redis container IP
    port: 6379
    password: "\${REDIS_PASSWORD}"
EOF

# Run gateway with Redis
docker run -p 8080:8080 \
  -v $(pwd)/config.yaml:/app/config.yaml \
  -e GOOGLE_CLIENT_ID="your-google-client-id" \
  -e GOOGLE_CLIENT_SECRET="your-google-client-secret" \
  -e REDIS_PASSWORD="mypassword" \
  ghcr.io/akshay5995/mcp-oauth-gateway:latest

配备Vault存储的企业

# Start Vault container (dev mode)
docker run -d --name vault \
  -p 8200:8200 \
  -e VAULT_DEV_ROOT_TOKEN_ID="myroot" \
  vault:latest

# Update config.yaml for Vault
cat >> config.yaml << EOF
storage:
  type: "vault"
  vault:
    url: "http://host.docker.internal:8200"
    token: "\${VAULT_TOKEN}"
    mount_point: "secret"
    path_prefix: "mcp-gateway"
EOF

# Run gateway with Vault
docker run -p 8080:8080 \
  -v $(pwd)/config.yaml:/app/config.yaml \
  -e GOOGLE_CLIENT_ID="your-google-client-id" \
  -e GOOGLE_CLIENT_SECRET="your-google-client-secret" \
  -e VAULT_TOKEN="myroot" \
  ghcr.io/akshay5995/mcp-oauth-gateway:latest

API终点

OAuth 2.1端点

  • GET /.well-known/oauth-authorization-server -服务器元数据
  • GET /.well-known/oauth-protected-resource -资源元数据
  • GET /oauth/authorize -授权端点
  • POST /oauth/token -令牌端点
  • POST /oauth/register -动态客户端注册

服务端点

  • GET /services -列出可用服务
  • GET /services/{service-id} -获取服务信息
  • ALL /{service-id}/mcp -MCP服务代理

公用设施端点

  • GET / -网关信息
  • GET /health -健康检查

安全特性

OAuth 2.1合规性

  • 所有授权码流都需要PKCE
  • 根据RFC 8707进行资源参数绑定
  • 正确的令牌受众验证
  • 安全重定向URI验证

令牌安全

  • 具有特定服务受众声明的JWT代币
  • 短期访问令牌(1小时)
  • 刷新公共客户端的令牌轮换
  • 令牌撤销支持

提供商安全

  • 每个网关实例有一个OAuth提供程序
  • 特定于提供商的用户身份验证
  • 安全的凭证存储
  • 状态参数CSRF保护

发展

运行测试

# Install test dependencies (included in requirements.txt)
pip install pytest pytest-asyncio pytest-httpx

# Run all tests
pytest tests/

# Run with coverage
pytest tests/ --cov=src

# Run specific test file
pytest tests/test_oauth_server.py -v

代码风格

# Format and lint code
ruff check src/ demo/ --fix
ruff format src/ demo/

环境变量

网关配置

  • MCP_CONFIG_PATH -配置文件的路径
  • MCP_GATEWAY_HOST -主机覆盖
  • MCP_GATEWAY_PORT -端口覆盖
  • MCP_DEBUG -调试模式

OAuth提供者

  • GOOGLE_CLIENT_ID -谷歌OAuth客户端ID
  • GOOGLE_CLIENT_SECRET -Google OAuth客户端密钥
  • GITHUB_CLIENT_ID -GitHub OAuth客户端ID
  • GITHUB_CLIENT_SECRET -GitHub OAuth客户端密钥
  • OKTA_CLIENT_ID -Okta OAuth客户端ID
  • OKTA_CLIENT_SECRET -Okta OAuth客户端密钥
  • OKTA_DOMAIN -Okta域名(例如dev-123.Okta.com)

存储后端

  • REDIS_HOST -Redis服务器主机
  • REDIS_PORT -Redis服务器端口
  • REDIS_PASSWORD -Redis身份验证密码
  • REDIS_SSL -启用Redis SSL(真/假)
  • VAULT_URL -保险库服务器URL
  • VAULT_TOKEN -保险库身份验证令牌
  • VAULT_MOUNT_POINT -保险库KV安装点
  • VAULT_PATH_PREFIX -保险库秘密路径前缀

存储后端

为您的部署选择合适的存储后端:

内存存储(默认)

storage:
  type: "memory"

✅ 最佳:开发、测试、单实例演示
❌ 局限性:重新启动时数据丢失,仅限单个实例

Redis存储(生产)

storage:
  type: "redis"
  redis:
    host: "${REDIS_HOST:-localhost}"
    port: 6379
    password: "${REDIS_PASSWORD}"
    ssl: true
    max_connections: 20

✅ 最佳:生产部署、横向扩展
✅ 特性:持久存储、多实例支持、连接池
✅ 兼容性:使用现代redis-py库实现Python 3.11+兼容性

保险库存储(企业)

storage:
  type: "vault"
  vault:
    url: "${VAULT_URL}"
    token: "${VAULT_TOKEN}"
    mount_point: "secret"
    path_prefix: "mcp-gateway"
    auth_method: "token"  # or "approle", "kubernetes"

✅ 最佳:企业环境、法规遵从性要求
✅ 特性:静态加密、审计日志记录、细粒度访问控制

建筑

网关实现了关注点的清晰分离:

  • OAuth服务器:核心OAuth 2.1授权服务器
  • 供应商经理:外部OAuth提供程序集成
  • 客户端注册表:动态客户注册和管理
  • 令牌管理器:JWT令牌创建和验证
  • 存储管理器:具有回退功能的可配置存储后端
  • MCP代理:使用用户上下文注入进行请求转发
  • 元数据提供程序:OAuth元数据端点实现

📖 查看完整的架构文档

故障排除

有问题吗?查看故障排除指南:

📚 故障排除指南 -常见问题和解决方案包括:

  • 源验证错误(403个响应)
  • MCP协议版本问题(400个响应)
  • 令牌受众验证问题(401条回复)
  • 配置和部署问题

快速链接

许可证

MIT许可证-有关详细信息,请参阅许可证文件。