OAuth 支持
核心亮点
- 覆盖上游 MCP 服务器的 OAuth 2.0 授权码(PKCE)全流程。
- 支持从
WWW-Authenticate响应和 RFC 8414 元数据自动发现。 - 实现动态客户端注册(RFC 7591)以及资源指示(RFC 8707)。
- 会将客户端凭据与令牌持久化到
mcp_settings.json,重启后直接复用。
MCPHub 何时启用 OAuth
- MCPHub 调用需要授权的 MCP 服务器并收到
401 Unauthorized。 - 响应通过
WWW-Authenticateheader 暴露受保护资源的元数据(authorization_server或as_uri)。 - MCPHub 自动发现授权服务器、按需注册客户端,并引导用户完成一次授权。
- 回调处理完成后,MCPHub 使用新令牌重新连接并继续请求。
MCPHub 会在服务器详情视图和后端日志中记录发现、注册、授权链接、换取令牌等关键步骤。
按服务器类型快速上手
支持动态注册的服务器
部分服务器会公开完整的 OAuth 元数据,并允许客户端动态注册。例如 Vercel 与 Linear 的 MCP 服务器只需配置 SSE 地址即可:- MCPHub 会自动发现授权服务器、完成注册,并处理整个 PKCE 流程。
- 所有凭据与令牌会写入
mcp_settings.json,无须在控制台额外配置。
需要手动配置客户端的服务器
另有一些服务端并不支持动态注册。GitHub 的 MCP 端点(https://api.githubcopilot.com/mcp/)就是典型例子,接入步骤如下:
- 在服务提供商控制台创建 OAuth 应用(GitHub 路径为 Settings → Developer settings → OAuth Apps)。
- 将回调/重定向地址设置为
http://localhost:3000/oauth/callback(或你的部署域名)。同时请确保 设置 → 安装 → 基础地址 与该域名一致,用于 MCP 请求与 OAuth 回调。 - 复制生成的 Client ID 与 Client Secret。
- 通过 MCPHub 控制台或直接编辑
mcp_settings.json写入如下配置。
- MCPHub 会跳过动态注册,直接使用你提供的凭据完成授权流程。
- 凭据轮换时需要同步更新控制台或配置文件。
- 将
scopes替换为服务端要求的具体 Scope。
私有网络中的 HTTP 令牌端点
从 v1.0.42 开始,MCP SDK 会拒绝非 HTTPS 的 OAuth 令牌端点,loopback 主机(localhost、127.0.0.1 和 ::1)除外。此检查同时作用于授权码兑换和令牌刷新,重连或重新授权无法绕过。
建议使用 HTTPS。管理员可以在上游服务器的 OAuth 配置 中显式启用 HTTP 令牌端点,也可以通过运维管理的配置文件设置:
false。启用后,凭据、授权码和令牌可能在传输过程中泄露,仅应在可信网络中使用。每次使用例外发送 HTTP 令牌请求时都会记录警告。普通用户不能通过创建、编辑、批量导入或模板导入启用此选项,也不能编辑已启用例外的服务器。关闭选项后,待完成的回调和已有 provider 的刷新也会被阻止。此例外不会关闭 SSRF 防护、放行其他上游,也不会改变 MCPHub 向下游客户端公布的 OAuth 端点。
SDK 客户端固定为 2.1.0,通过 pnpm 补丁增加按 provider 判断的例外接口。修补后的客户端会打包进后端构建产物,npm/npx 安装也会获得修复。升级 SDK 时需要迁移或替换补丁,并运行 tests/integration/oauth-insecure-token-endpoint.test.ts。
配置方式
大多数场景可依赖自动检测,也可以在mcp_settings.json 中显式声明 OAuth 配置。只填写确实需要的字段。
自动检测(最小配置)
- MCPHub 会根据挑战头自动发现授权服务器,并引导用户完成授权。
- 令牌(包含刷新令牌)会写入磁盘,重启后自动复用。
静态客户端凭据(自带 Client)
- 适用于需要手动注册客户端的授权服务器。
redirectUri会覆盖该服务器从 设置 → 安装 → 基础地址 推导出的回调地址。- 如果未配置
redirectUri,MCPHub 会依次回退到${Base URL}/oauth/callback,再回退到http://localhost:3000/oauth/callback。 - 同时确保 设置 → 安装 → 基础地址 与部署域名一致,以保证默认回调地址正确。
动态客户端注册(RFC 7591)
- MCPHub 会通过
issuer发现端点、完成注册,并持久化下发的client_id/client_secret。 - 如果配置了
oauth.redirectUri,MCPHub 会优先使用它作为回调地址,并把它加入动态注册的redirect_uris。 - 只有当注册端点受保护时才需要提供
initialAccessToken。
授权流程
- 初始化:启动时遍历服务器配置,发现元数据并在启用
dynamicRegistration时注册客户端。 - 用户授权:建立连接时自动打开系统浏览器,携带 PKCE 参数访问授权页。
- 回调处理:内置路径
/oauth/callback校验state、完成换取令牌,并通过 MCP SDK 保存结果。 - 令牌生命周期:MCPHub 将
expires_in保存为绝对时间戳accessTokenExpiresAt。向传输层返回已过期的令牌前,通过 SDK 续期并保存轮换后的刷新令牌。共享令牌保存在服务器设置中,个人令牌保存在对应用户的加密绑定中。过期时间在运行实例重建后仍然有效,同一 MCPHub 进程内,同一绑定版本的并发个人续期只发起一次刷新。
expires_in 的令牌,继续依赖 SDK 在 HTTP 401 时恢复;MCPHub 无法推断不透明令牌的过期时间。已有个人连接可重新授权以开始记录过期时间。提前撤销令牌的错误仍可能出现在成功的 MCP 工具响应内部,而非 HTTP 401。MCPHub 会返回该错误,不自动重放工具,以免重复执行有副作用的操作。受支持的恢复方式是在控制台重新连接,目前没有独立的个人令牌刷新接口。
提示与排障
- 确保授权过程中使用的回调地址与已注册的
redirect_uris完全一致。 - 若部署在 HTTPS 域名下,请对外暴露
/oauth/callback或通过反向代理转发。 - 如无法完成自动发现,可显式提供
authorizationEndpoint与tokenEndpoint。 - 授权服务器吊销令牌后,可手动清理
mcp_settings.json中的旧令牌,MCPHub 会在下一次请求时重新触发授权。
显式授权服务器元数据
私有 HTTP MCP 服务与授权服务器使用不同地址时,可在服务器 JSON 配置中设置oauth.authorizationServerMetadata。它在 SDK OAuth 流程中完整替代授权服务器发现,适用于共享和个人身份,优先于发现的元数据及旧的 authorizationEndpoint / tokenEndpoint 字段;不配置时保持原有发现行为。
clientSecret 并使用 none;机密客户端根据 token 端点支持情况使用 client_secret_post 或 client_secret_basic。使用 SDK 动态注册时,配置 registration_endpoint,无需预注册客户端。该字段通过 JSON 配置/API 设置,Dashboard 编辑及模板导入导出会保留它,没有专用表单编辑器。
MCP 受保护资源发现和 SDK 的 resource indicator 校验仍针对 MCP URL 执行,不会重写或删除 resource 参数。授权提供方必须接受生成的 resource 参数,并签发上游 MCP 服务接受的 token。该配置不会使内部 broker 自动可供浏览器访问,也不保证绕过 broker 的 token 转换后仍然兼容。直接使用 Microsoft 端点时,应验证所选上游模式的租户 issuer、Graph scopes、resource 参数及 token audience。
选中的元数据随待授权 PKCE/state 保存,支持回调恢复;授权、授权码交换和刷新使用同一配置的授权服务器。回调继续校验 iss,元数据声明 authorization_response_iss_parameter_supported: true 时必须提供该参数。HTTP token 端点仍需单独启用管理员控制的 allowInsecureTokenEndpoint 例外。个人 token 加密、刷新和用户隔离保持不变;修改元数据会使个人绑定失效,需要重新连接。
该服务器级配置独立于 MCPHub 下游的 systemConfig.oauthServer 和旧的全局 systemConfig.oauth 代理,此流程不需要启用这两项全局配置。
私网 broker 授权中继
管理员也可在服务器表单中配置:选择个人 OAuth 身份,展开 OAuth 配置 → 高级设置,勾选 通过 MCPHub 中继授权,填写允许跳转的 HTTPS origin 和 broker 元数据 JSON。关闭开关会移除 relay 配置,切换为共享身份也会关闭中继。 对于/authorize 立即跳转到外部身份提供方的私网 OAuth broker,管理员可在个人 OAuth HTTP 连接器中启用 oauth.authorizationRelay,并显式提供 broker 元数据及允许跳转的 HTTPS origin:
/oauth/relay/<name>?state=… 地址,使用公网 callback 的基础路径并保留安装前缀。MCPHub 转发已保存的授权请求,不携带浏览器 cookie 或认证头,仅返回允许的外部跳转。code 兑换和刷新仍通过原 broker,其 issuer、resource、state 及 PKCE 处理保持不变。入口要求有效的个人授权流程,并验证当前连接器声明及用户权限;断开绑定或完成回调后链接失效。该链接属于临时凭据,应在反向代理访问日志中隐藏查询参数。
本功能默认关闭,与旧的全局 OAuth 代理、直接使用 Microsoft Graph token 的集成分开。它不代理 HTML、cookie、内部相对跳转、broker callback 页面或任意 URL;需要浏览器再次访问私网地址的 broker 不适用。授权端点不得包含查询参数;请求超时为 10 秒,响应头有大小上限,响应体直接丢弃,只接受跳转到允许 HTTPS origin 的 302/303/307/308。未配置的连接器行为不变。
Mock 集成测试覆盖不同用户、回调恢复、code 兑换、刷新及带认证的 MCP 请求。真实 Microsoft 兼容性尚未验证,上线前应验证应用注册、broker 模式、scope 及刷新生命周期。
记忆下游应用的授权确认
MCPHub 自身的 OAuth 授权服务器默认在每次授权时显示确认页。管理员可在 设置 → OAuth 服务器 中开启 记住用户授权 并调整 授权记忆有效期(秒),也可通过systemConfig.oauthServer 启用授权记忆(PUT /api/system-config 同样支持这些字段):
approvalLifetime 表示从用户明确批准时起计算的固定有效期,单位为秒,默认 14 天,允许范围为 1–31536000。再次授权与 refresh token 轮换不会延长该期限。批准过期后,下次授权需要重新确认;已有 access token 和 refresh token 仍遵循各自的有效期。将 alwaysShowApprovalScreen 设为 true 可恢复每次确认,不会撤销已有访问。
批准记录绑定当前用户的凭据版本、客户端 ID 与元数据、精确回调地址,以及精确的 resource 值(包括未传入的情况)。只有实际申请的权限属于已批准权限的子集时才能跳过确认。省略 scope 时使用配置的 allowedScopes;新增权限需要重新确认。公开客户端仍须使用 S256 PKCE,每次成功授权都会签发新的授权码。若客户端在重连时重新注册了新的 client ID,用户仍需重新批准。
以下管理接口使用控制台身份认证,仅操作当前用户的批准记录:
GET /api/oauth/approvals返回{ "success": true, "data": [...] },每项包含id、clientId、scopes、resource、redirectUri、approvedAt和expiresAt。DELETE /api/oauth/approvals/:approvalId撤销该记录所属应用在当前用户下的全部批准与已有令牌,包括尚未兑换的授权码。其他用户的记录返回 404。MCP OAuth access token 不能用于认证这些管理接口。
<settings-path>.approvals.json,仅文件所有者可读写;数据库模式保存在 oauth_client_approvals。备份运行状态时应保留该旁路文件。批准记录不会进入配置导出或声明式同步。从文件模式切换到数据库模式后需要重新确认;关联批准记录缺失的令牌会被拒绝。过期记录会保留,以便撤销仍有效的令牌,并在删除用户、删除客户端或撤销应用时移除。数据库副本直接读取批准记录,撤销会在下次使用令牌时生效,包括与撤销并发保存的令牌。使用 DB_SYNCHRONIZE=false 的副本部署应在升级前运行 pnpm db:setup。