Skip to content

Device code flow

The way clients obtain a bearer token. It needs no client registration, no redirect URI and no client secret, which makes it suitable for CLIs, CI runners and scripts as well as applications.

1. Request a device code

curl -X POST https://api.taigacloud.com/v2/oauth2/device/code \
  -H "Content-Type: application/json" \
  -d '{"device_name": "my-ci-runner"}'

device_name is how the token will be identified later when you review or revoke it, and must be between 5 and 100 characters.

{
  "device_code": "…",
  "user_code": "A1B2C3D4E5F6",
  "verification_uri": "https://api.taigacloud.com/oauth2/device/verify?user_code=A1B2C3D4E5F6",
  "expires_in": 600,
  "interval": 5
}

2. Approve it

Open verification_uri in a browser and sign in. The link already carries the user_code, so there is nothing to type — print it and let the person running your tool click it.

You have expires_in seconds (10 minutes) to complete this before the device code lapses and you have to start again.

3. Poll for the token

curl -X POST https://api.taigacloud.com/v2/oauth2/device/token \
  -H "Content-Type: application/json" \
  -d '{"grant_type": "device_code", "device_code": "…"}'

Poll no faster than interval seconds. Until the approval happens you get:

Status Meaning What to do
428 Authorization pending Keep polling at interval.
400 Invalid or expired device code Start again from step 1.

Once approved it returns both tokens:

{
  "access_token": { "token": "…", "token_type": "bearer", "expires_in": 3600 },
  "refresh_token": { "token": "…", "token_type": "bearer", "expires_in": 604800 }
}

The token is nested

Each credential is an object, and the value you send in the Authorization header is access_token.token — not access_token. This differs from the flat shape some OAuth libraries expect, so a generic device-flow client may need a small adapter.

Refreshing

Access tokens last an hour; refresh tokens last seven days. Exchange one for a new pair at the same endpoint:

curl -X POST https://api.taigacloud.com/v2/oauth2/device/token \
  -H "Content-Type: application/json" \
  -d '{"grant_type": "refresh_token", "refresh_token": "…"}'

Each refresh token is single use, and using one twice is treated as a compromise: the request fails with 401 Refresh token reuse detected. Store the new refresh token from every response and discard the old one — a client that retries a refresh with the token it already spent will lock itself out.

Managing issued tokens

Every device flow you complete registers a device against your account.

GET /v2/oauth2/registered_devices List devices holding tokens.
POST /v2/oauth2/registered_devices/{deviceUUID}/revoke Revoke one device's tokens.
DELETE /v2/oauth2/registered_devices/{deviceUUID} Remove a device.

Revoke anything you no longer recognise, and anything belonging to a machine you have decommissioned. This is also the remedy if a token leaks — see /reference for the full parameters.

Handling tokens

  • Treat both tokens as secrets. Anything holding one can act as you.
  • Never put a token in a URL, a log line, or a source file. Use an environment variable or a secret store.
  • Give each machine its own device registration, so one can be revoked without disturbing the others.