PE
Protocol Explorer
OAuth 2.0

OAuth 2.0 — Device Authorization Grant

The Device Authorization Grant (RFC 8628) solves authorization for input-constrained devices like CLIs, smart TVs, media boxes, and IoT sensors that cannot open a browser or receive redirects. The device obtains a user code and verification URI from the AS, displays them to the user, and polls for a token while the user authorizes on a separate device (phone or laptop).

RFC 8628
CLI / Smart TVAuthorization ServerUser's Phone / BrowserResource Server1POST /device_authorization2002POST /token (poll — pending)3GET /activate (user navigat…4POST /activate (authenticat…5POST /token (poll — success)6GET /api/profile
POST https://auth.example.com/device_authorization200

The device requests a device code from the AS's device authorization endpoint. The AS returns a device_code (for polling), a user_code (for the user to type), and a verification_uri (where the user goes on their separate device). No user interaction has occurred yet.

RFC 8628 §3.1: The device authorization endpoint is a separate endpoint from the token endpoint.

RFC 8628 §6.1: user_code entropy should resist brute-force for the duration of the code's lifetime (typically 15–30 minutes).

Public clients (no client_secret) are supported — the client_id alone is sufficient to initiate the flow.

The device_code and user_code are bound together on the AS — when the user approves via the user_code, the AS marks the corresponding device_code as authorized.

1 / 6
speed

Step 1: POST /device_authorization

Request / response
POSThttps://auth.example.com/device_authorization
Content-Type?

application/x-www-form-urlencoded

Body
client_id=s6BhdRkqt3&scope=read:profile+media:stream+playlists:write
Cryptographic Signature

Construction Steps

1. 1. device_code — the device's session identifier
device_code = "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS"

This is a high-entropy opaque value. The device sends it
on every polling request to identify which authorization session
it is waiting for. It MUST be kept confidential — never shown
to the user. Expires in 1800 seconds (30 minutes).
2. 2. user_code — short human-typeable code
user_code = "WDJB-MJHT"

RFC 8628 §6.1: The user_code SHOULD have high entropy but MUST
be short enough to type on a constrained device (TV remote,
game controller). The AS SHOULD display it in a way that is
easy to distinguish (hyphens, uppercase, no ambiguous chars
like 0/O or 1/l/I).

This code is what the user types on their phone/laptop. It
corresponds to the device_code on the AS side.
3. 3. verification_uri — where the user goes
verification_uri          = "https://auth.example.com/activate"
verification_uri_complete = "https://auth.example.com/activate?user_code=WDJB-MJHT"

The device SHOULD display both:
  • The short URI + user_code (for typing on TV)
  • A QR code encoding verification_uri_complete (for scanning)

verification_uri_complete pre-fills the user_code so the
user can skip the manual entry step.
4. 4. Polling parameters
expires_in = 1800  (seconds until device_code expires)
interval   = 5     (minimum seconds between polling attempts)

The device MUST NOT poll more frequently than once per
interval seconds. If it polls too fast the AS returns
error=slow_down and the device must increase its interval
by 5 seconds.

Signature Base String

client_id=s6BhdRkqt3&scope=read:profile+media:stream+playlists:write

Signing Key

No user interaction at this step — device initiates the flow

Signature Output

device_code (secret), user_code (short, human-typeable), verification_uri