Skip to content

features.deviceFlow

This content is for v8.x. Switch to the latest version for up-to-date documentation.

RFC8628 - OAuth 2.0 Device Authorization Grant (Device Flow)

Enables Device Authorization Grant

default value:

{
charset: 'base-20',
deviceInfo: [Function: deviceInfo], // see expanded details below
enabled: false,
mask: '****-****',
successSource: [AsyncFunction: successSource], // see expanded details below
userCodeConfirmSource: [AsyncFunction: userCodeConfirmSource], // see expanded details below
userCodeInputSource: [AsyncFunction: userCodeInputSource] // see expanded details below
}
(Click to expand) features.deviceFlow options details

alias for a character set of the generated user codes. Supported values are

  • base-20 uses BCDFGHJKLMNPQRSTVWXZ
  • digits uses 0123456789

default value:

'base-20'

Function used to extract details from the device authorization endpoint request. This is then available during the end-user confirm screen and is supposed to aid the user confirm that the particular authorization initiated by the user from a device in their possession.

default value:

function deviceInfo(ctx) {
return {
ip: ctx.ip,
ua: ctx.get('user-agent'),
};
}

a string used as a template for the generated user codes, * characters will be replaced by random chars from the charset, -(dash) and (space) characters may be included for readability. See the RFC for details about minimal recommended entropy.

default value:

'****-****'

HTML source rendered when device code feature renders a success page for the User-Agent.

default value:

async function successSource(ctx) {
// @param ctx - koa request context
const {
clientId, clientName, clientUri, initiateLoginUri, logoUri, policyUri, tosUri,
} = ctx.oidc.client;
ctx.body = `<!DOCTYPE html>
<html>
<head>
<title>Sign-in Success</title>
<style>/* css and html classes omitted for brevity, see lib/helpers/defaults.js */</style>
</head>
<body>
<div>
<h1>Sign-in Success</h1>
<p>Your sign-in ${clientName ? `with ${clientName}` : ''} was successful, you can now close this page.</p>
</div>
</body>
</html>`;
}

HTML source rendered when device code feature renders an a confirmation prompt for ther User-Agent.

default value:

async function userCodeConfirmSource(ctx, form, client, deviceInfo, userCode) {
// @param ctx - koa request context
// @param form - form source (id="op.deviceConfirmForm") to be embedded in the page and
// submitted by the End-User.
// @param deviceInfo - device information from the device_authorization_endpoint call
// @param userCode - formatted user code by the configured mask
const {
clientId, clientName, clientUri, logoUri, policyUri, tosUri,
} = ctx.oidc.client;
ctx.body = `<!DOCTYPE html>
<html>
<head>
<title>Device Login Confirmation</title>
<style>/* css and html classes omitted for brevity, see lib/helpers/defaults.js */</style>
</head>
<body>
<div>
<h1>Confirm Device</h1>
<p>
<strong>${clientName || clientId}</strong>
<br/><br/>
The following code should be displayed on your device<br/><br/>
<code>${userCode}</code>
<br/><br/>
<small>If you did not initiate this action, the code does not match or are unaware of such device in your possession please close this window or click abort.</small>
</p>
${form}
<button autofocus type="submit" form="op.deviceConfirmForm">Continue</button>
<div>
<button type="submit" form="op.deviceConfirmForm" value="yes" name="abort">[ Abort ]</button>
</div>
</div>
</body>
</html>`;
}

HTML source rendered when device code feature renders an input prompt for the User-Agent.

default value:

async function userCodeInputSource(ctx, form, out, err) {
// @param ctx - koa request context
// @param form - form source (id="op.deviceInputForm") to be embedded in the page and submitted
// by the End-User.
// @param out - if an error is returned the out object contains details that are fit to be
// rendered, i.e. does not include internal error messages
// @param err - error object with an optional userCode property passed when the form is being
// re-rendered due to code missing/invalid/expired
let msg;
if (err && (err.userCode || err.name === 'NoCodeError')) {
msg = '<p>The code you entered is incorrect. Try again</p>';
} else if (err && err.name === 'AbortedError') {
msg = '<p>The Sign-in request was interrupted</p>';
} else if (err) {
msg = '<p>There was an error processing your request</p>';
} else {
msg = '<p>Enter the code displayed on your device</p>';
}
ctx.body = `<!DOCTYPE html>
<html>
<head>
<title>Sign-in</title>
<style>/* css and html classes omitted for brevity, see lib/helpers/defaults.js */</style>
</head>
<body>
<div>
<h1>Sign-in</h1>
${msg}
${form}
<button type="submit" form="op.deviceInputForm">Continue</button>
</div>
</body>
</html>`;
}