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 | | |
+----------+ +----------------+
(A) The client requests access from the authorization server and includes its client identifier in the request. Device Authorization Request
(B) The authorization server issues a verification code, an end-user code, and provides the end-user verification URI. Device Authorization Response
(C) The client instructs the end-user to use its user-agent (elsewhere) and visit the provided end-user verification URI. The client provides the end-user with the end-user code to enter in order to grant access.
(D) The authorization server validates the end-user code provided by the end-user (via the user-agent). The authorization server authenticates the end-user (via the user-agent) and prompts the end-user to grant the client's access request.
(E) While the end-user authorizes (or denies) the client's request (D), the client repeatedly polls the authorization server to find out if the end-user completed the end-user authorization step. The client includes the verification code and its client identifier. Device Token Request
(F) Assuming the end-user granted access, the authorization server validates the verification code provided by the client and responds back with the access token. Device Token Response
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.
Related Specifications
- Core 1.0
- Discovery 1.0
- Device Flow for Browserless and Input Constrained Devices
- RFC6750 Bearer Token Usage
- Token Revocation
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_type must be
- 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
andserver_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
andauthorization_pending
- application handles erroneous Device Token Responses
invalid_client
,invalid_request
andserver_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).