Beta

Create a tenant

A new tenant starts with its own users, OAuth settings, audit history and logs. You are its first Tenant Admin.

BTL Admin

Device authorization

All domains, codes, and tokens in these examples are fictional.

You have bought a digital photo frame for your living room. It has a screen and a single button, and you would like it to show photos from your photo account.

The authorization code flow does not fit well here. The frame has no convenient browser, and even if it had one, typing an email address and password with a single button would be miserable. Asking you to type your password into the frame would bring back the problem OAuth was meant to solve.

The device authorization grant splits the work between two devices. The frame asks for access, and you approve it on a device that is easier to use, such as your phone.

Starting on the device

The frame is a public client. Every frame of this model runs the same software, so a secret built into it could be extracted from any one of them. It identifies itself with a client ID and sends a request to the photo service's device authorization endpoint:

POST /device_authorization HTTP/1.1
Host: auth.photos.example
Content-Type: application/x-www-form-urlencoded

client_id=living-room-frame
&scope=photos.read

The response gives the frame two codes for two different audiences:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store

{
  "device_code": "demo-device-code-4",
  "user_code": "WDJB-MJHT",
  "verification_uri": "https://photos.example/device",
  "verification_uri_complete": "https://photos.example/device?user_code=WDJB-MJHT",
  "expires_in": 900,
  "interval": 5
}

The user_code is meant for you. It is short and easy to read and type. The device_code stays with the frame, which will use it to collect the result. The frame never shows it on screen.

The frame displays the verification address and the user code. It might also show a QR code built from verification_uri_complete, so you can scan it with your phone instead of typing. Both codes stop working after fifteen minutes in this example.

Approving on another device

On your phone, you open photos.example/device. The photo service asks you to sign in if you are not already signed in, then asks for the code shown on the frame. You type WDJB-MJHT.

The service now knows which pending request you mean. It shows you what is asking and what it wants: Living room frame would like to view your photos. You approve.

Notice where each part happened. You signed in and made your decision on the photo service, in your phone's browser. The frame never saw your password, and your phone never needed to know anything about the frame except the code you read from its screen.

Polling for the result

While you were busy with your phone, the frame could not wait for a redirect. Nothing sends the frame a message when you approve. Instead, it asks the token endpoint at intervals:

POST /token HTTP/1.1
Host: auth.photos.example
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code
&device_code=demo-device-code-4
&client_id=living-room-frame

The grant type is a full URN rather than a short word. That is how extension grants are named, and the device authorization grant was added to OAuth after the original specification.

Until you finish, the token endpoint answers with an error that means "not yet":

HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-store

{
  "error": "authorization_pending"
}

The frame waits at least the number of seconds given by interval before asking again. If it asks too quickly, the server replies with slow_down, and the frame adds five seconds to its interval for the rest of the attempt. Once you approve, the next poll returns an access token in the same shape as any other token response.

Two other answers end the attempt. access_denied means the request was refused, and expired_token means the codes ran out before anyone finished. In either case the frame stops polling and offers to start again with new codes.

Three stages: the photo frame receives two codes, displays the user code and verification address, and keeps the device code private. The frame polls and receives authorization_pending while the person signs in on a phone. After approval, the next poll returns the access token to the frame.
The frame starts the request and polls for the result. You sign in and approve on your phone, using the short code shown on the frame. View full-size illustration (opens in a new tab)

A code someone else started

The user code connects your approval to one pending request. That is also what makes it attractive to an attacker.

Suppose someone starts a device authorization request from their own device, then sends you a message: "Your photo account needs verifying. Go to photos.example/device and enter WDJB-MJHT." The page is genuine, and the sign-in is genuine. If you enter the code and approve, the attacker's device receives access to your photos.

Nothing in the protocol can tell whether the person approving is standing in front of the device that asked. The defenses come from the approval screen and from people's habits. The service names the client that is asking and what it wants, so you have a chance to notice that you are not setting up a photo frame. The codes expire quickly, which limits how long an invitation like that stays useful. And a code only makes sense when you are looking at it on your own device's screen. A code that arrives in an email or a message from someone else should be treated with suspicion.

The short user code creates one more risk. Someone could try guessing codes on the verification page, hoping to land on a pending request. The service limits how many attempts it accepts and makes codes long enough, compared with the number of requests pending at once, that guessing is impractical.

Use this grant for devices that cannot reasonably show a browser or accept typed input, such as televisions, frames, and some command-line tools. An application that can open a browser on the same device should use the authorization code flow, where the approval and the result stay together in one place.

Try it in the Lab

PUT IT INTO PRACTICE

Check your understanding

Try these questions before moving on. If an answer isn't right, use the feedback and try again.

0 of 2 answered correctly

Enable JavaScript to answer these questions and save progress in this browser.

QUESTION 1 OF 2The frame polls the token endpoint and receives authorization_pending. What should it do?

QUESTION 2 OF 2You receive a message asking you to enter a code at the photo service's genuine device page. You are not setting up any device. What is the risk?

We value your privacy

We use cookies and similar technologies to enhance your browsing experience, and analytics to understand our traffic. By clicking "Allow All", you consent to optional analytics. Cookie Policy

Learn identity