使用说明
mcp-oauth2-羟基
一个兼容OAuth 2.1的授权服务器和反向代理,旨在为普通用户添加身份验证 模型上下文协议(MCP) HTTP服务器,上游没有变化。
它位于MCP服务器的前面,处理所有OAuth流,在每个请求上验证Bearer令牌,并将经过身份验证的流量转发到上游。
特征
- 授权码流 使用PKC(S256)——由Claude等MCP客户端使用
- 刷新令牌流 使用轮转--客户端无需重新验证即可续订访问令牌
- 客户端凭据流 --机器对机器访问
- 基于浏览器的登录表单,带有bcrypt密码验证
- 可选的 OpenID连接登录 (例如谷歌)在密码表单旁边显示电子邮件分配列表
- JWT访问令牌(HS256)
iss,aud,sub,exp索赔 - 自动发现端点(RFC 8414+RFC 9728)
- 上游MCP HTTP服务器的透明反向代理
快速开始
git clone https://github.com/clems4ever/mcp-oauth2-proxy
cd mcp-oauth2-proxy
go build -o mcp-oauth2-proxy .
./mcp-oauth2-proxy --config example-config.yaml
或者使用Docker:
docker run --rm \
-p 8080:8080 \
-v $PWD/example-config.yaml:/config.yaml \
ghcr.io/clems4ever/mcp-oauth2-proxy --config /config.yaml
配置
server:
port: 8080
issuer: "https://auth.example.com" # public base URL — must match what clients see
jwt_secret: "change-me-in-production"
token_ttl: 3600 # access token lifetime, seconds
auth_code_ttl: 300 # authorization code lifetime, seconds
refresh_token_ttl: 2592000 # refresh token lifetime, seconds (default 30 days)
upstream_url: "http://localhost:9090" # MCP HTTP server to proxy authenticated requests to
# Human users for the authorization code flow.
# Passwords are bcrypt hashes — generate with: htpasswd -bnBC 10 "" <password> | tr -d ':\n'
users:
- username: alice
password: "$2a$10$..."
# Single OAuth2 application (used for both flows).
application:
client_id: "service-client-id"
client_secret: "service-client-secret"
allowed_scopes:
- read
- write
redirect_uris:
- "https://claude.ai/api/mcp/auth_callback"
默认配置路径: ~/.mcp-oauth2.yaml.用覆盖 --config.
以下各节分别记录了两个可选块: oidc (登录
与谷歌/任何OIDC提供商合作)以及 storage (将刷新令牌持久化到磁盘)。
端点
| 方法 | 路径 | 描述 |
|---|---|---|
GET |
/.well-known/oauth-authorization-server |
授权服务器元数据(RFC 8414) |
GET |
/.well-known/oauth-protected-resource |
受保护的资源元数据(RFC 9728) |
GET/POST |
/oauth2/authorize |
授权端点--显示登录表单,发出身份验证码 |
POST |
/oauth2/token |
令牌端点-- authorization_code, client_credentials 和 refresh_token 赠款 |
POST |
/oauth2/oidc/login |
启动OIDC登录(仅当 oidc 已配置) |
GET |
/oauth2/oidc/callback |
OIDC提供商回调(仅当 oidc 已配置) |
* |
/ |
反向代理到 upstream_url (需要有效的Bearer令牌) |
令牌端点
客户端凭据
curl -X POST http://localhost:8080/oauth2/token \
-u service-client-id:service-client-secret \
-d "grant_type=client_credentials&scope=read"
授权码(PKCE)
授权码流由MCP客户端启动。代理显示登录表单,用户进行身份验证,并向注册者返回授权码 redirect_uri。然后将代码交换为令牌:
curl -X POST http://localhost:8080/oauth2/token \
-u service-client-id:service-client-secret \
-d "grant_type=authorization_code&code=<code>&redirect_uri=<uri>&code_verifier=<verifier>"
授权码响应包括 refresh_token.
刷新令牌
将刷新令牌替换为新的访问令牌(以及旋转的刷新令牌)。
之前的刷新令牌在使用时无效;可选 scope 可能缩小
授予的范围(它必须是原始范围的子集):
curl -X POST http://localhost:8080/oauth2/token \
-u service-client-id:service-client-secret \
-d "grant_type=refresh_token&refresh_token=<refresh_token>"
仅为授权码(和刷新)流颁发刷新令牌--
这 client_credentials grant不返回任何值,因为机器客户端可以简单地
请求一个新的令牌及其凭据。
默认情况下,刷新令牌保存在内存中,并在重新启动时丢失。进行登录
生存重启,设置 storage.path 将它们保存在嵌入式系统中
bbolt 数据库(清除过期的令牌
自动):
storage:
path: "/var/lib/mcp-oauth2/store.db"
授权码和登录会话始终在内存中(它们是 短命)。
响应
{
"access_token": "eyJhbGci...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "9f8c...",
"scope": "read write"
}
Google/OIDC登录
除了密码表单,浏览器登录还可以对用户进行身份验证
针对任何OpenID Connect提供商(谷歌、Okta、Auth0、Entra等)。当A
oidc 如果配置中存在块,登录页面将显示 “登录
谷歌 用户名/密码窗体旁边的按钮。访问仅限于
电子邮件列表 --只有您列出的经过验证的电子邮件才能登录。
- 在您的提供商处创建OAuth客户端。对于谷歌: API和服务→ 凭证→ 创建OAuth客户端ID→ Web应用程序.
- 将此代理的回调添加为授权重定向URI:
<issuer base URL>/oauth2/oidc/callback(例如。https://auth.example.com/oauth2/oidc/callback). - 添加
oidc阻止您的配置:
oidc:
issuer: "https://accounts.google.com" # OIDC issuer; endpoints are discovered automatically
client_id: "xxxxxxxx.apps.googleusercontent.com"
client_secret: "your-google-client-secret"
# redirect_url defaults to <server.issuer>/oauth2/oidc/callback
scopes: ["openid", "email", "profile"] # optional; this is the default
allowed_emails:
- alice@example.com
工作原理:代理将浏览器重定向到提供商,验证
返回的ID令牌(签名、受众、随机数)和 email_verified,检查
电子邮件反对 allowed_emails,然后发布自己的授权码——所以
下游MCP令牌交换不变。已发放的访问令牌 sub
索赔是用户的电子邮件。
旗帜
| 标志 | 默认值 | 描述 |
|---|---|---|
--config |
~/.mcp-oauth2.yaml |
配置文件的路径 |
安全说明
- PKC与
S256是所有授权代码流所必需的(OAuth 2.1) - 用户密码必须存储为bcrypt哈希值
- A.
jwt_secret是 必需的:服务器拒绝从空服务器开始。在生产中使用强随机值 - 这
issuer值取自config--requestHost标头永远不受信任 - 代理提供纯HTTP;在它前面终止TLS(例如反向代理),因为否则令牌和密码将以明文形式传输