Skip to main content

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:

  1. Users initiate CloudBase login on a remote server, jump server, container, or cloud development machine, but the browser is on the local computer.
  2. 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:

  1. The terminal first requests a set of device_code and user_code.
  2. The user then goes to the browser to confirm "whether to allow this CloudBase login".

The value of this approach is:

  1. The terminal side is only responsible for initiating requests and polling for results, without requiring the ability to complete browser callbacks.
  2. 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.
  3. 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:

InterfaceMethodFunction
/auth/device/codePOSTTerminal requests device code, obtains device_code, user_code, verification_uri
/auth/device/verifyPOSTBrowser side confirms authorization, updates device code status from pending to authorized
/auth/tokenPOSTResponsible for first credential exchange, credential refresh, and session revocation

Among them, /auth/token distinguishes 3 actions through grant_type:

grant_typeFunction
urn:ietf:params:oauth:grant-type:device_codeUse device_code to exchange for credentials for the first time
refresh_tokenUse refreshToken to refresh temporary credentials, and rotate a new refreshToken
revoke_tokenRevoke 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:

  1. Verify that the current user has completed enterprise identity authentication.
  2. Receive user_code.
  3. Find the corresponding device_code record.
  4. Update the authorization status from pending to authorized.
  5. 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:

FieldDescription
refreshTokenLong-term token; if auto-renewal is implemented, a non-empty value must be returned
expiredExpiration timestamp (milliseconds) of refreshToken
tmpSecretIdTencent Cloud temporary key SecretId
tmpSecretKeyTencent Cloud temporary key SecretKey
tmpTokenTencent Cloud temporary security token
tmpExpiredTemporary key expiration timestamp (milliseconds)
uinCurrent logged-in user identifier
tokenIdSession or token ID
envIdsOptional
envListOptional
envBillingInfoListOptional

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:

FieldTypeDescription
EnvIdstringEnvironment ID
AliasstringEnvironment alias
StatusstringEnvironment status
SourcestringEnvironment source, such as Mini Program or Tencent Cloud
CreateTimestringCreation time
UpdateTimestringLast update time
PackageIdstringPackage ID
PackageNamestringPackage name
PayModestringPayment method
IsDefaultbooleanWhether it is the default environment
RegionstringEnvironment region

envBillingInfoList:

FieldTypeDescription
EnvIdstringEnvironment ID
PackageIdstringPackage ID
IsAutoRenewbooleanWhether auto-renewal is enabled
StatusstringBilling status
PayModestringBilling mode
IsolatedTimestringIsolation time
ExpireTimestringExpiration time
CreateTimestringFirst billing access time
UpdateTimestringLast update time
IsAlwaysFreebooleanWhether it has never been upgraded to paid version
PaymentChannelstringPayment channel
FreeQuotastringFree quota information
EnableOverrunbooleanWhether overflow pay-as-you-go is enabled
ExtPackageTypestringEnvironment 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:

  1. DescribeEnvs: https://cloud.tencent.com/document/product/876/34820
  2. DescribeBillingInfo: 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:

  1. Verify the current refresh token.
  2. Re-issue temporary credentials.
  3. Rotate a new refreshToken.
  4. 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.

Error CodeTypical Scenario
authorization_pendingUser has not confirmed authorization in the browser
slow_downClient polling is too frequent
expired_tokendevice_code has expired
invalid_clientclient_id is missing, invalid, or does not match
invalid_grantdevice_code, refresh_token, or authorization status is abnormal
unsupported_grant_typeUnsupported grant_type
already_consumedDevice code has already been used successfully
server_errorServer failed to issue temporary credentials