Device flow
Acording to RFC-8628device 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?
Let's assume you are building an application for a device, such as a fridge, which does not have access to a web browser and the application has to retrieve some information for the user's shopping list. In order to be able to do that, the application needs an access token. A step by step flow can be seen below:
- User buys a smart fridge, and plugs it in at home
- User already created an online account on the fridge customer application, where he can create shopping lists
- User plugs in the fridge and selects from the fridge's control panel Pair device
- Fridge displays a message which states something like this: For pairing your device, please go to http://www.onewelcome.com/device/user and type this code: HDcbjFDz
- User navigates to the suggested url, enters the code, and if not logged in already, is asked to login
- Once the user is logged in, a message will indicate that the device was successfully paired
What 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"
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 will be nicely shown to the user on the device, and in the next step the user will navigate to the indicated url and enter the code, and authenticate if not already. Upon this action, 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 to fast, i.e. not respecting the interval
property specified on 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.