Device Code Authorization Overview
This article explains what device code authorization is.
If you need to further understand how to use CloudBase CLI and the reference implementation to complete specific integration, please continue reading Enterprise Self-built Device Code Authorization Service Integration with CloudBase CLI.
1. Why Use Device Code Authorization
The core problem that device code authorization solves is: the terminal that initiates the login request and the browser that completes the web login confirmation are often not on the same machine, nor in the same interaction interface.
Typical scenarios include:
- Users initiate CloudBase login on a remote server, jump server, container, or cloud development machine, but the browser is on the local computer.
- Users trigger CloudBase login through chat tools or conversational AI tools like OpenClaw. The request is initiated by a bot or remote executor, but the browser confirmation occurs on the user's own device.
In such scenarios, the traditional login method of "terminal directly launching the browser and waiting for callback" is often unavailable. Device code authorization splits the flow into two segments:
- The terminal first requests a set of
device_codeanduser_code. - The user then goes to the browser to confirm "whether to allow this CloudBase login".
The value of this approach is:
- The terminal side is only responsible for initiating requests and polling for results, without requiring the ability to complete browser callbacks.
- The browser side is only responsible for identity authentication and authorization confirmation, without requiring it to be in the same process or on the same machine as the client that uses CLI/MCP to initiate CloudBase login.
- The same flow can support both ordinary terminals and asynchronous interaction scenarios such as chat tools, agent executors, and remote tasks.
2. Protocol Specification
A device code authorization service typically needs to implement 3 core interfaces:
| Interface | Method | Function |
|---|---|---|
/auth/device/code | POST | Terminal requests device code, obtains device_code, user_code, verification_uri |
/auth/device/verify | POST | Browser side confirms authorization, updates device code status from pending to authorized |
/auth/token | POST | Responsible for first credential exchange, credential refresh, and session revocation |
Among them, /auth/token distinguishes 3 actions through grant_type:
grant_type | Function |
|---|---|
urn:ietf:params:oauth:grant-type:device_code | Use device_code to exchange for credentials for the first time |
refresh_token | Use refreshToken to refresh temporary credentials, and rotate a new refreshToken |
revoke_token | Revoke the session corresponding to refreshToken, used by tcb logout |
2.1 Core Requests and Responses
POST /auth/device/code
Request:
{
"client_id": "cloudbase-cli"
}
Success response:
{
"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
This is the browser-side interface. The path can be designed by the enterprise itself, but the responsibility must be consistent:
- Verify that the current user has completed enterprise identity authentication.
- Receive
user_code. - Find the corresponding
device_coderecord. - Update the authorization status from
pendingtoauthorized. - Bind the current user identity for subsequent temporary credential issuance.
Reference request:
{
"user_code": "QWER-ASDF"
}
POST /auth/token with grant_type=device_code
Terminal polling request:
{
"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..."
}
}
The success response needs to return a set of login credentials that the client can save and use subsequently. The core fields are as follows:
| Field | Description |
|---|---|
refreshToken | Long-term token; if auto-renewal is implemented, a non-empty value must be returned |
expired | Expiration timestamp (milliseconds) of refreshToken |
tmpSecretId | Tencent Cloud temporary key SecretId |
tmpSecretKey | Tencent Cloud temporary key SecretKey |
tmpToken | Tencent Cloud temporary security token |
tmpExpired | Temporary key expiration timestamp (milliseconds) |
uin | Current logged-in user identifier |
tokenId | Session or token ID |
envIds | Optional |
envList | Optional |
envBillingInfoList | Optional |
If your enterprise self-built authorization service needs to return these 3 fields in custom endpoint scenarios, you can organize them according to the following structure:
envIds:
[
"cloud1-123456",
"cloud1-abcdef"
]
envList:
| Field | Type | Description |
|---|---|---|
EnvId | string | Environment ID |
Alias | string | Environment alias |
Status | string | Environment status |
Source | string | Environment source, such as Mini Program or Tencent Cloud |
CreateTime | string | Creation time |
UpdateTime | string | Last update time |
PackageId | string | Package ID |
PackageName | string | Package name |
PayMode | string | Payment method |
IsDefault | boolean | Whether it is the default environment |
Region | string | Environment region |
envBillingInfoList:
| Field | Type | Description |
|---|---|---|
EnvId | string | Environment ID |
PackageId | string | Package ID |
IsAutoRenew | boolean | Whether auto-renewal is enabled |
Status | string | Billing status |
PayMode | string | Billing mode |
IsolatedTime | string | Isolation time |
ExpireTime | string | Expiration time |
CreateTime | string | First billing access time |
UpdateTime | string | Last update time |
IsAlwaysFree | boolean | Whether it has never been upgraded to paid version |
PaymentChannel | string | Payment channel |
FreeQuota | string | Free quota information |
EnableOverrun | boolean | Whether overflow pay-as-you-go is enabled |
ExtPackageType | string | Environment package type |
If you need to further implement these two object arrays, you can refer to calling Tencent Cloud API to obtain the corresponding response structure:
DescribeEnvs:https://cloud.tencent.com/document/product/876/34820DescribeBillingInfo:https://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"
}
Recommended behavior:
- Verify the current refresh token.
- Re-issue temporary credentials.
- Rotate a new
refreshToken. - Immediately invalidate the old
refreshToken.
POST /auth/token with grant_type=revoke_token
{
"grant_type": "revoke_token",
"refresh_token": "<refreshToken>",
"client_id": "cloudbase-cli"
}
Recommended behavior: Delete or invalidate the corresponding session, and return {}. This interface should remain idempotent.
2.2 Recommended Error Codes
| Error Code | Typical Scenario |
|---|---|
authorization_pending | User has not confirmed authorization in the browser |
slow_down | Client polling is too frequent |
expired_token | device_code has expired |
invalid_client | client_id is missing, invalid, or does not match |
invalid_grant | device_code, refresh_token, or authorization status is abnormal |
unsupported_grant_type | Unsupported grant_type |
already_consumed | Device code has already been used successfully |
server_error | Server failed to issue temporary credentials |