设想:
- 当您用微信账号登录第三方笔记工具,为何无需向笔记软件泄露密码?
- 当企业ERP系统自动同步CRM数据时,如何避免凭证硬编码的安全风险?
这背后正是OAuth构建的信任桥梁,OAuth 目前已经进化到2.1,MCP的安全认证部分就是用的OAuth 2.1。
OAuth 2.1 的由来
OAuth(开放授权)是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而无需将用户名和密码提供给第三方应用。
OAuth 2.0 是 OAuth 协议的第二个版本,它不兼容 OAuth 1.0。它的改进在于简化了开发和提高了灵活性,使其能够适应多种不同的应用场景,而不仅仅是传统的网页应用。
OAuth 2.1 是 OAuth 2.0 的安全演进版本,旨在整合最佳实践并修复已知漏洞。它移除隐式授权、资源所有者密码凭据授权这两种授权模式。
OAuth 相关的四种角色:
- 资源所有者(Resource Owner):能够授权访问受保护资源的实体,通常是最终用户。
- 资源服务器(Resource Server):托管受保护资源的服务器,能够使用访问令牌(Access Token)接受和响应受保护资源的请求,也就是存储用户数据的服务(API 服务器)。
- 客户端(Client):代表资源所有者且经其授权发出对受保护资源的请求的应用程序,通常是第三方应用。
- 授权服务器(Authorization Server):在认证资源所有者并获取其授权后,向客户端颁发访问令牌,也就是签发令牌的服务(如 Google、GitHub)。
这四种角色之间的关系如下:
- 客户端使用令牌访问资源服务器
- 资源服务器必须验证令牌有效性
OAuth 2.1 授权模式:
OAuth 2.1 旨在解决 OAuth 2.0 在过去十几年中暴露的一些安全问题和实施复杂性。通过移除一些不安全的旧流程并强制要求使用一些安全扩展来提高整体安全性。
-
授权码模式 (Authorization Code) + PKCE(Proof Key for Code Exchange):需要用户登录的前端应用(SPA/移动端/Web),强调用户授权与防钓鱼攻击。
-
客户端模式 (Client Credentials):适用于机器对机器(M2M)场景,服务间后台通信(微服务/自动化任务),依赖凭证保密性与最小权限管控。
授权码模式(Authorization Code Grant) + PKCE 流程
关键点:客户端发送授权码换取令牌
适用场景:所有需要用户交互的应用(Web、SPA、移动端等)。
强制要求集成 PKCE(Proof Key for Code Exchange)
PKCE 的作用:
- 防止授权码拦截攻击(如公共客户端无法安全存储 client_secret 的场景)
- 通过动态生成的 code_verifier 和 code_challenge 验证客户端身份,即使授权码泄露也无法换取令牌
那 PKCE 为什么有这种魔力呢? 实际上它的原理是客户端提供一个自创建的证明给授权服务器, 授权服务器通过它来验证客户端,把访问令牌(access_token) 颁发给真实的客户端而不是伪造的。
流程
特点:
-
强制集成 PKCE(Proof Key for Code Exchange)
- 客户端需生成 code_verifier(随机字符串)和 code_challenge(其哈希值)
- 授权请求时携带 code_challenge,令牌请求时提交 code_verifier 供验证
-
令牌传递禁止通过 URL
- 访问令牌必须通过 Authorization: Bearer 头部传递,禁止 URL 参数
OAuth 2.0 时特点:
- 最安全:通过两次通信获取令牌
- 令牌不经过浏览器(后端通信)
- 适合 Web 服务器端应用
OAuth 2.1 的强化点:
| 步骤 | OAuth 2.0 | OAuth 2.1 | 安全意义 |
|---|---|---|---|
| 步骤2 | 仅重定向 | 重定向时携带 code_challenge | 防御授权码拦截攻击 |
| 步骤6 | 发送 client_secret 发送 code_verifier(替代凭证) | 消除公共客户端密钥泄露风险 | |
| 步骤7 | 令牌可能通过URL返回 | 强制通过HTTP头部传递 | 防止浏览器历史/日志泄露令牌 |
PKCE 工作原理:
- code_verifier:客户端生成的43-128位随机字符串
- code_challenge = BASE64URL(SHA256(code_verifier))
授权服务器通过比对哈希值验证请求合法性
客户端模式(Client Credentials Grant)流程
关键点:客户端发送自身凭证换取令牌
适用于机器对机器(M2M)场景
安全增强:
- 强化安全实践:要求使用 HTTPS 传输,且客户端凭证需加密存储(如 Keystore/Keychain)
- 推荐短期令牌+刷新令牌轮换机制:访问令牌生命周期缩短,刷新令牌应为一次性(每次换取新令牌后旧令牌失效)
OAuth 2.0特点:
- 无用户参与
- 机器对机器通信
- 用于 API 服务间认证
OAuth 2.1 对安全的增强
| 实践 | 说明 |
|---|---|
| 凭证存储 | 使用密钥管理系统(KMS)或硬件安全模块(HSM)保护 client_secret |
| 刷新令牌轮换 | 每次刷新后旧刷新令牌立即失效,防止重用 |
| 令牌绑定 | 建议绑定客户端实例(如DPoP协议),防止令牌劫持 |
客户端模式需要 PKCE 吗?
不需要,且 PKCE 不适用。原因如下:
设计目标不同
PKCE 专为防御 授权码拦截攻击 设计,通过动态 code_verifier 绑定初始请求与令牌交换。客户端模式无授权码步骤,直接通过凭证交换令牌,无需此机制。
安全依赖不同
客户端模式的安全基础是 client_secret 的保密性 与 HTTPS 传输,而非动态挑战。OAuth 2.1 要求对该模式强化凭证存储(如 HSM 加密)而非引入 PKCE。
适用场景
1、机器对机器(M2M)通信
- 微服务间认证:订单服务调用支付服务 API,使用自身 client_id/client_secret 获取令牌。
- 自动化任务:定时报表生成、数据同步任务,以系统身份调用 API。
2、 无用户上下文的后台服务
- 基础设施访问:监控服务拉取服务器指标,令牌权限限制为只读。
- 内部工具链:CI/CD 流水线调用部署 API,凭证存储于安全仓库(如 Vault)。
3、 安全强化要求
- 凭证加密存储:client_secret 必须存于 HSM/Keystore,禁止明文。
- 短期令牌策略:访问令牌生命周期短(如 10 分钟),减少泄露风险。
典型时序:服务 A → 提交凭证换取令牌 → 访问服务 B 的 API。
区别:
| 授权模式 | 授权码模式 + PKCE | 客户端凭证模式 |
|---|---|---|
| 关键交互点(客户端↔授权服务器) | 客户端发送授权码换取令牌 | 客户端发送自身凭证换取令牌 |
| 用户参与 | ✅ 需要 | ❌ 不需要,服务器间调用 |
| 核心机制 | code_challenge/code_verifier | client_id/client_secret |
| 传输加密 | 强制 HTTPS(TLS 1.3+) | 强制 HTTPS(TLS 1.3+) |
| 凭证存储 | 无需 client_secret(公共客户端) | 加密存储于 HSM/Keychain |
| 令牌传递方式 | 仅 HTTP Header | 仅 HTTP Header |
| 刷新令牌 | 支持,需轮换或绑定客户端 | 通常不提供(或短期一次性令牌) |
总结
-
用授权码模式 + PKCE 当:需要用户登录的前端应用(SPA/移动端/Web),强调用户授权与防钓鱼攻击。
-
用客户端模式当:服务间后台通信(微服务/自动化任务),依赖凭证保密性与最小权限管控。
MCP协议支持 OAuth
MCP协议的最新规范(2025-03-26版)明确要求支持OAuth 2.1授权流程。
https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization
带认证的MCP服务请求时序图如下:
上图中MCP的几个角色必须实现的如下:
MCP 客户端 (Client)
MCP 客户端是请求访问受保护资源的应用程序。它必须实现以下功能:
-
OAuth 2.0 授权流程:
- 授权服务器发现: 使用 OAuth 2.0 Protected Resource Metadata 来发现认证服务器。
- 授权请求: 必须使用 PKCE (Proof Key for Code Exchange) 来防止授权码被拦截。
- 令牌请求: 必须在授权请求和令牌请求中包含 resource 参数(遵循 RFC 8707)。
-
访问令牌处理:
- 使用 Authorization 请求头字段携带访问令牌。
- 必须能够解析 WWW-Authenticate 头部,并根据 HTTP 401 Unauthorized 响应作出适当的处理。
MCP 服务器 (Resource Server)
MCP 服务器是受保护资源的宿主,它必须充当 OAuth 2.1 资源服务器。它必须实现以下功能:
-
元数据提供:
- 提供 OAuth 2.0 Protected Resource Metadata (RFC9728),其文档中必须包含 authorization_servers 字段,以指示认证服务器的位置。
-
访问令牌验证:
- 在处理请求之前,必须验证收到的访问令牌是否有效。
- 必须验证访问令牌的受众 (audience),确保令牌是专门为该服务器颁发的。
-
错误处理:
- 当返回 HTTP 401 Unauthorized 响应时,必须在响应的 WWW-Authenticate HTTP 头部中指示其 Protected Resource Metadata 的 URL 地址。
- 必须根据不同的错误情况返回适当的 HTTP 状态码(如 400 Bad Request、401 Unauthorized、403 Forbidden)。
认证服务器 (Authorization Server)
认证服务器负责向客户端颁发访问令牌。它必须实现以下功能:
-
OAuth 2.1 协议: 必须遵守 OAuth 2.1 协议,并实施相应的安全措施。
-
元数据提供: 提供 OAuth 2.0 Authorization Server Metadata (RFC8414),包含用于发现和配置其服务的必要信息。
-
安全性要求:
- 协议安全: 必须通过 HTTPS 提供服务。
- 令牌管理: 应对公共客户端轮换刷新令牌,并建议颁发短期访问令牌。
- 重定向 URI 验证: 必须根据预先注册的值精确验证重定向 URI。
-
客户端注册: 建议支持 OAuth 2.0 Dynamic Client Registration Protocol (RFC7591) 以简化客户端的注册过程。
MCP的选择本质是安全优先策略:
- 安全加固:OAuth 2.1 剔除了不安全的授权模式,并强制要求将 PKCE 集成到授权码流程中,从而显著增强了对授权码拦截攻击的防御能力。
- 生态兼容性:复用企业已部署的OAuth基础设施,加速协议落地。
总结
OAuth 2.1 在安全授权领域扮演的关键角色,它不仅是 OAuth 2.0 的简单升级,更是一场重要的安全实践整合与强化:
-
模式的精炼与强化:OAuth 2.1 剔除了不安全的授权模式,并强制要求将 PKCE 集成到授权码流程中,从而显著增强了对授权码拦截攻击的防御能力。
-
角色的精准划分:它再次强调了授权服务器与资源服务器的职责分离,以及客户端在不同场景下的不同安全需求,通过 客户端凭证模式 满足了机器对机器通信的特殊需要。
-
面向未来的标准:新兴的 MCP 协议 明确将 OAuth 2.1 纳入其规范,证明了这一安全框架已成为现代协议构建可信认证授权生态的基石。
浙公网安备 33010602011771号