Skip to content

Instantly share code, notes, and snippets.

@jaredpalmer
Last active September 1, 2021 09:35
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jaredpalmer/0da17c1351aac03df9d08ab024f8ec75 to your computer and use it in GitHub Desktop.
Save jaredpalmer/0da17c1351aac03df9d08ab024f8ec75 to your computer and use it in GitHub Desktop.
OAuth 2.0 Device Flow

OAuth Device Flow

This is flow used by apps on Apple TV / Roku. However, it is also useful for CLIs.

Here is my rundown. Please correct me in comments if something is wrong or if there is a better way to do this.


Device pings the server to begin activation process

POST https://authorization-server.com/device

client_id={CLIENT_ID}

The client_id is public. It may contain information about the device.

Server creates a token with a value and a short code, but does not actually associate it with a user. It then responds with activation information

{
  "device_code": "NGU4QWFiNjQ5YmQwNG3YTdmZMEyNzQ3YzQ1YSA",
  "verification_uri": "https://example.com/device",
  "user_code": "BDSD-HQMK",
  "expires_in": 1800,
  "interval": 5
}

Now the device needs to display the URL and User Code to the user somehow. While the device waits for the user to enter the code and log in, it will make a POST request every 5 seconds as specified by the interval returned. This POST request will be made to the token endpoint, using a grant type of device_code.

POST https://authorization-server.com/token

grant_type=urn:ietf:params:oauth:grant-type:device_code
&client_id=CLIENT_ID
&device_code=NGU4QWFiNjQ5YmQwNG3YTdmZMEyNzQ3YzQ1YSA

While that's happening, user goes to https://example.com/device in their browser (the verification_url).

The user will log in if they aren't already.

They enter the user_code into an input.

The application sends the user_code to https://authorization-server.com/activate authorized by the access_token that comes from the application's auth flow (likely in browser cookie or local storage).

POST https://authorization-server.com/activate

user_code=BDSD-HQMK
&access_token=XXXXXXXXXXXXXXX

The server now looks up both the user associated with the access_token and the token associated with user_code.

Optional: Confirm the device Server returns info about the original token and client id to the application. The application asks to the user to confirm the device (maybe it shows the user-agent from the device's original request or the name/version of the client). The user can then approve or deny the device.

(If approved) the server updates the original token so that it is now assigned to specifically to the user.

On the device's next request to https://authorization-server.com/token (recall that it has been polling this endpoint every 5 seconds), the token will now be assigned to a user.

POST https://authorization-server.com/token

grant_type=urn:ietf:params:oauth:grant-type:device_code
&client_id=CLIENT_ID
&device_code=NGU4QWFiNjQ5YmQwNG3YTdmZMEyNzQ3YzQ1YSA

In that request, the server generates a newer long-lived token for the device which is now assigned to the user and finally returns it.

{
  "access_token": "MsQ50jbzRn43NzqNLgV3Ia",
  "expires_in": 3600,
  "refresh_token": "b7aab34e37298a160e0ede5b43ed1f70a8"
}

The device stores the access_token and can now act on behalf of the user.


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment