设备授权流(RFC 8628)
无浏览器的 MCP 客户端(桌面 / CLI Agent)的登录方式:设备显示用户码,用户在任意浏览器完成确认。
流程
设备 AuthKeystone 用户浏览器
│ POST /oauth/device/authorize ──────────▶│ │
│ ◀── device_code + user_code ────────────│ │
│ │◀── GET /device?user_code ──────│
│ │─── 登录 + 批准/拒绝 ──────────▶│
│ POST /oauth/token (device_code) ─────▶│ │
│ ◀── access_token / authorization_pending│ │
1. 设备发起
POST https://auth.ai-as.cc/oauth/device/authorize
Content-Type: application/x-www-form-urlencoded
client_id=mcp_cli_client
&scope=openid profile auth:permissions
&resource=https://mcp.erp/api # 可选,RFC 8707 → token aud
响应:
{
"device_code": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk",
"user_code": "WDJB-MJHT",
"verification_uri": "https://auth.ai-as.cc/admin/#/device",
"verification_uri_complete": "https://auth.ai-as.cc/admin/#/device?user_code=WDJB-MJHT",
"expires_in": 600,
"interval": 5
}
设备展示 user_code 与 verification_uri(有屏幕的设备直接展示 verification_uri_complete 二维码)。
前置条件:client 的 grant_types 含 urn:ietf:params:oauth:grant-type:device_code(后台勾选 device_code)。公开客户端(CLI)免 secret,走 PKCE 同级的安全性由用户确认环节保证。
2. 用户确认
浏览器打开 verification_uri_complete(或打开确认页手输用户码)→ 登录 → 授权页展示 client 与 scope 明细 → 批准 / 拒绝。
3. 设备轮询
按 interval 秒轮询:
POST /oauth/token
grant_type=urn:ietf:params:oauth:grant-type:device_code
&device_code=<device_code>
&client_id=mcp_cli_client
| 状态 | 响应(HTTP 400 + error) |
|---|---|
| 等待用户确认 | authorization_pending |
| 轮询快于 interval | slow_down |
| 用户拒绝 | access_denied |
| 设备码过期(600s) | expired_token |
| 已批准 | 200,标准 token 响应(access + refresh + id_token) |
批准后设备码一次性消费,重放返回 invalid_grant。签发的 token:sub = 批准用户,aud = resource(传了的话)否则 client_id。