跳转到内容

设备码授权流程

查看 Markdown

设备码授权适合不能安全保存应用 client-auth 私钥的客户端:CLI、启动器、终端工具、共享设备,以及其他公共客户端。客户端向 Sudomimus 请求一组短暂有效的 deviceCode / userCode,把用户码展示给用户,引导用户到浏览器确认,然后轮询直到批准变成普通的 Sudomimus 应用令牌。

实现时请从 SDK 选择指南 和你所用语言的页面开始。请参考现有语言指南或下方协议示例,并在 SDK 源文档中确认包的可用性。

这条流程遵循 OAuth 2.0 Device Authorization Grant(RFC 8628) 的模型:发起客户端拿到 device code 和 user code,用户在有浏览器能力的 user agent 中批准,客户端持续轮询直到授权完成。Sudomimus 保留标准 device-flow 形状,但最终返回的是 Sudomimus 应用令牌。

它是独立于 Connect 和 Native direct-issue 的接入路径:

路径 请求靠什么证明
Connect 应用私钥签出的 client-auth JWT
Native direct-issue Steam ticket 或 AccessKey secret 这样的平台凭据
设备码授权 公共客户端开启码会话,浏览器里的用户批准它

公开 HTTP 服务是 device-api.sudomimus.com。浏览器批准页面仍然由 via.sudomimus.com 承载。

步骤 发起方 端点 结果
1. 开始 客户端 device-api POST /device-authorize { deviceCode, userCode, verificationUri, verificationUriComplete, expiresIn, interval }
2. 批准 浏览器中的用户 via.sudomimus.com/device 用户登录、确认显示的码,并批准或拒绝
3. 轮询 客户端 device-api POST /device-token 等待状态、轮询指令、拒绝、过期,或 { accessToken, refreshToken }
4. 继续使用 客户端 session-api POST /refresh 后续令牌轮换使用普通 Session API 令牌操作
sequenceDiagram
    autonumber

    participant Client as 公共客户端
    participant Browser as 用户浏览器
    participant Device as Device API
    participant Via as via.sudomimus.com
    participant Session as Session API

    Client->>Device: POST /device-authorize<br/>applicationAnchor
    Device-->>Client: deviceCode + userCode<br/>verificationUri + interval
    Client-->>Browser: 打开 verificationUri<br/>展示 userCode

    par 浏览器批准
        Browser->>Via: 打开 /device 并确认 userCode
        Note over Browser,Via: 用户完成认证并批准
        Via-->>Browser: 已批准;返回客户端
    and 客户端轮询
        loop 直到批准完成
            Client->>Device: POST /device-token<br/>deviceCode
            Device-->>Client: authorization_pending 或 slow_down
        end
    end

    Client->>Device: POST /device-token<br/>deviceCode
    Device-->>Client: accessToken + refreshToken<br/>设备会话已消费

    Client->>Session: 后续:POST /refresh<br/>refreshToken
    Session-->>Client: 新 accessToken + 轮换后的 refreshToken

只有客户端能看到 deviceCode。只有用户看到并确认 userCode。/device-token 成功后会消费这次设备会话,所以同一个 deviceCode 不能再签发第二组令牌。

客户端先提交应用 anchor:

终端窗口
curl -X POST https://device-api.sudomimus.com/device-authorize \
-H "Content-Type: application/json" \
-d '{
"applicationAnchor": "your-application"
}'

成功响应:

{
"applicationAnchor": "your-application",
"deviceCode": "dvc_...",
"userCode": "ABCD-EFGH",
"verificationUri": "https://via.sudomimus.com/device",
"verificationUriComplete": "https://via.sudomimus.com/device?user_code=ABCD-EFGH",
"expiresIn": 600,
"interval": 5
}

/device-authorize 不接收 client-auth JWT。应用通过配置选择开放这条路径:它必须有一条启用的 Layer 3 DEVICE_CODE ReturnRule。如果缺少这条规则,请求会被拒绝。

在客户端界面清楚展示 userCode,并让用户打开浏览器批准页面:

访问 https://via.sudomimus.com/device
输入验证码:ABCD-EFGH

如果可以,优先打开 verificationUriComplete。它会预填用户码,也最适合做成二维码或终端里的可点击链接:

https://via.sudomimus.com/device?user_code=ABCD-EFGH

浏览器页面会再次展示应用和验证码,让用户确认自己批准的是同一个客户端会话。浏览器永远不会收到 deviceCode,也不会显示 access token 或 refresh token;它只负责批准或拒绝这次待处理会话。

客户端用私有的 deviceCode 轮询 /device-token:

终端窗口
curl -X POST https://device-api.sudomimus.com/device-token \
-H "Content-Type: application/json" \
-d '{
"deviceCode": "dvc_..."
}'

轮询频率不要快于返回的 interval。用户还在操作时,/device-token 会返回 OAuth 风格的轮询错误:

{
"error": "authorization_pending"
}

批准完成后,同一个端点会返回普通 Sudomimus 应用令牌:

{
"applicationAnchor": "your-application",
"accessToken": "...",
"refreshToken": "...",
"claims": {
"email": { "requirement": "OPTIONAL", "state": "GRANTED" },
"firstName": { "requirement": "OFF", "state": "UNKNOWN" },
"lastName": { "requirement": "OFF", "state": "UNKNOWN" },
"staticAvatar": { "requirement": "SYNTHETIC_ONLY", "state": "UNKNOWN" },
"animatedAvatar": { "requirement": "OFF", "state": "UNKNOWN" }
}
}

claims 块展示应用的 claim policy 与用户当前共享决定的合并结果。实际 token payload 仍遵循普通 Sudomimus token 规则。

设备码授权只负责最初这次公共客户端交换。一旦 /device-token 成功,refresh token 就属于普通 Sudomimus 应用会话模型。

后续使用 Session API 令牌操作:

  • POST /refresh 轮换 refresh token 并签发新的 access token。
  • POST /logout 终态吊销当前 ApplicationSession。
  • POST /introspect 检查 token。
  • POST /revoke-all 做应用级会话吊销。

这些操作见管理会话;轮询状态机见设备码轮询与错误。

新应用初始状态为 DRAFT。配置下方规则后,由组织 OWNER 激活应用,再调用 /device-authorize。设备授权要求应用为 ACTIVE,且所属组织和扇区均可用。

应用必须允许浏览器侧认证和 realize 检查通过:

层 要求
Layer 1 现有认证方式,例如邮箱验证码或通行密钥
Layer 2 能允许该账户的现有身份规则
Layer 3 一条 DEVICE_CODE ReturnRule

DEVICE_CODE 是 Layer 3 返回方式,不是新的认证方式。用户仍然通过应用已有的 Layer 1 方法登录,也仍然要通过 Layer 2 检查后,设备会话才能被批准。

当客户端是公共客户端、无法保密 client-auth 私钥时,选择设备码授权。典型场景包括发给用户安装的 CLI、桌面启动器、纯终端环境,或者需要用户在另一台有浏览器的设备上完成登录的共享屏幕设备。

如果你有能保护 client-auth 私钥的机密后端,优先考虑 Connect 浏览器轮询。如果客户端拥有 Steam ticket 或预签发 AccessKey 这样的平台凭据,使用 Native direct-issue。

原始端点契约见 Device API 参考。