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.