## Device flow The Device Authorization Grant ([RFC 8628](https://datatracker.ietf.org/doc/html/rfc8628)) lets users authenticate on input-constrained devices — smart TVs, CLI tools, IoT devices, and set-top boxes — without typing credentials directly on the device. The device displays a short code and a URL; the user opens the URL on a phone or laptop, signs in, and approves access. The device polls in the background and receives tokens once the user approves. ### Prerequisites Prerequisites - A Frontegg workspace with OAuth enabled. - An OAuth application configured in your Frontegg dashboard. - Your `application ID`. - Your Frontegg domain (e.g. `https://app-xxxx.frontegg.com`). br All API calls in this guide use your Frontegg domain as the base URL: ``` https://{your-domain}/frontegg/oauth ``` ### How it works The device flow has three participants: - **Device app** (you build) — the TV, CLI, or IoT application that initiates the flow and polls for tokens. - **Verification page** (you build) — a page in your web application where the user signs in and approves or denies the request. - **Frontegg APIs** — the backend that manages device codes, user verification, and token issuance. ``` Device App Frontegg APIs Your Verification Page | | | | 1. POST /device/authorize | | |------------------------------->| | | { device_code, user_code, | | | verification_uri, ... } | | |<-------------------------------| | | | | | Display code + URL pointing | | | to YOUR verification page | | | | | | | 2. User opens your page | | |<-------------------------------| | | 3. User signs in | | |<-------------------------------| | | 4. GET /device?user_code= | | |<-------------------------------| | | { appName, scopes, status }| | |------------------------------->| | | 5. POST /device/verify | | | { approved: true } | | |<-------------------------------| | | | | 6. POST /token (polling) | | |------------------------------->| | | { access_token, id_token, | | | refresh_token } | | |<-------------------------------| | ``` br Important: you must build your own verification page The `verification_uri` returned by the API is **not** a user-facing web page, it points to a Frontegg JSON API endpoint. **Do not display it to users or encode it in a QR code.** Frontegg provides the backend APIs for the device flow but does not host a verification UI. You must build a verification page in your own application (see Step 2) and display its URL to the user instead. ### Step 1: Request device authorization The device initiates the flow by requesting a device code from the following public endpoint (no authentication required): ```http POST /frontegg/oauth/device/authorize Content-Type: application/json ``` br **Request body:** | Field | Type | Required | Description | | --- | --- | --- | --- | | `client_id` | string | Yes | Your OAuth application client ID | | `scope` | string | No | Space-separated list of scopes | **Example:** ```bash curl -X POST https://{your-domain}/frontegg/oauth/device/authorize \ -H "Content-Type: application/json" \ -d '{"client_id": "your-client-id", "scope": "openid profile email"}' ``` br **Response (200 OK):** ```json { "device_code": "a1b2c3d4e5f6...", "user_code": "BCKF-DHLM", "verification_uri": "https://app-xxxx.frontegg.com/oauth/device", "verification_uri_complete": "https://app-xxxx.frontegg.com/oauth/device?user_code=BCKF-DHLM", "expires_in": 1800, "interval": 5 } ``` | Field | Description | | --- | --- | | `device_code` | Opaque token the device uses to poll for access tokens. Keep this secret — never expose it to the user. | | `user_code` | Short human-readable code (`XXXX-XXXX` format) displayed to the user for verification. | | `verification_uri` | **Do not use.** Points to a Frontegg JSON API endpoint, not a web page. See note below. | | `verification_uri_complete` | Same as `verification_uri`, with `user_code` appended. **Do not use.** | | `expires_in` | Seconds until the device code expires (default: 900 / 15 minutes). | | `interval` | Minimum seconds to wait between polling requests (default: 5). | Important: display your own verification page URL `verification_uri` and `verification_uri_complete` point to a Frontegg JSON API endpoint, not a user-facing page. Displaying them to users or encoding them in a QR code will not work. Instead, direct users to your own verification page (see Step 2) and pass the `user_code` as a query parameter: ``` Go to: https://myapp.com/device-activate Enter code: BCKF-DHLM ``` Or as a QR code URL: ``` https://myapp.com/device-activate?user_code=BCKF-DHLM ``` br After receiving the response: - Display `user_code` prominently on screen. - Direct users to your verification page URL (not `verification_uri`). - Store `device_code` locally — you'll need it to poll for tokens. - Use `interval` as the minimum delay between polling requests. ### Step 2: Build the verification page Host a page in your application where authenticated users can review and approve or deny device access requests. This page calls the Frontegg device APIs on behalf of the signed-in user. Using the Frontegg SDK The verification page can be a protected route in your application using a Frontegg SDK (`@frontegg/react`, `@frontegg/nextjs`, `@frontegg/angular`, `@frontegg/vue`). When the route is behind the SDK's authentication guard, unauthenticated users are automatically redirected to login and back — no manual token handling required. br Your verification page should follow this flow: 1. Host the page at a URL such as `/device-activate`. 2. Read `user_code` from the URL query string (`?user_code=BCKF-DHLM`), or prompt the user to enter it manually. 3. Authenticate the user. If using the Frontegg SDK on a protected route, this happens automatically. 4. Fetch device info to display the app name and requested scopes. 5. Show a confirmation UI with the app name, scopes, and user code, then prompt the user to approve or deny. 6. Submit the decision to Frontegg. 7. Show a result screen telling the user to return to their device. #### Get device info Retrieve details about the device request to display to the user before they approve. ```http GET /frontegg/oauth/device?user_code={user_code} Authorization: Bearer {access_token} Accept: application/json ``` **Response (200 OK):** ```json { "appName": "My TV App", "scopes": "openid profile email", "status": "pending" } ``` | Field | Description | | --- | --- | | `appName` | Name of the application requesting access. | | `scopes` | Requested scopes, or `undefined` if none were requested. | | `status` | `pending`, `approved`, or `denied`. Only show the approve/deny UI when `pending`. | #### Approve or deny ```http POST /frontegg/oauth/device/verify Authorization: Bearer {access_token} Content-Type: application/json ``` **Request body:** | Field | Type | Required | Description | | --- | --- | --- | --- | | `user_code` | string | Yes | The code displayed on the device. | | `approved` | boolean | Yes | `true` to approve, `false` to deny. | **Example:** ```bash curl -X POST https://{your-domain}/frontegg/oauth/device/verify \ -H "Content-Type: application/json" \ -H "Authorization: Bearer eyJhbGciOi..." \ -d '{"user_code": "BCKF-DHLM", "approved": true}' ``` **Response:** `200 OK` with no body returned on success. #### Complete verification page example The following self-contained HTML/JS example demonstrates the full verification page flow. It includes a simple login form for illustration. In production, protect this route with the Frontegg SDK so authentication is handled automatically, and replace the manual login with the SDK's `getAccessToken()`. Replace `BASE_URL` with your Frontegg domain (e.g. `https://app-xxxx.frontegg.com`). ```html
Loading...