OAuth Hacking: The Complete Guide to OAuth and OIDC Attacks
OAuth Device Flow Abuse
How the OAuth device authorization grant is phished: trick the victim into approving the attacker's user code, then poll the token endpoint for their token.
Published
The device authorization grant lets an input-constrained device get authorized by having the user approve a short code elsewhere. That separation is convenient and phishable: an attacker can get the victim to approve the attacker's code on the real provider page. This page covers the abuse. Practice on a free live target.
How the device grant works
A device with no good input method starts the flow by asking the authorization server for a code pair, then displays a short user_code and a verification_uri for the user to visit on another device:
POST /device_authorization HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded
client_id=tvapp&scope=openid%20emailHTTP/1.1 200 OK
Content-Type: application/json
{"device_code":"GmRh...","user_code":"WDJB-MJHT","verification_uri":"https://auth.example.com/device","expires_in":900,"interval":5}The user visits verification_uri, enters WDJB-MJHT, and approves. Meanwhile the device polls the token endpoint with its device_code until approval happens.
Step 1: start the flow as the attacker
The attacker calls device_authorization themselves and gets a user_code and device_code. The user_code is the bait. The device_code is what the attacker will redeem.
Step 2: phish the victim into approving
The attacker sends the victim the real provider verification URL and the attacker's user_code, framed as a sign-in to complete:
"Confirm your account: go to https://auth.example.com/device and enter code WDJB-MJHT"Because the link is the genuine provider page over HTTPS, the usual phishing tells are absent. The victim enters the code and approves, authorizing the attacker's device against the victim's account.
Step 3: poll for the victim's token
The attacker has been polling the token endpoint with the device_code the whole time:
POST /token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=GmRh...&client_id=tvappBefore approval the server returns authorization_pending. Once the victim approves, it returns the token:
HTTP/1.1 200 OK
Content-Type: application/json
{"access_token":"2YotnFZF...","token_type":"Bearer","id_token":"eyJhbGci..."}The attacker now holds a token for the victim's account.
Edge variants
authorization_pending the normal pre-approval poll response; keep polling at the interval
slow_down increase the polling interval by 5 seconds (RFC 8628)
expired_token the user_code expired before approval; restart the flow
QR-code lure present the verification_uri + code as a QR to lower the victim's guardWhy UX alone cannot protect it
The protection ultimately rests on the victim noticing an unexpected client name on the approval screen, which is weak. The real mitigations are structural:
Fixing it
- Short code lifetime and polling limits, so the attacker's window is small.
- Show the requesting client clearly and warn the user to only approve devices they personally started.
- Bind the approval context where possible, and consider device flow only for genuinely input-constrained clients.
Full guidance is in preventing OAuth attacks. For every payload in one place, see the cheat sheet, or try the device flow on a free lab.
← Back to OAuth Hacking: The Complete Guide to OAuth and OIDC Attacks