Input-constrained devices and service chains need flows beyond the redirect-based one.
Device authorization grant (RFC 8628) serves devices without a usable browser or keyboard: smart TVs, CLIs, IoT devices.
- The device POSTs to the device authorization endpoint and gets a
device_code, a shortuser_code, averification_uri(often alsoverification_uri_completefor QR codes) and a pollinginterval. - It shows "Visit example.com/device and enter WDJB-MJHT".
- The user completes login and consent on their phone or laptop.
- Meanwhile the device polls the token endpoint with
grant_type=urn:ietf:params:oauth:grant-type:device_code, receivingauthorization_pendinguntil the user finishes, andslow_downif it polls too fast.
gh auth login, az login --use-device-code and many streaming apps use it. It is phishable (attackers can send victims a code to approve), so show the client name clearly on the approval screen and keep codes short-lived.
Token exchange (RFC 8693) lets a service trade one token for another: grant_type=urn:ietf:params:oauth:grant-type:token-exchange with a subject_token. Uses include:
- Down-scoping a user's token for a specific downstream API (new
audience), instead of forwarding the original broad token. - Delegation chains where the new token records the acting service in an
actclaim. - Workload identity federation: exchanging a Kubernetes or GitHub Actions OIDC token for a cloud access token.
Example
# 1. Device asks for codes
curl -s https://auth.example.com/oauth/device/code \
-d client_id=tv-app -d scope="openid profile"
# {"device_code":"GmRhm...","user_code":"WDJB-MJHT",
# "verification_uri":"https://example.com/device","expires_in":900,"interval":5}
# 2. Poll every `interval` seconds until the user approves
curl -s https://auth.example.com/oauth/token \
-d grant_type=urn:ietf:params:oauth:grant-type:device_code \
-d device_code=GmRhm... -d client_id=tv-app
# {"error":"authorization_pending"} ...later... {"access_token":"...", ...}
# Token exchange: get a narrower token for a downstream API
curl -s https://auth.example.com/oauth/token -u "orders-api:$SECRET" \
-d grant_type=urn:ietf:params:oauth:grant-type:token-exchange \
-d subject_token="$USER_ACCESS_TOKEN" \
-d subject_token_type=urn:ietf:params:oauth:token-type:access_token \
-d audience=https://inventory.example.comRemember
- Device flow: show a user code, the user approves elsewhere, the device polls
- Honour
intervalandslow_downwhen polling - Token exchange swaps a token for one with a narrower audience or delegation
Watch out for
- Forwarding a user's broad access token to every downstream service instead of exchanging it.