跳到主要内容

设备码授权概览

本文说明什么是设备码授权。

如果你需要进一步了解如何用 CloudBase CLI 与参考实现完成具体对接,请继续阅读 企业自建设备码授权服务对接 CloudBase CLI


1. 为什么要用设备码授权

设备码授权解决的核心问题是:发起登录请求的终端,与完成网页登录确认的浏览器,往往不在同一台机器,也不在同一个交互界面里。

典型场景包括:

  1. 用户在远程服务器、跳板机、容器或云端开发机里发起 CloudBase 登录,但浏览器在本地电脑上。
  2. 用户通过聊天工具或类 OpenClaw 的对话式 AI 工具触发 CloudBase 登录,请求是由机器人或远端执行器发起的,浏览器确认却发生在用户自己的设备上。

这类场景下,传统“终端直接拉起浏览器并等待回调”的登录方式往往不可用。设备码授权把流程拆成两段:

  1. 终端先申请一组 device_codeuser_code
  2. 用户再去浏览器里确认“是否允许这次 CloudBase 登录”。

这样做的价值在于:

  1. 终端侧只负责发起请求和轮询结果,不要求能完成浏览器回调。
  2. 浏览器侧只负责身份认证和授权确认,不要求和使用 CLI/MCP 发起 CloudBase 登录的客户端在同一个进程或同一台机器上。
  3. 同一套流程既能支持普通终端,也能支持聊天工具、代理执行器、远程任务这类异步交互场景。

2. 协议约定

一套设备码授权服务通常需要实现 3 个核心接口:

接口方法作用
/auth/device/codePOST终端申请设备码,获取 device_codeuser_codeverification_uri
/auth/device/verifyPOST浏览器侧确认授权,把设备码状态从 pending 更新为 authorized
/auth/tokenPOST负责首次换取凭证、刷新凭证、撤销会话

其中 /auth/token 通过 grant_type 区分 3 种动作:

grant_type作用
urn:ietf:params:oauth:grant-type:device_code使用 device_code 首次换取凭证
refresh_token使用 refreshToken 刷新临时凭证,并轮换新的 refreshToken
revoke_token撤销 refreshToken 对应会话,供 tcb logout 使用

2.1 核心请求与响应

POST /auth/device/code

请求:

{
"client_id": "cloudbase-cli"
}

成功响应:

{
"device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS8A",
"user_code": "QWER-ASDF",
"verification_uri": "https://auth.example.com/cli-auth",
"expires_in": 600,
"interval": 3
}

POST /auth/device/verify

这是浏览器侧接口,路径可以由企业自行设计,但职责必须一致:

  1. 校验当前用户已经完成企业身份认证。
  2. 接收 user_code
  3. 找到对应的 device_code 记录。
  4. 把授权状态从 pending 更新为 authorized
  5. 绑定当前用户身份,供后续签发临时凭证使用。

参考请求:

{
"user_code": "QWER-ASDF"
}

POST /auth/token with grant_type=device_code

终端轮询请求:

{
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
"device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS8A",
"client_id": "cloudbase-cli",
"device_info": {
"os": "darwin",
"mac": "AA:BB:CC:DD:EE:FF",
"hash": "a1b2c3d4e5f6..."
}
}

成功响应需要返回一组可供客户端保存和后续使用的登录凭证,核心字段如下:

字段说明
refreshToken长期令牌;如果实现自动续期,必须返回非空值
expiredrefreshToken 的过期时间戳(毫秒)
tmpSecretId腾讯云临时密钥 SecretId
tmpSecretKey腾讯云临时密钥 SecretKey
tmpToken腾讯云临时安全令牌
tmpExpired临时密钥过期时间戳(毫秒)
uin当前登录用户标识
tokenId会话或令牌 ID
envIds可选
envList可选
envBillingInfoList可选

如果你的企业自建授权服务需要在自定义 endpoint 场景下返回这 3 个字段,可以按下面的结构组织:

envIds:

[
"cloud1-123456",
"cloud1-abcdef"
]

envList:

字段类型说明
EnvIdstring环境 ID
Aliasstring环境别名
Statusstring环境状态
Sourcestring环境来源,例如小程序或腾讯云
CreateTimestring创建时间
UpdateTimestring最后更新时间
PackageIdstring套餐 ID
PackageNamestring套餐名称
PayModestring支付方式
IsDefaultboolean是否默认环境
Regionstring环境地域

envBillingInfoList:

字段类型说明
EnvIdstring环境 ID
PackageIdstring套餐 ID
IsAutoRenewboolean是否自动续费
Statusstring计费状态
PayModestring计费模式
IsolatedTimestring隔离时间
ExpireTimestring过期时间
CreateTimestring首次接入计费时间
UpdateTimestring最近更新时间
IsAlwaysFreeboolean是否从未升级过付费版
PaymentChannelstring支付渠道
FreeQuotastring免费额度信息
EnableOverrunboolean是否开启超额按量付费
ExtPackageTypestring环境套餐类型

如果你需要进一步实现这两个对象数组,可参考调用腾讯云云 API 获取对应返回结构:

  1. DescribeEnvshttps://cloud.tencent.com/document/product/876/34820
  2. DescribeBillingInfohttps://cloud.tencent.com/document/product/876/94390

POST /auth/token with grant_type=refresh_token

{
"grant_type": "refresh_token",
"refresh_token": "<refreshToken>",
"client_id": "cloudbase-cli"
}

推荐行为:

  1. 校验当前 refresh token。
  2. 重新签发临时凭证。
  3. 轮换新的 refreshToken
  4. 让旧 refreshToken 立即失效。

POST /auth/token with grant_type=revoke_token

{
"grant_type": "revoke_token",
"refresh_token": "<refreshToken>",
"client_id": "cloudbase-cli"
}

推荐行为:删除或失效对应会话,并返回 {}。这个接口应保持幂等。

2.2 建议错误码

错误码典型场景
authorization_pending用户还没有在浏览器中确认授权
slow_down客户端轮询过快
expired_tokendevice_code 已过期
invalid_clientclient_id 缺失、非法或不匹配
invalid_grantdevice_coderefresh_token 或授权状态异常
unsupported_grant_type不支持的 grant_type
already_consumed设备码已成功使用过
server_error服务端签发临时凭证失败