4. 客户端凭证模式与设备码模式
在 OAuth2 授权框架中,客户端凭证模式(Client Credentials Grant)与设备码模式(Device Code Grant)分别解决了两个截然不同的场景:服务间无用户参与的通信,以及无浏览器或输入受限设备上的用户授权。理解这两种模式的适用边界、流程差异和安全风险,是构建健壮 API 权限体系的关键。
4.1 客户端凭证模式:服务间通信的专用通道
客户端凭证模式适用于没有最终用户参与的场景,例如后端微服务之间的数据同步、定时任务调用管理 API、或服务器到服务器的批量操作。该模式下,客户端使用自身的凭证(client_id + client_secret)直接向授权服务器请求 access_token,无需授权码或用户交互。
核心特征:客户端既是资源所有者,也是授权请求方。令牌代表客户端应用本身,而非某个用户。
4.1.1 流程步骤
- 客户端认证:客户端向授权服务器的令牌端点发送 POST 请求,携带
grant_type=client_credentials以及自身的 client_id 和 client_secret。 - 授权服务器验证:服务器验证客户端凭证的有效性,并检查客户端是否有权访问所请求的资源范围。
- 颁发令牌:验证通过后,授权服务器直接返回 access_token(通常不颁发 refresh_token,因为客户端凭证可以随时重新获取令牌)。
- 访问资源:客户端使用 access_token 调用受保护的 API。
安全提示:由于令牌直接代表客户端身份,务必对 client_secret 进行高强度保护(如使用密钥管理服务、环境变量注入),并限制令牌的作用域(scope)为最小必要权限。
4.1.2 客户端凭证模式流程图
4.2 设备码模式:无浏览器设备的授权方案
设备码模式专为无浏览器或输入能力受限的设备设计,例如智能电视、物联网传感器、命令行工具、或打印机。用户无法在这些设备上直接输入用户名和密码,但可以通过另一台设备(如手机或电脑)上的浏览器完成授权。
安全风险提示:设备码模式涉及用户手动输入设备码,存在中间人钓鱼攻击的风险。攻击者可能伪造设备码页面诱导用户授权。必须确保用户验证的 URL 是可信的,并实施短有效期和速率限制。
4.2.1 流程步骤
- 设备发起请求:设备向授权服务器的设备授权端点发送 POST 请求,携带 client_id。
- 服务器返回设备码和用户码:授权服务器返回
device_code、user_code、verification_uri以及interval(轮询间隔)。 - 用户手动授权:设备在屏幕上显示
user_code和verification_uri。用户使用手机或电脑浏览器访问该 URI,输入user_code并完成登录授权。 - 设备轮询令牌:设备以
interval为间隔,向令牌端点发送device_code和grant_type=urn:ietf:params:oauth:grant-type:device_code,轮询授权结果。 - 授权服务器颁发令牌:一旦用户在浏览器中完成授权,服务器在下一次轮询时返回
access_token(可选refresh_token)。
4.2.2 设备码模式交互图
4.3 两种模式对比
| 对比维度 | 客户端凭证模式 | 设备码模式 |
|---|---|---|
| 适用场景 | 服务间通信、后台任务、CLI 工具(无用户) | 智能电视、IoT 设备、命令行(有用户但无浏览器) |
| 用户参与 | 无需用户 | 需要用户通过浏览器手动授权 |
| 令牌代表 | 客户端应用身份 | 用户身份(通过设备代理) |
| 主要安全风险 | 客户端凭证泄露、权限过大 | 设备码钓鱼、用户码暴力破解 |
| 令牌刷新 | 通常不颁发 refresh_token | 可颁发 refresh_token 用于长期访问 |
| 典型 grant_type | client_credentials |
urn:ietf:params:oauth:grant-type:device_code |
4.4 错误码断言实践要点
在实现这两种模式时,安全错误码断言机制需要针对各自的特点进行调整:
- 客户端凭证模式:当授权服务器返回
invalid_client错误时,表明 client_secret 可能已泄露或过期,应立即触发告警并轮换密钥。对于invalid_scope错误,应检查客户端请求的权限范围是否超出其授权列表。 - 设备码模式:设备在轮询过程中可能收到
authorization_pending(用户尚未完成授权)、slow_down(轮询过于频繁,需增加间隔)或expired_token(设备码已过期)等错误。客户端必须正确处理这些错误码,尤其是slow_down,以避免被授权服务器限流。
最佳实践:在客户端凭证模式中,始终使用 HTTPS 并考虑使用 JWT 断言(client assertion)替代共享密钥;在设备码模式中,强制用户码使用高熵值并设置短有效期,同时在用户授权页面展示设备类型和位置信息以增强用户信任。