Device flow
According to RFC-8628, the "device authorization grant is designed for Internet-connected devices that either lack a browser to perform a user-agent-based authorization or are input constrained to the extent that requiring the user to input text in order to authenticate during the authorization flow is impractical. It enables OAuth clients on such devices (like smart TVs, media consoles, digital picture frames, and printers) to obtain user authorization to access protected resources by using a user agent on a separate device."
How does this work?
For example, if you are building an application for a device, such as a fridge, which does not have access to a web browser, the application has to retrieve some information for the user's shopping list. To be able to do that, the application needs an access token. A step-by-step flow can be seen below:
- The user buys a smart fridge.
- The user already created an online account on the fridge customer application, where they can create shopping lists.
- The user plugs in the fridge and selects the setting from the fridge's control panel to pair the device.
- The fridge displays a message that states something like For pairing your device, go to http://www.onewelcome.com/device/user and type this code: HDcbjFDz.
- The user navigates to the suggested URL, enters the code, and if not logged in already, is asked to log in.
- When the user is logged in, a message indicates that the device was successfully paired.
Which API do you need?
For implementing the functionality described above, you have to use the following oauth2 APIs:
The flow starts when the browser-less device initiates the flow by sending the following request:
curl -k -H 'Cache-Control: no-cache' -H "Content-Type: application/x-www-form-urlencoded" -d "response_type=id_token&scope=openid+phone+email&client_id=oauth2fridge&nonce=qweqd23sd-3edssad-3dsadas-adsa" "https://www.onewelcome.com/onewelcome-dev/auth/oauth2.0/v1/device/code"
The API responds with:
{
"user_code":"HDcbjFDz",
"device_code":"ce3df1d4-8769-4a3b-bca8-b546fa95fcef",
"verification_url":"http://www.onewelcome.com/onewelcome-dev/auth/oauth2.0/v1/device/user",
"expires_in":300,
"interval":5
}
The response of the API is shown to the user on the device. In the next step, the user navigates to the indicated URL, enters the code, and authenticates. When the user is authenticated, the following API will be called:
curl -k -H 'Cache-Control: no-cache' -H 'Content-Type: application/x-www-form-urlencoded' -H "Cookie: iwdev=AQIC5wM2LY4SfczbU9fRgr9oIMjGm4DU-1Xltj1sDtutltE.*AAJTSQACMDIAAlNLABMzNTk1OTk5MDI2NDY3MzMwMzg4AAJTMQACMDE.*" -d 'scope=email openid phone&nonce=qweqd23sd-3edssad-3dsadas-adsa&response_type=id_token&client_id=oauth2fridge&decision=allow&user_code=HDcbjFDz' https://www.onewelcome.com/onewelcome-dev/auth/oauth2.0/v1/device/user -v
In the meantime, until the user enters the code, the browser-less device will continuously poll for an access token using the device_code
obtained from the first request.
Until the user enters the code, the API will respond with:
{
"error":"authorization_pending",
"error_description":"The user has not yet completed authorization"
}
If the application polls too fast, not respecting the interval
property specified in the response of the first request, the authorization server will return a 400 Bad Request
with the response body as the one below:
{
"error": "slow_down",
"error_description": "The polling interval has not elapsed since the last request"
}
After the user successfully enters the code, an access token along with an id_token
(for this example) will be returned to the device and the response will look like below:
{
"access_token":"54899b54-ef16-431c-82e5-623cf552f100",
"refresh_token":"d3b0f940-652d-477c-9238-2bd24c33ae35",
"scope":"phone email openid",
"id_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6IjM3TG1KRmk1aWNoa0RLZG81MlE4Rlc4TDFkMD0ifQ.eyJzdWIiOiJhMjZmNjc0ZS04YTg4LTQwZjgtYTZkZC1hMWE0YmJiN2M2ZGQiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImlzcyI6Imh0dHBzOi8vd3d3Lml3ZWxjb21lLmNvbS9hdXRoL29hdXRoMi4wIiwidG9rZW5OYW1lIjoiaWRfdG9rZW4iLCJwaG9uZV9udW1iZXJfdmVyaWZpZWQiOmZhbHNlLCJub25jZSI6ImFld3FlcWVld3F3ZXEiLCJhdWQiOiJvYXV0aDJmcmlkZ2UiLCJhenAiOiJvYXV0aDJmcmlkZ2UiLCJhdXRoX3RpbWUiOjE2MTg1NjgzNzAsInBob25lX251bWJlciI6IjAxMzcxMjM0NTY3ODkwYCIsImV4cCI6MTYxODU3MTk3NiwidG9rZW5UeXBlIjoiSldUVG9rZW4iLCJpYXQiOjE2MTg1NjgzNzYsImVtYWlsIjoieHl6QHlvcG1haWwuY29tIiwic2Vzc2lvbi1pZCI6ImU1NzYyN2U4LWExM2EtNDUzOC1hMWFhLTBjZTBiZGEyNjAwOSJ9.qg9NmyUohf9wZ3sQHJTm4WSBvctlaZcxEajMzF5tb6s",
"token_type":"Bearer",
"expires_in":3599
}
The id_token
could be used by the device to get the informations about the authenticated user to display some user-friendly messages.