前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
返回 AI 情报前线
All News · 全部资讯9369
  • Agent 静默失败导致数千美元损失:如何用外部核查机制堵漏
  • Grok Build 真实用户体验:宣传与实际的落差
  • 两个面向AI Agent的x402 API:页面质量检测与成本计算
  • AI幻觉报告泛滥,谷歌暂停开源漏洞奖励计划
  • Rust成为微软内部一级语言,与C++/C#并列
  • 生产级Agentic RAG系统实战课程
  • Claude-Mem:让AI编程工具跨会话持久记忆
  • Google Gemini 调整分层策略:免费用户只能用量最小的 Flash-Lite
  • 积分系统设计中没人会纳入预算的工程细节
  • Agenthof:用控制面让 AI Agent 的每次调用都有审计可查
  • Claude Code Mods 发布:Agent 变成可扩展平台
  • ThinkingBox:Benchmark 专门捕获 AI Agent「说完成但没做完」
  • 5 个 JSON Schema 将 AI 编程智能体的输出质量管起来
  • DeepSeek Harness v0.2 发布官方桌面客户端
  • Redis 作者新项目 DwarfStar:消费级硬件运行 DeepSeek V4
  • Chalkboard:用可视化面板追踪 AI Agent 修改过程的 Electron 工具
  • Agent PR 合并率 90% 仍可能掩盖工程工作流弱点
  • AI API 定价的隐藏成本:system prompt token 开销常被低估
  • MacBook Pro外接iPhone加速LLM推理:预填充最高提效44%
  • MCP 传输协议对比:stdio 与远程 HTTP 怎么选
  • 远程 MCP 服务器的 OAuth 2.1 认证完整指南
  • Agent报告完成但数据库未写入:分布式一致性的典型陷阱
  • Kiro Workflows:多 Agent 编排的声明式工作流框架
  • 我用AI当助产士:程序员用LLM记录分析分娩全程
  • Nocturne:可自编辑记忆的 Agent,支持遗忘策略与召回验证
  • 零依赖 Pre-commit 守卫:防止 Cursor/Claude Code 破坏整洁架构
  • Claude官方指南:如何充分释放Opus 5.5在Claude和Claude Code中的性能
  • Claude Code 接入第三方模型作子代理,省 Token 新思路
  • OpenAPI 规范一键转 MCP Server 的具体映射方法
  • 编码 Agent 权限安全:黑名单漏过 46/75 提示注入,能力边界放过 3 成
  • AI编程代理成本实测:token单价低不等于任务成本低
  • 我用 Diff Budget 约束 AI 编码 Agent 的范围蔓延
  • AI加速漏洞利用,传统漏洞表格已跟不上节奏
  • 8GB 显卡运行 510GB DeepSeek-V4.1-Flash 的实战记录
  • 本地语音转文字 pipeline:faster-whisper int8 量化实现全离线
  • 393 个 AI 构建仓库人工复审:八分之一存在严重缺陷
  • 开源工具 BootLoops + Claude 三个月产出 36 篇跨学科论文
  • Jev/TEV意图识别 vs Embedding:不是替代是分工
  • 2026年AI智能合约审计实战:从LLM到CI/CD集成
  • AI Agent通过DNS逃逸:OpenAI训练事故的技术复盘
  • Verax:为AI Agent设计的可验证紧急停止开关
  • Claude Code推出Mods系统:可直接从内部重写AI编码工具
  • IBM Bob 支持私有化部署,代码不出内网的 AI 开发时代来了
  • 近期三个 AI API 变更正在静默破坏你的线上代码
  • Angular升级全自动Agent循环架构解析
  • 7 行 Claude Code mod 可绕过 deny 规则:权限安全审计
  • Prime Intellect推出Prime Inference:前沿开源模型Serverless推理服务
  • OpenAI官方指南:如何选对GPT-6系列模型并优化提示词
  • 微软发布MAI-Transcribe-2-Streaming:实时语音转文字登顶基准榜
  • OpenAI 自研芯片 Jalapeño 量产,搭配 AMD Turin 而非英伟达
  • SQL Agent 的知识层缺失:OKF 实践(下)
  • 已加载 51 / 9369
8.0
热点
AI SCORE
技术实践2026-10-04 06:57

远程 MCP 服务器的 OAuth 2.1 认证完整指南

dev.to · AI#MCP#OAuth#安全
Editor brief · 编辑速览

详解 MCP 远程服务器如何实现 OAuth 2.1 + PKCE 认证流程,解决生产环境多租户场景下的令牌安全和轮换问题。

文章思维导图
Knowledge map
拖拽缩放
Full translation

完整中文译文

本地通过 stdio 启动的 MCP Server 会继承机器上已有的凭证。Shell 里已有 AWS_PROFILE、DOCKER_HOST,还有 ~/.config 里的一堆 token,Server 直接拿来用就行。这也是为什么大多数团队很晚才发现 MCP 鉴权问题:第一个需要全公司共享的 Server 根本没有 Shell 可以继承凭证。

远程 MCP Server 基于 Streamable HTTP 通信,架在真实的域名后面,必须对每个调用方做身份验证。Model Context Protocol 定义了具体的鉴权方式:OAuth 2.1 搭配 PKCE、元数据发现和 Bearer Token。本文从头到尾走一遍完整流程,涵盖客户端发出的具体请求,以及如何配置才能让 Claude Desktop、Cursor 和 VS Code 无需手动 workaround 就能接入你的 Server。

为什么不直接把 Token 放 URL 里

一个看似方便的捷径是 https://mcp.example.com/mcp?token=...。五分钟内能用,之后每次安全审查都会挂掉:

  • URL 会落入代理日志、浏览器历史记录和 Referer 头
  • Token 无法在不重新分发 URL 的情况下轮换
  • 没有 Audience 限制,被抓到的 Token 可以拿去撞所有内部主机
  • 每个 MCP 客户端都实现了同一套 OAuth 流程,自己搞一套 Header 方案意味着永远要给每个客户端写单独的接入文档

MCP 客户端都遵循标准流程。实现一次,所有符合规范的客户端都能直接接入,无需定制集成。

登录前客户端如何发现配置

一个受保护的 MCP 资源返回 401 Unauthorized,并带有 WWW-Authenticate 头,指向授权服务器的元数据:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource"

受保护资源文档告诉客户端授权发生在哪个地址,以及 Token 必须携带哪个 Audience:

{
  "resource": "https://mcp.example.com/mcp",
  "authorization_servers": ["https://auth.example.com"],
  "bearer_methods_supported": ["header"],
  "scopes_supported": ["tools:read", "tools:run", "admin"]
}

客户端随后获取授权服务器的元数据,按惯例放在 /.well-known/oauth-authorization-server:

{
  "issuer": "https://auth.example.com",
  "authorization_endpoint": "https://auth.example.com/authorize",
  "token_endpoint": "https://auth.example.com/token",
  "registration_endpoint": "https://auth.example.com/register",
  "code_challenge_methods_supported": ["S256"],
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "token_endpoint_auth_methods_supported": ["none", "client_secret_basic"]
}

如果你已经在跑一个身份提供商,Auth0、Okta、Keycloak 和 AWS Cognito 都暴露了这些文档。你要做的只是配置路由,而不是自己写一个鉴权服务器。

动态客户端注册

MCP 客户端不是预先注册好的应用。首次连接时它们调用注册端点,获取一个 Client ID:

POST /register HTTP/1.1
Content-Type: application/json

{
  "client_name": "Claude Desktop",
  "redirect_uris": ["http://127.0.0.1:6273/callback"],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}
{ "client_id": "mcp-local-9f3a2c", "client_secret_expires_at": 0 }

公开客户端不使用密钥。这是刻意设计的:桌面应用没法保密一个 Secret,所以 OAuth 2.1 依赖 PKCE 来保障安全。如果你的提供商禁用了动态注册,可以 out of band 发放一个 Client ID,让用户在 MCP URL 配置里传入;流程中其他部分保持不变。

PKCE 授权码流程

客户端生成一个 Code Verifier 及其 SHA-256 Challenge,然后打开浏览器:

https://auth.example.com/authorize
  ?response_type=code
  &client_id=mcp-local-9f3a2c
  &redirect_uri=http://127.0.0.1:6273/callback
  &scope=tools:read%20tools:run
  &state=8xZ1...
  &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
  &code_challenge_method=S256

用户同意后,浏览器重定向到回环地址并带上一个 Code。客户端用它换 Token,同时证明自己持有 Verifier:

curl -X POST https://auth.example.com/token \
  -d grant_type=authorization_code \
  -d client_id=mcp-local-9f3a2c \
  -d code=SplxlOBeZQQYbYS6WxSbIA \
  -d redirect_uri=http://127.0.0.1:6273/callback \
  -d code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_token": "v1.MTQwYzI3...",
  "scope": "tools:read tools:run"
}

从此以后,每次对 MCP 端点的 JSON-RPC 请求都携带 Bearer Token:

POST /mcp HTTP/1.1
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
Content-Type: application/json
Accept: application/json, text/event-stream

{"jsonrpc":"2.0","id":1,"method":"tools/list"}

Access Token 的生命周期应该是分钟级,而不是周级。Refresh Token 才是长期凭证,而且可以在服务端直接撤销,不影响客户端。

用与工具实际行为匹配的 Scope

一旦 Server 暴露了横跨三个服务的二十个工具,扁平的 read/write Scope 会很快变得不够用。按能力划分 Scope 并在每次调用时做校验:

注册时把每个工具映射到一个 Scope,收到调用时直接拒绝并返回结构化错误,而不是让 Agent 在把东西搞坏之后才摸索到边界:

{
  "jsonrpc": "2.0",
  "id": 7,
  "error": {
    "code": -32003,
    "message": "token lacks scope tools:run:write",
    "data": { "required_scope": "tools:run:write" }
  }
}

阻挡真实客户端的四个常见错误

接了几个内部 Server 之后,支撑工单里几乎全是以下四个问题:

元数据通过 HTTP 提供,或结尾斜杠不匹配。 Token 里的 Issuer 必须和 Issuer 字段完全一致,包括协议和主机名。

允许列表里没有回环地址重定向。 桌面客户端用 http://127.0.0.1:<port>/callback,拒绝回环 URI 会导致登录无法完成。

Token 没有 Audience。 多租户身份提供商默认签发的 Token 可以用于你拥有的所有应用,除非你设置了 aud 并做校验。

把时钟偏差当作致命错误。 在过期校验上至少留 60 秒的缓冲;笔记本时钟很容易漂移。

先用纯 HTTP 客户端把整个链路验证通。curl 元数据文档、在浏览器里跑授权流程、用 Token 调用 initialize 和 tools/list。等裸请求跑通之后,MCP Inspector 可以交互式地驱动 OAuth 流程。

规范从何而来

当一个团队把 OpenAPI 文档作为托管 MCP Server 发布时,鉴权就是 Demo 和基础设施之间的分水岭:文档保持公开,而接触真实系统的工具则藏在 OAuth 后面,带有按用户划分的 Scope 和审计日志。发布那个端点只是从一份规范生成构建产物,而不是再实现一套安全方案。

如果你想看这个流程的托管端,参考从一份规范同时发布 API 文档和 MCP 端点(部署在你自己的域名上),以及 MCP stdio 与远程传输的对比(了解什么时候才真正需要托管部署)。也可以试试本地优先的工作流——Server 起在本地机器上,根本不存在鉴权面——在线 Demo 里有演示。

Original source

本文由 AI 翻译整理自 dev.to · AI,原文版权归原作者所有。

阅读英文原文
上一篇
MCP 传输协议对比:stdio 与远程 HTTP 怎么选
下一篇
Agent报告完成但数据库未写入:分布式一致性的典型陷阱