diagram.mmd — sequence
Device Login Flow sequence diagram

The Device Login Flow (formally the OAuth2 Device Authorization Grant, RFC 8628) is designed for input-constrained devices that cannot easily display a full browser or accept keyboard input — smart TVs, game consoles, CLI tools, IoT devices, and media players.

The problem these devices face is that the standard OAuth2 Authorization Code Flow requires a browser to handle redirects. A CLI tool or a TV app cannot intercept a redirect URI the same way a web app can. The Device Authorization Grant solves this by splitting authentication across two devices: the constrained device (e.g., the TV) and a secondary device the user already trusts (their phone or laptop).

The flow begins with the constrained device making a POST to the authorization server's /device/code endpoint with its client_id and requested scope. The server responds with three values: a device_code (used by the device to poll), a user_code (a short, human-readable code like WDJB-MJHT), and a verification_uri (e.g., https://provider.com/activate). The device displays the user_code and verification_uri on screen and begins polling the /token endpoint every few seconds.

On their phone or laptop, the user navigates to the verification_uri, enters the user_code, logs in, and approves the access request. Back on the constrained device, one of the next polling attempts returns a successful response with access and refresh tokens. The device stores the tokens and is now authenticated — with no keyboard entry of passwords required.

This flow is the basis for "Sign in on your TV" experiences from YouTube, Netflix, and GitHub's gh auth login CLI command. Token management after this point follows the same patterns as other OAuth2 flows — see Refresh Token Rotation.

Free online editor
Edit this diagram in Graphlet
Fork, modify, and export to SVG or PNG. No sign-up required.
Open in Graphlet →

Frequently asked questions

The OAuth2 Device Authorization Grant (RFC 8628) is a grant type designed for input-constrained devices — smart TVs, game consoles, CLI tools, and IoT devices — that cannot easily open a browser or accept keyboard input. It splits authentication across two devices: the constrained device displays a short code, and the user completes login on a trusted secondary device (phone or laptop).
The device POSTs its `client_id` and `scope` to the authorization server's `/device/code` endpoint. The server returns a `device_code`, a short `user_code`, and a `verification_uri`. The device displays the `user_code` and URL, then begins polling the `/token` endpoint every few seconds. The user navigates to the URL on their phone, enters the code, authenticates, and approves access. The device's next poll returns access and refresh tokens.
The device polls the `/token` endpoint at the interval specified in the `interval` field of the device authorization response (typically 5 seconds). It must handle three response states: `authorization_pending` (user has not yet completed login — keep polling), `slow_down` (increase polling interval by 5 seconds), and `expired_token` (the `device_code` has expired — restart the flow). Polling too aggressively may result in rate limiting.
The `user_code` must be displayed clearly and the `verification_uri` should be short and easy to type. The `device_code` and `user_code` should expire quickly (typically 5–15 minutes) to limit the phishing window where an attacker could display a code to trick a user into authorising a malicious device. The authorization server should warn users about what device is requesting access before they approve.
mermaid
sequenceDiagram participant Device as Constrained Device (TV/CLI) participant AuthServer as Authorization Server participant User participant Browser as User Browser / Phone Device->>AuthServer: POST /device/code with client_id + scope AuthServer-->>Device: device_code, user_code, verification_uri, interval Device-->>User: Display: Go to https://example.com/activate\nEnter code WDJB-MJHT loop Poll every 5 seconds Device->>AuthServer: POST /token with device_code (polling) AuthServer-->>Device: authorization_pending - keep polling end User->>Browser: Navigate to verification_uri Browser->>AuthServer: GET /activate AuthServer-->>Browser: Show user code entry form User->>Browser: Enter user_code WDJB-MJHT Browser->>AuthServer: POST user_code AuthServer-->>Browser: Show login form User->>Browser: Authenticate and approve scopes Browser->>AuthServer: Submit approval AuthServer-->>Browser: Authorization complete Device->>AuthServer: POST /token with device_code (next poll) AuthServer-->>Device: Access token + refresh token Device-->>User: Authentication successful
Copied to clipboard