Device flow
Sign in a CLI, TV or headless device with a short code the person approves in any browser (OAuth 2.0 Device Authorization Grant, RFC 8628).
Use the device flow when your app runs somewhere a person can't easily complete a
browser redirect: a command-line tool, a TV app, an SSH session, a build box. Your app
asks Hypery for a code, shows it, and polls the token endpoint. The person opens
https://hypery.ai/device on their phone or laptop, signs in, checks the code and the
permissions, and presses Approve. Your app's next poll receives the same
access_token and refresh_token as the authorization code flow.
At a glance
0. Enable it for your app
The device flow is off for every app until you turn it on: in the developer console, open
your app's Settings, switch on Sign in from other devices in the Sign-in section, and
save. Until then both endpoints answer unauthorized_client. Turning it off again stops
new device sign-ins and any codes that haven't been redeemed yet; tokens already issued keep
working until they expire or are revoked.
1. Start: request a device code
POST https://hypery.ai/api/oauth/device_authorization
Content-Type: application/x-www-form-urlencoded
client_id=YOUR_CLIENT_ID&scope=read%20ai%3AchatThe body may be form-encoded or JSON. Client credentials may also be sent with HTTP Basic.
Response (200):
{
"device_code": "Wm9...long opaque value...",
"user_code": "BCDF-GHJK",
"verification_uri": "https://hypery.ai/device",
"verification_uri_complete": "https://hypery.ai/device?user_code=BCDF-GHJK",
"expires_in": 600,
"interval": 5
}Keep device_code secret: it is what redeems the tokens. Show the person user_code and
verification_uri (or render verification_uri_complete as a QR code, so they don't have
to type the code).
2. The person approves
The person opens verification_uri, signs in to Hypery if needed, and enters the code.
The page shows your app's name, logo, the code and the permissions requested, with
Approve and Deny. Nothing is granted until they press Approve, even when they
arrive through verification_uri_complete.
Approving records your app on the person's Connected Apps list, exactly like the consent screen of the authorization code flow.
3. Poll the token endpoint
POST https://hypery.ai/api/oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=DEVICE_CODE&client_id=YOUR_CLIENT_IDWait interval seconds between requests. Until the person answers, the response is an
error (HTTP 400, { "error": "<code>" }):
Once approved, the next poll returns the tokens (200), once:
{
"access_token": "…",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "…",
"scope": "read ai:chat"
}Refresh and revoke them as described in OAuth 2.0 apps. A
public client (no client_secret at step 1) refreshes without a secret too.
Example
const HUB = 'https://hypery.ai';
const form = (fields) => ({
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams(fields),
});
const start = await (
await fetch(`${HUB}/api/oauth/device_authorization`, form({ client_id: CLIENT_ID, scope: 'read ai:chat' }))
).json();
console.log(`Open ${start.verification_uri} and enter ${start.user_code}`);
let interval = start.interval;
for (;;) {
await new Promise((r) => setTimeout(r, interval * 1000));
const res = await fetch(
`${HUB}/api/oauth/token`,
form({
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
device_code: start.device_code,
client_id: CLIENT_ID,
}),
);
const body = await res.json();
if (res.ok) {
saveTokens(body); // access_token, refresh_token, expires_in, scope
break;
}
if (body.error === 'authorization_pending') continue;
if (body.error === 'slow_down') {
interval += 5;
continue;
}
throw new Error(`Sign-in failed: ${body.error}`);
}curl -sS https://hypery.ai/api/oauth/device_authorization \
-d client_id="$HYPERY_CLIENT_ID" \
-d scope="read ai:chat"
# then, every `interval` seconds:
curl -sS https://hypery.ai/api/oauth/token \
-d grant_type=urn:ietf:params:oauth:grant-type:device_code \
-d device_code="$DEVICE_CODE" \
-d client_id="$HYPERY_CLIENT_ID"