Skip to main content

Device Authorization Grant

RFC 8628

Client type: Input-constrained devices: Smart TVs, game consoles, CLI tools, IoT devices that cannot open a browser

The Device Authorization Grant (RFC 8628) lets devices with no browser or limited input (TV, CLI, IoT sensor) authorize by displaying a short code and URL. The user enters the code on another device (phone/computer). The device polls the authorization server until the user completes authorization. Used by YouTube on TV, Spotify on TV, GitHub CLI, AWS CLI.

How it works

The Device Flow solves the problem of authorizing a device that cannot open a browser or accept text input conveniently.

Flow: 1. Device POSTs client_id to /device_authorization 2. Server returns device_code, user_code, verification_uri, expires_in, interval 3. Device displays: 'Visit example.com/activate and enter code: ABCD-1234' 4. User visits the URL on their phone/computer and enters the code 5. Meanwhile, device polls /token every {interval} seconds with device_code 6. Authorization server returns 'authorization_pending' until user completes 7. Once user authorizes, next poll returns access_token and refresh_token

Polling: device must respect the interval (typically 5 seconds). Polling faster results in 'slow_down' error; device must then increase interval by 5 seconds.

User code format: short, human-typable, case-insensitive. Typically 8 characters in format XXXX-XXXX. Designed to be read from a TV screen at distance and typed on a phone.

Expiry: device_code and user_code expire after expires_in seconds (typically 1800 seconds / 30 minutes). If expired, device must restart the flow.

Error codes during polling: authorization_pending – user hasn't authorized yet, keep polling slow_down – polling too fast, increase interval by 5s access_denied – user denied, stop polling expired_token – device_code expired, restart flow

Flow Steps

  1. 1

    Device POSTs client_id to /device_authorization endpoint

  2. 2

    Server returns device_code, user_code (e.g., ABCD-1234), verification_uri, expires_in, interval

  3. 3

    Device displays: 'Go to example.com/activate and enter: ABCD-1234'

  4. 4

    User visits URL on phone/computer, enters code, authenticates and grants permission

  5. 5

    Device polls /token every {interval} seconds with grant_type=urn:ietf:params:oauth:grant-type:device_code

  6. 6

    On success, server returns access_token and refresh_token

Parameters

ParameterRequiredDescription
grant_typeYesurn:ietf:params:oauth:grant-type:device_code
client_idYesDevice application identifier
device_codeYesdevice_code returned from /device_authorization request

Examples

Device Flow – initial request and polling
# Step 1: Request device code
POST https://auth.example.com/device_authorization
Content-Type: application/x-www-form-urlencoded
client_id=tv_app&scope=read:library

# Response:
{
  "device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS",
  "user_code": "WDJB-MJHT",
  "verification_uri": "https://example.com/device",
  "verification_uri_complete": "https://example.com/device?user_code=WDJB-MJHT",
  "expires_in": 1800,
  "interval": 5
}

# Step 2: Display to user – poll every 5s
while (true) {
  const res = await fetch('/oauth/token', {
    method: 'POST',
    body: 'grant_type=urn:ietf:params:oauth:grant-type:device_code' +
          '&client_id=tv_app&device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS'
  });
  const data = await res.json();
  if (data.access_token) break;       // done
  if (data.error === 'slow_down') interval += 5;
  if (data.error === 'access_denied') throw new Error('User denied');
  await sleep(interval * 1000);
}

When to use

Smart TVs, game consoles, CLI tools (GitHub CLI, AWS CLI, gcloud), Raspberry Pi/IoT devices, any device where opening a browser is impractical.

See Also