Browserless and Input Constrained Device Integration

7Pass device flow is suitable for clients executing on devices that do not have an easy data-entry method (e.g., game consoles, TVs, picture frames, and media hubs), but where the end-user has separate access to a user-agent on another computer or device (e.g., desktop computer, a laptop, a smart phone, or a tablet).

Instead of interacting with the end-user's user-agent, the client instructs the end-user to use another computer or device and connect to the authorization server to approve the access request. Since the client cannot receive incoming requests, it polls the authorization server repeatedly until the end-user completes the approval process.

Overview

+----------+                                +----------------+
|          |>---(A)-- Client Identifier --->|                |
|          |                                |                |
|          |<---(B)-- Verification Code, --<|                |
|          |              User Code,        |                |
|          |         & Verification URI     |                |
|  Device  |                                |                |
|  Client  |         Client Identifier &    |                |
|          |>---(E)-- Verification Code --->|                |
|          |    polling...                  |                |
|          |>---(E)-- Verification Code --->|                |
|          |                                |  Authorization |
|          |<---(F)-- Access Token --------<|     Server     |
+----------+  (w/ Optional Refresh Token)   |                |
      v                                     |                |
      :                                     |                |
     (C) User Code & Verification URI       |                |
      :                                     |                |
      v                                     |                |
+----------+                                |                |
| End-user |                                |                |
|    at    |<---(D)-- User authenticates -->|                |
|  Browser |                                |                |
+----------+                                +----------------+

Client identifier

Identifier required to request access from the authorization server can be generated in the clients section of the 7Pass developer panel.

Endpoints

Endpoints required for this flow are discovered using Discovery 1.0, the relevant metadata are device_authorization_endpoint, token_endpoint, userinfo_endpoint

Commonly asked questions

  • I am getting XMLHttpRequest cannot load .... No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin ... is therefore not allowed access. Please allow CORS for this endpoint.
    • Answer: CORS is purposefully not allowed for the device flow, we understand that tools used to develop the type of applications that need to consume this flow are mostly web-browser based, in most cases these are html5 applications that you open in a regular browser which implements all standard web security features. The target device/user-agent however does not and the recommendation is to disable web security while developing.

Device Authorization Request

Device Authorization Request is made with a x-www-form-urlencoded POST request and these parameters.

parameter note
client_id REQUIRED The client identifier value.
scope OPTIONAL The scope of the access request, defaults to openid.
claims OPTIONAL This parameter is used to request that specific Claims be returned. The value is a JSON object listing the requested Claims.
login_hint OPTIONAL Hint to the Authorization Server about the login identifier the End-User might use to log in (if necessary). This hint can be used by an RP if it first asks the End-User for their e-mail address (or other identifier) and then wants to pass that value as a hint to the discovered authorization service.
max_age OPTIONAL Maximum Authentication Age. Specifies the allowable elapsed time in seconds since the last time the End-User was actively authenticated by the OP. If the elapsed time is greater than this value, the OP will attempt to actively re-authenticate the End-User. When max_age is used, the ID Token returned will include an auth_time Claim Value.
prompt OPTIONAL Space-delimited, case-sensitive list of ASCII string values that specifies whether the Authorization Server prompts the End-User for reauthentication and consent.

For example:

POST /authorization HTTP/1.1
Host: device.7pass.de
Content-Type: application/x-www-form-urlencoded

client_id=s6BhdRkqt3&scope=openid%20profile%20offline_access&prompt=consent

Device Authorization Response

When successful Device Authorization Response is a JSON document with these properties.

property note
device_code The verification code.
user_code The end-user verification code.
verification_uri The end-user verification URI on the authorization server. This URL is to be used for development only, you are required to navigate End-Users to your own, where you will request the user_code, see Submitting User Code for details on this step.
expires_in The duration in seconds of the verification code lifetime.
interval The minimum amount interval in seconds the client should wait between Device Token Requests.

For example:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "device_code": "74tq5miHKB",
  "user_code": "94248",
  "verification_uri": "https://device.7pass.de",
  "expires_in": 600,
  "interval": 5
}

Device Token Request

Device Token Request is made with a x-www-form-urlencoded POST request and these parameters.

parameter note
grant_type REQUIRED The parameter value MUST be set to urn:ietf:params:oauth:grant-type:device_code.
device_code REQUIRED The device verification code, device_code from the Device Authorization Response
client_id REQUIRED The client identifier value.

For example:

POST /token HTTP/1.1
Host: op.7pass.de
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code&device_code=74tq5miHKB&client_id=s6BhdRkqt3

Device Token Response

When successful Device Token Response is a JSON document with these properties, corresponding to Core 1.0 access_token, expires_in, id_token, token_type, session_state, refresh_token (optional).

For example:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "access_token": "atfoobar",
  "expires_in": 7200,
  "token_type": "Bearer",
  "id_token": "jwt.for.you",
  "session_state": "567hjeqhuidsa.dsa6a32",
  "refresh_token": "rtfoobar"
}

Device Token Response can respond with soft errors, that indicate further polling is still going to be accepted. These errors are authorization_pending and slow_down.

Other error codes are considered hard errors, the client should stop polling and react accordingly, for example, by displaying an error to the user. These are expired_token, invalid_client, invalid_request, server_error.

For example:

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
  "error": "authorization_pending",
  "error_description": "End-user did not finish authorization yet."
}
HTTP/1.1 500 Server Error
Content-Type: application/json

{
  "error": "server_error",
  "error_description": "oopps"
}

Short URL recommendation

Utilizing short URLs, possibly even registering a custom domain that serves like a URL shortener is recommended.

e.g. instead of redbutton.de/tv just red.bt

https://domainr.com is a great tool for discovering what alternative domains may be available that resemble your actual domain.

The final url must enforce secure (TLS) connection with the server, but having a listener for http (port 80) and redirecting to https is recommended.

Submitting User Code

After the End-User navigates to your website he should be clearly prompted for the User Code he has displayed on his device.

The End-User User Code must be submitted to the verification_uri by the User-Agent. This request must be a x-www-form-urlencoded POST request with the following parameters.

parameter note
client_id REQUIRED The client identifier value.
redirect_uri REQUIRED Redirection URI to which a response will be sent. This URI MUST exactly match one of the Redirection URI values for the Client pre-registered in the 7Pass developer panel.
user_code REQUIRED The User Code provided by End-User.
state OPTIONAL Opaque value used by the RP to maintain state between the request and the callback to the endpoint specified by the redirect_uri parameter. If included, the OP passes this value back to the RP using the state query parameter when redirecting the User-Agent back to the RP.

For example:

POST / HTTP/1.1
Host: device.7pass.de
Content-Type: application/x-www-form-urlencoded

client_id=s6BhdRkqt3&user_code=FNP25BY&redirect_uri=https%3A%2F%2Fredbutton.de%2Fcb&state=af0ifjsldkj

To aid with this request the 7Pass Javascript SDK has helper function that creates an invisible DOM form element with the parameters as hidden inputs and submits it.

var sdk = new Pass.RP.SDK({
  clientId: '58ee0deb01062e7245c35b26',
}, 'https://op.7pass.de');

function deviceLogin() {
  sdk.deviceLogin(user_code, 'https://redbutton.de/cb', 'af0ifjsldkj');
}

When the entered code is invalid the User-Agent will be redirected to the specified redirect_uri with the parameters error=invalid_code and (optionally) state serialized using Query String Serialization, indicating the user should re-enter his user_code

Where to next?

Acknowledgement

7Pass version of device flow and at large the above copies are based on / are implementing Device Flow for Browserless and Input Constrained Devices.

Integration checklist

  • the device application does not have a bundled client_secret in its source code
  • one or more device clients are present and use a device client template/best practice setup
    • application_type must be native
    • token_endpoint_auth_type must be none
    • response_types must only contain code
    • grant_types must only contain urn:ietf:params:oauth:grant-type:device_code, authorization_code and (optional) refresh_token
    • at the very least every "platform" has a separate client, recommendation is that every major platform × supported major version combination has one client
  • application uses discovery to determine the endpoints it should be using
  • authentication prompt on the device does a valid Device Authorization Request
  • customized user_code prompt is implemented on a client-controlled website
  • application handles erroneous Device Authorization Responses invalid_client, invalid_request and server_error
  • upon the receipt of successful Device Authorization Response the application shows the custom short URI and user_code,
  • on the client website the user enters his code and a User-Agent performs a POST request to verification_uri with the required parameters
  • the client website handles invalid_code callback and re-prompts the user for his code
  • application starts Device Token Request polling in a reasonable interval
  • application handles soft Device Token Response errors slow_down and authorization_pending
  • application handles erroneous Device Token Responses invalid_client, invalid_request and server_error
  • application shows a success prompt to the user after the receipt of a successful Device Token Response
  • if present, a logout action discards it's known Access and Refresh Token using Token Revocation
  • application refreshes access tokens using refresh_token grant and handles refresh token rotation

7Pass Online Documentation. Generated from integrate/device.md. Generated at Tue Dec 14 2021 08:57:32 GMT+0000 (Coordinated Universal Time). Last file content update at Tue Dec 14 2021 08:56:38 GMT+0000 (Coordinated Universal Time).