Device authorization grant
The device authorization grant, formerly known as the device flow, is designed for client devices that have limited user interfaces, such as a set-top box, streaming radio, or a server process running on a headless operating system.
Rather than logging in by using the client device itself, you can authorize the client to access protected resources on your behalf by logging in with a different user agent, such as an Internet browser or smartphone, and entering a code displayed on the client device.
The device authorization grant flow
-
The client device requests a device code from Identity Cloud.
-
Identity Cloud returns a device code, a user code, a URL for entering the user code, and an interval, in seconds.
-
The client device provides instructions to the user to enter the user code. The client can choose an appropriate method to convey the instructions, for example, text instructions on screen, or a QR code.
-
The client device begins to continuously poll Identity Cloud to check if authorization has been completed.
-
If the user has not yet completed the authorization, Identity Cloud returns an HTTP 403 status code, with an
authorization_pending
message. -
The user follows the instructions from the client device to enter the user code by using a separate device.
-
If the user code is valid, Identity Cloud redirects the resource owner for authentication.
-
Upon authentication, the user is prompted to confirm the user code. The page is pre-populated with the one entered before.
-
The user can authorize the client device. The Identity Cloud consent page also displays the requested scopes, and their values.
Identity Cloud does not display the confirmation nor the consent pages if the user has a valid session when they entered the code, and the client is allowed to skip consent.
This is also true if you perform the call using REST and pass the
decision=allow
parameter. -
Upon authorization, Identity Cloud responds to the client device’s polling with an HTTP 200 status, and an access token, giving the client device access to the requested resources.
Demonstrate the device authorization grant flow
Follow these steps to demonstrate the OAuth 2.0 device grant flow:
Prepare the demonstration
Complete these steps to prepare the device authorization grant demonstration:
-
Create an application owner profile and record the username and password.
-
Register a client application.
-
In the Identity Cloud admin UI, go to Applications and select + Custom Application.
-
Select the sign-in method as OIDC - OpenId Connect and application type as Native / SPA.
-
Create the application, providing the following details:
- Name
-
myClient
- Owners
-
<application-owner>
- Client ID
-
myClient
-
Switch to the Sign On tab and under General Settings, set these fields to have the following values:
- Sign-in URLs
-
https://www.example.com:443/callback
- Scopes
-
write
- Grant Types
-
Device Code
-
Save your changes.
-
-
Create a resource owner profile and record the username and password.
Get a user code for the device
Devices can display a user code and instructions for a user, which can be used on a separate client to provide consent, allowing the device to access resources.
User codes consist of a random selection of a configurable set of characters.
By default, the user code is generated using eight of the following characters:
234567ABCDEFGHIJKLMNOPQRSTVWXYZabcdefghijkmnopqrstvwxyz
You can configure the list of possible characters to improve usability. For example,
remove similar characters such as The length of the user code is also configurable. For more information, refer to the device flow configuration. |
Perform the following steps to request a user code in the OAuth 2.0 device flow:
-
As the client, call the /oauth2/device/code endpoint, specifying at least the client ID,
myClient
.For information about client authentication methods, refer to Client application authentication.
For example:
$ curl \ --request POST \ --data "client_id=myClient" \ --data "scope=write" \ "https://<tenant-env-fqdn>/am/oauth2/realms/root/realms/alpha/device/code" { "interval": 5, "device_code": "7a95a0a4-6f13-42e3-ac3e-d3d159c94c55...", "verification_uri": "https://<tenant-env-fqdn>/am/oauth2/realms/root/realms/alpha/device/user", "verification_url": "https://<tenant-env-fqdn>/am/oauth2/realms/root/realms/alpha/device/user", "verification_uri_complete": "https://<tenant-env-fqdn>/am/oauth2/realms/root/realms/alpha/device/user?user_code=VAL12e0v", "user_code": "VAL12e0v", "expires_in": 300 }
On success, Identity Cloud returns a user code, a
verification_uri
, and averification_uri_complete
value comprising the user code appended to the URI, which can be used to create QR codes.The
verification_url
output is included to support earlier versions of the specification.Identity Cloud also returns an
interval
, in seconds, that the client device must wait for in between requests for an access token.In the Access Management console, go to Realms > Realm Name > Services > OAuth2 Provider > Device Flow to configure the returned values.
-
The client device should now provide instructions to the user to enter the user code and grant access to the OAuth 2.0 device.
The client can choose an appropriate method to convey the instructions, for example, text instructions on screen, or a QR code. Perform the steps in one of the following procedures:
-
To grant access to the client using a browser, refer to Grant consent using a browser.
-
To grant access to the client without using a browser, refer to Grant consent using REST.
-
-
The client device should also begin polling the authorization server for the access token using the interval and device code information obtained in the previous step.
For more information, refer to Poll for authorization.
Grant consent using REST
The OAuth 2.0 device flow requires the user to grant consent to allow the client device to access the resources. The authorization server would then provide the client with an access token.
To grant consent with a user code without using a browser, perform the following steps:
-
The resource owner logs in to the authorization server.
For example:
$ curl \ -i \ --request POST \ --header "Content-Type: application/json" \ --header "X-OpenAM-Username: <resource-owner-username>" \ --header "X-OpenAM-Password: <resource-owner-password>" \ --header "Accept-API-Version: resource=2.0, protocol=1.0" \ 'https://<tenant-env-fqdn>/am/json/realms/root/realms/alpha/authenticate' {"tokenId":"<tokenId>","successUrl":"/enduser/?realm=/alpha","realm":"/alpha"}
-
As the client, call the /oauth2/device/user endpoint. Provide the resource owner’s SSO token in a cookie, and at least the following parameters:
-
user_code
=<resource-owner-user-code> -
decision
=allow
-
csrf
=<tokenId>
For example:
$ curl \ --request POST \ --header "Cookie: <session-cookie-name>=<tokenId>" \ --data "user_code=VAL12e0v" \ --data "decision=allow" \ --data "csrf=<tokenId>" \ "https://<tenant-env-fqdn>/am/oauth2/realms/root/realms/alpha/device/user"
The
scope
and theclient_id
parameters are not required because the user code already contains that information.Identity Cloud returns HTML containing a JavaScript fragment named
pageData
, with details of the result.Successfully allowing or denying access returns:
pageData = { locale: "en_US", baseUrl : "https://<tenant-env-fqdn>/am/XUI/", realm : "/alpha", done: true }
done: true
means that the flow can now continue.If the supplied user code has already been used or is incorrect, Identity Cloud returns the following:
pageData = { locale: "en_US", errorCode: "not_found", realm : "/alpha", baseUrl : "https://<tenant-env-fqdn>/am/XUI/" oauth2Data: { csrf: "ErFIk8pMraJ1rvKbloTgpp6b7GZ57kyk9HaIiKMVK3g=", userCode: "VAL12e0v", } }
As per Section 4.1.1 of the OAuth 2.0 authorization framework, it is required that the authorization server legitimately obtains an authorization decision from the resource owner.
Any client using the endpoints to register consent is responsible for ensuring this requirement, Identity Cloud cannot assert that consent was given in these cases.
-
Grant consent using a browser
The OAuth 2.0 device flow requires that the user grants consent to allow the client device to access the resources.
The authorization server would then provide the client with an access token.
To grant consent with a user code using a browser, perform the following steps:
-
The resource owner navigates to the verification URL acquired with the user code. For example:
https://<tenant-env-fqdn>/am/oauth2/realms/root/realms/alpha/device/user
-
The resource owner logs in to the authorization server.
-
The resource owner enters their user code:
Figure 2. OAuth 2.0 User CodeThe
verification_uri_complete
property in the response appends the user code as a query parameter.Identity Cloud prefills the form with the user code value if provided in the
user_code
query parameter. -
The resource owner authorizes the device flow client by allowing the requested scopes:
Figure 3. OAuth 2.0 Consent PageBy default, client applications use implied consent. Identity Cloud does not display the screen to the user.
-
Identity Cloud adds the OAuth 2.0 client to the user’s profile page in the Authorized Apps section and displays that the user is done with the flow:
Figure 4. OAuth 2.0 Done PageThe device that is polling the authorization server (Identity Cloud) can now obtain an access token.
Poll for authorization
The client device must poll the authorization server for an access token, since it cannot know whether the resource owner has already given consent or not.
Perform the following steps to poll for an access token:
-
On the client device, create a POST request to poll the
/oauth2/access_token
endpoint to request an access token specifying, at least, the following parameters:-
client_id
=<your-client-id> -
grant_type
=urn:ietf:params:oauth:grant-type:device_code
-
device_code
=<your-device-code>
For information about the parameters supported by the
/oauth2/access_token
endpoint, refer to /oauth2/access_token.The client device must wait for the number of seconds previously provided as the value of
interval
between polling Identity Cloud for an access token. For example:$ curl \ --request POST \ --data "client_id=myClient" \ --data "grant_type=urn:ietf:params:oauth:grant-type:device_code" \ --data "device_code=<your-device-code>" \ "https://<tenant-env-fqdn>/am/oauth2/realms/root/realms/alpha/access_token"
If the user has authorized the client device, an HTTP 200 status code is returned, with an access token that can be used to request resources:
{ "access_token": "<access-token>", "refresh_token": "<refresh-token>", "scope": "write", "token_type": "Bearer", "expires_in": 3599 }
If the user has not yet authorized the client device, an HTTP 403 status code is returned, with the following error message:
{ "error": "authorization_pending", "error_description": "The user has not yet completed authorization" }
If the client device is polling faster than the specified interval, an HTTP 400 status code is returned, with the following error message:
{ "error": "slow_down", "error_description": "The polling interval has not elapsed since the last request" }
-