Skip to main content

Device Authorization Flow

OAuth 2.0 Device Authorization Grant (RFC 8628) for input-constrained devices like CLI tools, smart displays, and IoT devices.

Device Flow Overview

  1. Device requests codes via POST /oauth/device_token — receives a device_code and user_code
  2. Device displays the user_code and verification_uri to the user
  3. User visits the verification URI in a browser and enters the user code
  4. Server validates code via POST /oauth/device_user_code and shows the client details
  5. User authorizes via POST /oauth/authorize_device
  6. Device polls via POST /oauth/device_access_token until authorization is granted
  7. Server issues tokens — access token (and optionally refresh token)

POST /api/oauth/device_token

Initiate a device authorization request. Returns codes for the user to enter in a browser.

Authentication: Required

Payload:

{
"client_id": "a6bd8f0f72b2c3275ff6",
"scope": "read:dataset write:dataset"
}
FieldTypeRequiredDescription
client_idstringYesOAuth client ID
scopestringNoSpace-separated list of requested scopes

Response:

{
"device_code": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
"user_code": "BKFT-DNLZ",
"interval": 5,
"expires_in": 1800,
"verification_uri": "https://informer.example.com/oauth/device",
"verification_uri_complete": "https://informer.example.com/oauth/device?code=BKFT-DNLZ"
}
FieldDescription
device_code16-byte hex token for the device to use when polling
user_codeHuman-readable code (8 uppercase consonants in XXXX-XXXX format)
intervalMinimum seconds between polling requests
expires_inCode lifetime in seconds (1800 = 30 minutes)
verification_uriURL the user should visit to enter the code
verification_uri_completeURL with the user code pre-filled

POST /api/oauth/device_user_code

Validate a user code entered in the browser. Returns the associated client details so the user can confirm authorization.

Authentication: Required

Payload:

{
"user_code": "BKFT-DNLZ"
}
FieldTypeRequiredDescription
user_codestringYesUser code in XXXX-XXXX format

Response:

{
"device_code": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
"user_code": "BKFT-DNLZ",
"client_id": "a6bd8f0f72b2c3275ff6",
"scope": "read:dataset write:dataset",
"app": {
"id": "client-uuid-123",
"name": "Informer CLI",
"description": "Command-line interface for Informer",
"url": null,
"client_id": "a6bd8f0f72b2c3275ff6",
"pkce": true,
"enableRefreshTokens": true
}
}
One-Time Use

The user code is deleted after validation. If the user enters the code again, it will return an error.

Error Responses:

  • 404 Not Found - User code is invalid or expired

POST /api/oauth/authorize_device

Authorize or deny a device authorization request. Called by the user in their browser after reviewing the client details.

Authentication: Required

Payload:

{
"device_code": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
"authorize": true
}
FieldTypeRequiredDescription
device_codestringYesDevice code from the initial request
authorizebooleanNoWhether to authorize the device

Response:

{
"authorized": true
}

POST /api/oauth/device_access_token

Poll for the access token after the user has been prompted to authorize. The device should call this endpoint at the interval specified in the initial response.

Authentication: Required

Payload:

{
"device_code": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6"
}
FieldTypeRequiredDescription
device_codestringYesDevice code from the initial request

Success Response (after user authorizes):

{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "bearer",
"scope": "read:dataset write:dataset",
"refresh_token": "eyJhbGciOiJIUzI1NiIs...",
"expires_in": 900
}

Pending Response (user hasn't authorized yet):

{
"error": "authorization_pending"
}

Error Responses:

ErrorHTTP StatusDescription
authorization_pending400User hasn't authorized yet — keep polling
access_denied400User explicitly denied authorization
expired_token400Device code has expired — restart the flow
Polling Best Practices
  • Respect the interval value (default: 5 seconds) between polls
  • Stop polling after receiving expired_token or access_denied
  • On authorization_pending, wait and retry