From 269f7a92599f58003e6173d9fce1d3092da3244e Mon Sep 17 00:00:00 2001 From: Dave Berner Date: Fri, 1 Aug 2025 06:29:36 +1000 Subject: [PATCH 01/14] feat: initial commit of device flow --- .../device-authorization-flow/api-calls.mdx | 225 ++++++++++++++++++ .../device-authorization-flow/overview.mdx | 120 ++++++++++ .../device-authorization-flow/quick-start.mdx | 105 ++++++++ .../troubleshooting.mdx | 206 ++++++++++++++++ .../about-m2m/m2m-quick-start-guide.mdx | 10 +- src/data/sidebarData.ts | 28 ++- 6 files changed, 684 insertions(+), 10 deletions(-) create mode 100644 src/content/docs/authenticate/device-authorization-flow/api-calls.mdx create mode 100644 src/content/docs/authenticate/device-authorization-flow/overview.mdx create mode 100644 src/content/docs/authenticate/device-authorization-flow/quick-start.mdx create mode 100644 src/content/docs/authenticate/device-authorization-flow/troubleshooting.mdx diff --git a/src/content/docs/authenticate/device-authorization-flow/api-calls.mdx b/src/content/docs/authenticate/device-authorization-flow/api-calls.mdx new file mode 100644 index 00000000..9faa05ce --- /dev/null +++ b/src/content/docs/authenticate/device-authorization-flow/api-calls.mdx @@ -0,0 +1,225 @@ +--- +page_id: 8d8234a5-b064-47a1-a1e1-9b3f98a57f34 +title: Call your API using device authorization flow +sidebar: + order: 3 +relatedArticles: + - 2944d2bc-4e84-4918-b4f6-7406a7c26f98 + - 888b1546-8047-4609-af59-8cf859527aa0 + - de937e16-8094-4aad-ada9-e6a37d74f508 + - 1cbd91d2-c0b3-45b3-b038-319de1b2c794 +--- + +Once you've received an access token from the Device Authorization Flow, you can use it to call your protected APIs. This guide shows you how to validate tokens, handle scopes, and make authenticated API requests. + +## Using the access token + +The access token you receive from Device Authorization Flow is a standard OAuth 2.0 Bearer token. Include it in the `Authorization` header of your API requests: + +```bash +curl -X GET https://your-api.com/protected-resource \ + -H "Authorization: Bearer YOUR_ACCESS_TOKEN" +``` + +## Token validation + +Before processing API requests, validate the access token to ensure it's valid and hasn't expired: + +### Validate with Kinde's userinfo endpoint + +```bash +curl -X GET https://.kinde.com/oauth2/v2/user_profile \ + -H "Authorization: Bearer YOUR_ACCESS_TOKEN" +``` + +**Success response**: + +```json +{ + "sub": "kp_c3143a4b50ad43c88e541d9077681782", + "provided_id": "some_external_id", + "name": "John Snow", + "given_name": "John", + "family_name": "Snow", + "updated_at": 1612345678, + "email": "john.snow@example.com", + "email_verified": true, + "picture": "https://example.com/john_snow.jpg", + "preferred_username": "john_snow", + "id": "kp_c3143a4b50ad43c88e541d9077681782" +} +``` + +**Error response** (invalid token): + +```json +{ + "error": "invalid_token", + "error_description": "The access token is invalid or expired" +} +``` + +### Validate with your own API + +You can also validate tokens in your own API by verifying the JWT signature and claims: + +```javascript +// Node.js example using jsonwebtoken +const jwt = require("jsonwebtoken"); + +function validateToken(token) { + try { + const decoded = jwt.verify(token, "YOUR_JWT_SECRET"); + return { + valid: true, + user: decoded + }; + } catch (error) { + return { + valid: false, + error: error.message + }; + } +} +``` + +## Scope enforcement + +Access tokens include scopes that determine what resources the user can access. Check the required scopes before processing requests: + +```javascript +// Example: Check if user has required scope +function hasRequiredScope(token, requiredScope) { + const decoded = jwt.decode(token); + const tokenScopes = decoded.scope.split(" "); + return tokenScopes.includes(requiredScope); +} + +// Usage +if (!hasRequiredScope(accessToken, "read:users")) { + return res.status(403).json({error: "Insufficient scope"}); +} +``` + +## Common API patterns + +### Protected resource endpoint + +```javascript +// Express.js example +app.get("/api/protected-resource", authenticateToken, (req, res) => { + // req.user contains the decoded token payload + res.json({ + message: "Access granted", + user: req.user + }); +}); + +function authenticateToken(req, res, next) { + const authHeader = req.headers["authorization"]; + const token = authHeader && authHeader.split(" ")[1]; + + if (!token) { + return res.status(401).json({error: "Access token required"}); + } + + // Validate token with Kinde + fetch("https://.kinde.com/oauth2/v2/user_profile", { + headers: { + Authorization: `Bearer ${token}` + } + }) + .then((response) => { + if (!response.ok) { + throw new Error("Invalid token"); + } + return response.json(); + }) + .then((user) => { + req.user = user; + next(); + }) + .catch((error) => { + return res.status(401).json({error: "Invalid token"}); + }); +} +``` + +### Error handling + +Handle common token-related errors: + +```javascript +function handleTokenError(error) { + switch (error.error) { + case "invalid_token": + // Token is invalid or expired + return res.status(401).json({error: "Please re-authenticate"}); + + case "insufficient_scope": + // Token doesn't have required permissions + return res.status(403).json({error: "Insufficient permissions"}); + + default: + return res.status(500).json({error: "Authentication error"}); + } +} +``` + +## Security best practices + +### Token storage + +- **Never store tokens in localStorage**: Use secure HTTP-only cookies or memory storage +- **Validate tokens server-side**: Always validate tokens on your backend, not just the client + +### Rate limiting + +Implement rate limiting for token validation requests: + +```javascript +const rateLimit = require("express-rate-limit"); + +const tokenValidationLimiter = rateLimit({ + windowMs: 15 * 60 * 1000, // 15 minutes + max: 100, // limit each IP to 100 requests per windowMs + message: "Too many token validation requests" +}); + +app.use("/api/protected-resource", tokenValidationLimiter); +``` + +### Logging and monitoring + +Log authentication events for security monitoring: + +```javascript +function logAuthEvent(token, action, success) { + console.log({ + timestamp: new Date().toISOString(), + action: action, + success: success, + userId: token.user_id, + scopes: token.scope + }); +} +``` + +## Testing your API + +Test your protected endpoints with the access token: + +```bash +# Test with curl +curl -X GET https://your-api.com/protected-resource \ + -H "Authorization: Bearer YOUR_ACCESS_TOKEN" + +# Test with JavaScript +fetch('https://your-api.com/protected-resource', { + headers: { + 'Authorization': 'Bearer YOUR_ACCESS_TOKEN' + } +}) +.then(response => response.json()) +.then(data => console.log(data)); +``` diff --git a/src/content/docs/authenticate/device-authorization-flow/overview.mdx b/src/content/docs/authenticate/device-authorization-flow/overview.mdx new file mode 100644 index 00000000..32a393ff --- /dev/null +++ b/src/content/docs/authenticate/device-authorization-flow/overview.mdx @@ -0,0 +1,120 @@ +--- +page_id: ab3834cc-4645-4b7a-826a-c7f502eee3dd +title: Overview +sidebar: + order: 2 +relatedArticles: + - 2944d2bc-4e84-4918-b4f6-7406a7c26f98 + - 8d8234a5-b064-47a1-a1e1-9b3f98a57f34 + - 888b1546-8047-4609-af59-8cf859527aa0 + - 28c6e830-8e82-4bf8-aab7-87ebafeb68e4 +--- + +Device Authorization Flow (RFC 8628) enables OAuth 2.0 authorization for devices with limited input capabilities, such as smart TVs, gaming consoles, or IoT devices. Users authenticate on a secondary device (like a phone or computer) while the primary device receives the access token. + +## How it works + +The Device Authorization Flow follows these steps: + +1. **Device requests authorization**: The device requests a device code and user code from Kinde +2. **User authenticates**: The user visits a verification URI on another device and enters the user code +3. **Device polls for token**: The device polls the token endpoint until authorization is complete +4. **Access granted**: The device receives an access token and can call protected APIs + +## Endpoints + +### Device Authorization Endpoint + +**URL**: `https://.kinde.com/oauth2/device/auth` + +**Method**: `POST` + +**Content-Type**: `application/x-www-form-urlencoded` + +**Parameters**: + +- `grant_type`: `urn:ietf:params:oauth:grant-type:device_code` +- `client_id` (optional): Your application's client ID - can be omitted if you have set an application as the default for device flows +- `audience` (optional): The audience to use for the request + +**Response**: + +```json +{ + "device_code": "kinde_dc_device_code_here", + "user_code": "CSLDFDUU", + "verification_uri": "https://.kinde.com/device", + "verification_uri_complete": "https://.kinde.com/device?user_code=CSLDFDUU", + "expires_in": 600, + "interval": 5, + "qr_code": "data:image/png;base64,..." +} +``` + +### Token Endpoint + +**URL**: `https://.kinde.com/oauth2/token` + +**Method**: `POST` + +**Content-Type**: `application/x-www-form-urlencoded` + +**Parameters**: + +- `grant_type`: `urn:ietf:params:oauth:grant-type:device_code` +- `client_id`: Your application's client ID +- `device_code`: The device code received from the authorization endpoint + +**Success response**: + +```json +{ + "access_token": "eyJ...", + "expires_in": 86400, + "scope": "", // granted scopes are in the access token + "token_type": "bearer" +} +``` + +**Example error response**: + +```json +{ + "error": "authorization_pending", + "error_description": "The user has not yet completed the authorization" +} +``` + +## Polling behavior + +The device must poll the token endpoint at regular intervals until the user completes authentication: + +- **Initial interval**: Use the `interval` value from the device authorization response (typically 5 seconds) +- **Slow down**: If you receive a `slow_down` error, increase the polling interval by 5 seconds +- **Maximum time**: Stop polling after the `expires_in` time (typically 30 minutes) + +## Error codes + +| Error Code | Description | Action | +| ----------------------- | ------------------------------------ | ------------------------------ | +| `authorization_pending` | User hasn't completed authentication | Continue polling | +| `slow_down` | Polling too frequently | Increase interval by 5 seconds | +| `access_denied` | User denied the authorization | Stop polling | +| `expired_token` | Device code has expired | Request a new device code | +| `server_error` | Misconfigured device code | Request a new device code | + +## Security considerations + +- **User code format**: User codes are formatted as `XXXXXXXX` for easy entry +- **Verification URI**: Users should verify they're on the correct domain +- **Token expiration**: Access tokens expire after 1 hour by default + +## Audience + +If an `audience` is specified in the request, the access token will include the audience in the `aud` claim. Kinde supports requesting multiple audiences. + +The API must be authorized for the Device Authorization application. + +## Scopes and permissions + +If an audience is specified in the request, any scopes which are belong to that audience that are granted to the user by their role will also be granted to the device. The list of scopes will be displayed on the consent screen. If the user consents, the scopes will be included in the `scope` claim of the access token. diff --git a/src/content/docs/authenticate/device-authorization-flow/quick-start.mdx b/src/content/docs/authenticate/device-authorization-flow/quick-start.mdx new file mode 100644 index 00000000..3b2c9429 --- /dev/null +++ b/src/content/docs/authenticate/device-authorization-flow/quick-start.mdx @@ -0,0 +1,105 @@ +--- +page_id: 2944d2bc-4e84-4918-b4f6-7406a7c26f98 +title: Quick start +sidebar: + order: 1 +relatedArticles: + - 8d8234a5-b064-47a1-a1e1-9b3f98a57f34 + - 888b1546-8047-4609-af59-8cf859527aa0 +--- + +The Device authorization Flow allows users to authenticate on one device (like a TV or smart device) using another device (like a phone or computer). This is perfect for devices with limited input capabilities. + +In this quick start, you'll learn how to implement the Device Authorization Flow using Kinde in just 5 minutes. + +## Prerequisites + +- `curl` or a similar HTTP client + +## Step 1 - Create a Device Authorization app + +1. From the home page select **Add application** +2. Enter a name +3. Choose **Device and IoT** +4. Select **Save** +5. Make a note of the Client ID, you'll need this later + +## Step 2 - Enable an authentication method for your application + +1. Select **Authentication** from the left hand menu +2. Select **Configure** on the **Passwordless** > **Email + code** card +3. Under **Applications** select the application you created in step 1 +4. Select **Save** + +## Step 3 - Request a device code + +Request a device code from Kinde's authorization endpoint: + +```bash +curl -X POST https://.kinde.com/oauth2/device/auth \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "client_id=" \ + -d "grant_type=urn:ietf:params:oauth:grant-type:device_code" +``` + +The response will include a `device_code`, `user_code`, and `verification_uri`: + +```json +{ + "device_code": "kinde_dc_...", + "user_code": "CSLDFDUU", + "verification_uri": "https://.kinde.com/device", + "verification_uri_complete": "https://.kinde.com/device?user_code=CSLDFDUU", + "expires_in": 600, + "interval": 5, + "qr_code": "data:image/png;base64,..." +} +``` + +## Step 4 - Display the user code + +Show the `user_code` to the user and provide the `verification_uri_complete` or QR code from the response. The user should: + +1. Visit the `verification_uri_complete` URL on their phone or computer +2. Complete the authentication process + +## Step 5 - Poll for the access token + +While the user is authenticating, poll the token endpoint: + +```bash +curl -X POST https://.kinde.com/oauth2/token \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "grant_type=urn:ietf:params:oauth:grant-type:device_code" \ + -d "client_id=" \ + -d "device_code=" +``` + +Continue polling every 5 seconds (or the `interval` value from the response) until you receive a successful response like: + +```json +{ + "access_token": "eyJ...", + "expires_in": 86400, + "scope": "", + "token_type": "bearer" +} +``` + +## Step 6 - Use the access token + +Once you have received the access token, you can call your protected APIs: + +```bash +curl -X GET https://your-api.com/protected-resource \ + -H "Authorization: Bearer YOUR_ACCESS_TOKEN" +``` + +## Useful tips + +You can set an application to be the default for device flows. This will be the application that is used if no Client ID is specified in the request. + +1. Select **Settings** > **Applications** +2. Select the Device Authorization application you want to set as default +3. Select **Set as default** +4. Select **Save** diff --git a/src/content/docs/authenticate/device-authorization-flow/troubleshooting.mdx b/src/content/docs/authenticate/device-authorization-flow/troubleshooting.mdx new file mode 100644 index 00000000..fdb38c5e --- /dev/null +++ b/src/content/docs/authenticate/device-authorization-flow/troubleshooting.mdx @@ -0,0 +1,206 @@ +--- +page_id: 545c511c-ce01-4251-be2a-d04407820d6f +title: Troubleshooting & common errors +sidebar: + order: 6 +relatedArticles: + - 2944d2bc-4e84-4918-b4f6-7406a7c26f98 + - 888b1546-8047-4609-af59-8cf859527aa0 + - de937e16-8094-4aad-ada9-e6a37d74f508 +--- + +This guide helps you diagnose and resolve common issues with Device Authorization Flow. Learn how to handle errors, debug problems, and implement proper error recovery. + +## Common error codes + +### authorization_pending + +**Error**: `authorization_pending` +**Description**: The user hasn't completed the authorization process yet. + +**Solution**: Continue polling the token endpoint. This is normal behavior. + +```javascript +// Example: Handle authorization_pending +if (error === "authorization_pending") { + console.log("User has not completed authorization yet. Continue polling..."); + // Wait for the specified interval before next poll + setTimeout(pollForToken, interval * 1000); +} +``` + +### slow_down + +**Error**: `slow_down` +**Description**: You're polling too frequently. + +**Solution**: Increase the polling interval by 5 seconds. + +```javascript +// Example: Handle slow_down +if (error === "slow_down") { + console.log("Polling too fast. Increasing interval..."); + interval += 5; // Increase interval by 5 seconds + setTimeout(pollForToken, interval * 1000); +} +``` + +### access_denied + +**Error**: `access_denied` +**Description**: The user denied the authorization request. + +**Solution**: Stop polling and inform the user they need to try again. + +```javascript +// Example: Handle access_denied +if (error === "access_denied") { + console.log("User denied authorization"); + showErrorMessage("Authorization was denied. Please try again."); + stopPolling(); +} +``` + +### expired_token + +**Error**: `expired_token` +**Description**: The device code has expired (typically after 30 minutes). + +**Solution**: Request a new device code. + +```javascript +// Example: Handle expired_token +if (error === "expired_token") { + console.log("Device code expired"); + showErrorMessage("This code has expired. Please request a new one."); + requestNewDeviceCode(); +} +``` + +## Polling mistakes + +### Too frequent polling + +**Problem**: Polling more frequently than the recommended interval. + +**Solution**: Always respect the `interval` value from the device authorization response. + +```javascript +// Good: Respect the interval +function pollForToken(deviceCode, interval = 5) { + setTimeout(() => { + // Make token request + checkTokenStatus(deviceCode); + }, interval * 1000); +} + +// Bad: Polling too frequently +function pollForToken(deviceCode) { + setInterval(() => { + // This polls every 1 second - too frequent! + checkTokenStatus(deviceCode); + }, 1000); +} +``` + +### Not handling slow_down properly + +**Problem**: Not increasing the interval when receiving `slow_down` errors. + +**Solution**: Implement exponential backoff. + +```javascript +let currentInterval = 5; // Start with 5 seconds + +function pollForToken(deviceCode) { + checkTokenStatus(deviceCode).then((response) => { + if (response.error === "slow_down") { + currentInterval += 5; // Increase by 5 seconds + console.log(`Increasing interval to ${currentInterval} seconds`); + } + + // Continue polling with updated interval + setTimeout(() => pollForToken(deviceCode), currentInterval * 1000); + }); +} +``` + +### Not stopping on errors + +**Problem**: Continuing to poll after receiving fatal errors. + +**Solution**: Stop polling for non-recoverable errors. + +```javascript +function pollForToken(deviceCode) { + checkTokenStatus(deviceCode).then((response) => { + if (response.error) { + switch (response.error) { + case "authorization_pending": + // Continue polling + setTimeout(() => pollForToken(deviceCode), interval * 1000); + break; + case "slow_down": + // Increase interval and continue + interval += 5; + setTimeout(() => pollForToken(deviceCode), interval * 1000); + break; + case "access_denied": + case "expired_token": + // Stop polling - these are fatal errors + stopPolling(); + handleError(response.error); + break; + } + } else { + // Success - stop polling + handleSuccess(response); + } + }); +} +``` + +## Network issues + +### Connection timeouts + +**Problem**: Network requests timing out. + +**Solution**: Implement proper timeout handling and retry logic. + +```javascript +function checkTokenStatus(deviceCode) { + return fetch("https://.kinde.com/oauth2/token", { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded" + }, + body: new URLSearchParams({ + grant_type: "urn:ietf:params:oauth:grant-type:device_code", + client_id: "", + device_code: deviceCode + }), + timeout: 10000 // 10 second timeout + }) + .then((response) => response.json()) + .catch((error) => { + console.error("Network error:", error); + // Retry after a delay + setTimeout(() => checkTokenStatus(deviceCode), 5000); + }); +} +``` + +### DNS resolution issues + +**Problem**: Cannot resolve the Kinde domain. + +**Solution**: Verify your domain configuration and network connectivity. + +```bash +# Test DNS resolution +nslookup .kinde.com + +# Test connectivity +curl -I https://.kinde.com/oauth2/v2/device_authorization +``` diff --git a/src/content/docs/machine-to-machine-applications/about-m2m/m2m-quick-start-guide.mdx b/src/content/docs/machine-to-machine-applications/about-m2m/m2m-quick-start-guide.mdx index 1a3b639d..9c588fff 100644 --- a/src/content/docs/machine-to-machine-applications/about-m2m/m2m-quick-start-guide.mdx +++ b/src/content/docs/machine-to-machine-applications/about-m2m/m2m-quick-start-guide.mdx @@ -13,10 +13,11 @@ This guide shows you how to create a Machine-to-Machine (M2M) application in Kin ## Step 1 - Create a machine-to-machine app -1. Go to the **Applications** section in your Kinde dashboard -2. Select **Machine-to-machine apps** -3. Choose **Add M2M application** -4. Enter a name +1. Go to the **Settings** > **Applications** section in your Kinde dashboard +2. Select **Add application** +3. Enter a name +4. Choose **Machine-to-machine (M2M)** +5. Select **Save** ## Step 2 - Create an API in Kinde (if you don't have one) @@ -90,4 +91,3 @@ Include the token in the `Authorization` header: curl https://your-subdomain.kinde.com/v1/organizations \ -H "Authorization: Bearer " ``` - diff --git a/src/data/sidebarData.ts b/src/data/sidebarData.ts index cafd1954..afdcd906 100644 --- a/src/data/sidebarData.ts +++ b/src/data/sidebarData.ts @@ -11,7 +11,10 @@ const sidebarData = [ items: [ {label: "Guides", autogenerate: {directory: "get-started/guides"}, collapsed: false}, { - label: "Learn about Kinde", autogenerate: {directory: "get-started/learn-about-kinde"}, collapsed: false}, + label: "Learn about Kinde", + autogenerate: {directory: "get-started/learn-about-kinde"}, + collapsed: false + }, { label: "Switch to Kinde", autogenerate: {directory: "get-started/switch-to-kinde"}, @@ -132,6 +135,11 @@ const sidebarData = [ label: "Social connections", autogenerate: {directory: "authenticate/social-sign-in"}, collapsed: false + }, + { + label: "Device Authorization Flow", + autogenerate: {directory: "authenticate/device-authorization-flow"}, + collapsed: false } ] }, @@ -282,13 +290,21 @@ const sidebarData = [ autogenerate: {directory: "machine-to-machine-applications/organization-scoped-m2m-apps"}, collapsed: false }, - {label: "M2M token customization", autogenerate: {directory: "machine-to-machine-applications/m2m-token-customization"}, collapsed: false}, + { + label: "M2M token customization", + autogenerate: {directory: "machine-to-machine-applications/m2m-token-customization"}, + collapsed: false + }, { label: "Automation", autogenerate: {directory: "machine-to-machine-applications/m2m-workflow-automation"}, collapsed: false }, - {label: "Troubleshooting", autogenerate: {directory: "machine-to-machine-applications/troubleshooting-m2m"}, collapsed: false} + { + label: "Troubleshooting", + autogenerate: {directory: "machine-to-machine-applications/troubleshooting-m2m"}, + collapsed: false + } ] }, { @@ -331,11 +347,13 @@ const sidebarData = [ { label: "About", autogenerate: {directory: "releases/about"}, - collapsed: false}, + collapsed: false + }, { label: "Guides", autogenerate: {directory: "releases/guides"}, - collapsed: false}, + collapsed: false + }, { label: "Feature flags", autogenerate: {directory: "releases/feature-flags"}, From d3c96af080888c1971b6b4484c86a0bf1a48f8a1 Mon Sep 17 00:00:00 2001 From: Dave Berner Date: Fri, 1 Aug 2025 06:37:28 +1000 Subject: [PATCH 02/14] chore: fix formatting --- src/data/sidebarData.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/sidebarData.ts b/src/data/sidebarData.ts index afdcd906..4c20061b 100644 --- a/src/data/sidebarData.ts +++ b/src/data/sidebarData.ts @@ -137,7 +137,7 @@ const sidebarData = [ collapsed: false }, { - label: "Device Authorization Flow", + label: "Device authorization flow", autogenerate: {directory: "authenticate/device-authorization-flow"}, collapsed: false } From 539f7cae069b9789da32cc0fe7a4b2a2680e5673 Mon Sep 17 00:00:00 2001 From: ClaireM <127452294+clairekinde11@users.noreply.github.com> Date: Tue, 5 Aug 2025 11:20:30 +1000 Subject: [PATCH 03/14] Claire edit for consistent style. --- .../device-authorization-flow/quick-start.mdx | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/content/docs/authenticate/device-authorization-flow/quick-start.mdx b/src/content/docs/authenticate/device-authorization-flow/quick-start.mdx index 3b2c9429..e2bc789e 100644 --- a/src/content/docs/authenticate/device-authorization-flow/quick-start.mdx +++ b/src/content/docs/authenticate/device-authorization-flow/quick-start.mdx @@ -8,7 +8,7 @@ relatedArticles: - 888b1546-8047-4609-af59-8cf859527aa0 --- -The Device authorization Flow allows users to authenticate on one device (like a TV or smart device) using another device (like a phone or computer). This is perfect for devices with limited input capabilities. +The Device Authorization Flow allows users to authenticate on one device (like a TV or smart device) using another device (like a phone or computer). This is perfect for devices with limited input capabilities. In this quick start, you'll learn how to implement the Device Authorization Flow using Kinde in just 5 minutes. @@ -16,22 +16,22 @@ In this quick start, you'll learn how to implement the Device Authorization Flow - `curl` or a similar HTTP client -## Step 1 - Create a Device Authorization app +## Step 1: Create a Device Authorization app -1. From the home page select **Add application** -2. Enter a name -3. Choose **Device and IoT** -4. Select **Save** -5. Make a note of the Client ID, you'll need this later +1. From the Kinde home page select **Add application**. +2. Enter a name for the application. +3. Choose **Device and IoT**. +4. Select **Save**. +5. Make a note of the Client ID, you'll need this later. -## Step 2 - Enable an authentication method for your application +## Step 2: Enable an authentication method for your application -1. Select **Authentication** from the left hand menu -2. Select **Configure** on the **Passwordless** > **Email + code** card -3. Under **Applications** select the application you created in step 1 -4. Select **Save** +1. Go to **Settings > Authentication**. +2. Select **Configure** on the **Passwordless** > **Email + code** card. +3. Under **Applications** select the application you created in step 1. +4. Select **Save**. -## Step 3 - Request a device code +## Step 3: Request a device code Request a device code from Kinde's authorization endpoint: @@ -56,14 +56,14 @@ The response will include a `device_code`, `user_code`, and `verification_uri`: } ``` -## Step 4 - Display the user code +## Step 4: Display the user code Show the `user_code` to the user and provide the `verification_uri_complete` or QR code from the response. The user should: -1. Visit the `verification_uri_complete` URL on their phone or computer -2. Complete the authentication process +1. Visit the `verification_uri_complete` URL on their phone or computer. +2. Complete the authentication process. -## Step 5 - Poll for the access token +## Step 5: Poll for the access token While the user is authenticating, poll the token endpoint: @@ -86,7 +86,7 @@ Continue polling every 5 seconds (or the `interval` value from the response) unt } ``` -## Step 6 - Use the access token +## Step 6: Use the access token Once you have received the access token, you can call your protected APIs: @@ -95,7 +95,7 @@ curl -X GET https://your-api.com/protected-resource \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` -## Useful tips +## Set an app as default You can set an application to be the default for device flows. This will be the application that is used if no Client ID is specified in the request. From b243355774e16093dbe04f86155f585db69c93be Mon Sep 17 00:00:00 2001 From: ClaireM <127452294+clairekinde11@users.noreply.github.com> Date: Tue, 5 Aug 2025 11:28:59 +1000 Subject: [PATCH 04/14] Claire update to edit headings and style --- .../device-authorization-flow/overview.mdx | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/src/content/docs/authenticate/device-authorization-flow/overview.mdx b/src/content/docs/authenticate/device-authorization-flow/overview.mdx index 32a393ff..0c8bdfb6 100644 --- a/src/content/docs/authenticate/device-authorization-flow/overview.mdx +++ b/src/content/docs/authenticate/device-authorization-flow/overview.mdx @@ -10,20 +10,18 @@ relatedArticles: - 28c6e830-8e82-4bf8-aab7-87ebafeb68e4 --- -Device Authorization Flow (RFC 8628) enables OAuth 2.0 authorization for devices with limited input capabilities, such as smart TVs, gaming consoles, or IoT devices. Users authenticate on a secondary device (like a phone or computer) while the primary device receives the access token. +Kinde's device authorization flow adheres to `RFC 8628`, also known as the OAuth 2.0 Device Authorization Grant. It enables authorization for devices with limited input capabilities, such as smart TVs, gaming consoles, or IoT devices. Users authenticate on a secondary device (like a phone or computer) while the primary device receives the access token. -## How it works +## How the device authentication flow works -The Device Authorization Flow follows these steps: +1. **Device requests authorization**: The device requests a device code and user code from Kinde. +2. **User authenticates**: The user visits a verification URI on another device and enters the user code. +3. **Device polls for token**: The device polls the token endpoint until authorization is complete. +4. **Access granted**: The device receives an access token and can call protected APIs. -1. **Device requests authorization**: The device requests a device code and user code from Kinde -2. **User authenticates**: The user visits a verification URI on another device and enters the user code -3. **Device polls for token**: The device polls the token endpoint until authorization is complete -4. **Access granted**: The device receives an access token and can call protected APIs +## Endpoints for the device authorization flow -## Endpoints - -### Device Authorization Endpoint +### Device authorization endpoint **URL**: `https://.kinde.com/oauth2/device/auth` @@ -51,7 +49,7 @@ The Device Authorization Flow follows these steps: } ``` -### Token Endpoint +### Token endpoint **URL**: `https://.kinde.com/oauth2/token` @@ -89,11 +87,11 @@ The Device Authorization Flow follows these steps: The device must poll the token endpoint at regular intervals until the user completes authentication: -- **Initial interval**: Use the `interval` value from the device authorization response (typically 5 seconds) -- **Slow down**: If you receive a `slow_down` error, increase the polling interval by 5 seconds -- **Maximum time**: Stop polling after the `expires_in` time (typically 30 minutes) +- **Initial interval**: Use the `interval` value from the device authorization response (typically 5 seconds). +- **Slow down**: If you receive a `slow_down` error, increase the polling interval by 5 seconds. +- **Maximum time**: Stop polling after the `expires_in` time (typically 30 minutes). -## Error codes +## Device authorization flow error codes | Error Code | Description | Action | | ----------------------- | ------------------------------------ | ------------------------------ | @@ -103,18 +101,18 @@ The device must poll the token endpoint at regular intervals until the user comp | `expired_token` | Device code has expired | Request a new device code | | `server_error` | Misconfigured device code | Request a new device code | -## Security considerations +## Security considerations for device authorization -- **User code format**: User codes are formatted as `XXXXXXXX` for easy entry -- **Verification URI**: Users should verify they're on the correct domain -- **Token expiration**: Access tokens expire after 1 hour by default +- **User code format**: User codes are formatted as `XXXXXXXX` for easy entry. +- **Verification URI**: Users should verify they're on the correct domain. +- **Token expiration**: Access tokens expire after 1 hour by default. -## Audience +## Specifying an audience in a device authorization request If an `audience` is specified in the request, the access token will include the audience in the `aud` claim. Kinde supports requesting multiple audiences. -The API must be authorized for the Device Authorization application. +The API must be authorized for the device authorization application. -## Scopes and permissions +## Scopes and permissions for a device authorization request If an audience is specified in the request, any scopes which are belong to that audience that are granted to the user by their role will also be granted to the device. The list of scopes will be displayed on the consent screen. If the user consents, the scopes will be included in the `scope` claim of the access token. From 2582b529064511842de47a9c5578e169fb05214b Mon Sep 17 00:00:00 2001 From: ClaireM <127452294+clairekinde11@users.noreply.github.com> Date: Tue, 5 Aug 2025 11:29:36 +1000 Subject: [PATCH 05/14] Title update --- .../docs/authenticate/device-authorization-flow/overview.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/authenticate/device-authorization-flow/overview.mdx b/src/content/docs/authenticate/device-authorization-flow/overview.mdx index 0c8bdfb6..5a878a92 100644 --- a/src/content/docs/authenticate/device-authorization-flow/overview.mdx +++ b/src/content/docs/authenticate/device-authorization-flow/overview.mdx @@ -1,6 +1,6 @@ --- page_id: ab3834cc-4645-4b7a-826a-c7f502eee3dd -title: Overview +title: Overview of the device authorization flow sidebar: order: 2 relatedArticles: From 9c592f10bc736b9392d35e5602a4d358e5bd6083 Mon Sep 17 00:00:00 2001 From: ClaireM <127452294+clairekinde11@users.noreply.github.com> Date: Tue, 5 Aug 2025 11:35:12 +1000 Subject: [PATCH 06/14] Claire more edits --- .../device-authorization-flow/quick-start.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/content/docs/authenticate/device-authorization-flow/quick-start.mdx b/src/content/docs/authenticate/device-authorization-flow/quick-start.mdx index e2bc789e..9cb3339e 100644 --- a/src/content/docs/authenticate/device-authorization-flow/quick-start.mdx +++ b/src/content/docs/authenticate/device-authorization-flow/quick-start.mdx @@ -8,11 +8,11 @@ relatedArticles: - 888b1546-8047-4609-af59-8cf859527aa0 --- -The Device Authorization Flow allows users to authenticate on one device (like a TV or smart device) using another device (like a phone or computer). This is perfect for devices with limited input capabilities. +The 'Device Authorization Flow' allows users to authenticate on one device (like a TV or smart device) using another device (like a phone or computer). This is perfect for devices with limited input capabilities. -In this quick start, you'll learn how to implement the Device Authorization Flow using Kinde in just 5 minutes. +In this quick start, you'll learn how to implement the device authorization flow using Kinde in just 5 minutes. -## Prerequisites +## Prerequisites for the device authorization flow - `curl` or a similar HTTP client @@ -95,9 +95,9 @@ curl -X GET https://your-api.com/protected-resource \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` -## Set an app as default +## Default app for device flows -You can set an application to be the default for device flows. This will be the application that is used if no Client ID is specified in the request. +When you set up a default app for device flows, this will be the application that is used if no Client ID is specified in the request. 1. Select **Settings** > **Applications** 2. Select the Device Authorization application you want to set as default From e1b3531edc5c32b04db8b2a754bf615bcdf4b921 Mon Sep 17 00:00:00 2001 From: ClaireM <127452294+clairekinde11@users.noreply.github.com> Date: Tue, 5 Aug 2025 11:39:02 +1000 Subject: [PATCH 07/14] Claire edits for headings and style --- .../device-authorization-flow/api-calls.mdx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/content/docs/authenticate/device-authorization-flow/api-calls.mdx b/src/content/docs/authenticate/device-authorization-flow/api-calls.mdx index 9faa05ce..9a110c4a 100644 --- a/src/content/docs/authenticate/device-authorization-flow/api-calls.mdx +++ b/src/content/docs/authenticate/device-authorization-flow/api-calls.mdx @@ -10,18 +10,18 @@ relatedArticles: - 1cbd91d2-c0b3-45b3-b038-319de1b2c794 --- -Once you've received an access token from the Device Authorization Flow, you can use it to call your protected APIs. This guide shows you how to validate tokens, handle scopes, and make authenticated API requests. +Once you've received an access token from the device authorization flow, you can use it to call your protected APIs. This guide shows you how to validate tokens, handle scopes, and make authenticated API requests. -## Using the access token +## Use the access token from the device authorization flow -The access token you receive from Device Authorization Flow is a standard OAuth 2.0 Bearer token. Include it in the `Authorization` header of your API requests: +The access token you receive from the device authorization flow is a standard OAuth 2.0 Bearer token. Include it in the `Authorization` header of your API requests: ```bash curl -X GET https://your-api.com/protected-resource \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` -## Token validation +## Token validation in the device authorization flow Before processing API requests, validate the access token to ensure it's valid and hasn't expired: @@ -83,7 +83,7 @@ function validateToken(token) { } ``` -## Scope enforcement +## Scope enforcement for device authorization Access tokens include scopes that determine what resources the user can access. Check the required scopes before processing requests: @@ -101,7 +101,7 @@ if (!hasRequiredScope(accessToken, "read:users")) { } ``` -## Common API patterns +## Common API patterns for device authorization ### Protected resource endpoint @@ -145,7 +145,7 @@ function authenticateToken(req, res, next) { } ``` -### Error handling +### Error handling for device authorization Handle common token-related errors: @@ -166,7 +166,7 @@ function handleTokenError(error) { } ``` -## Security best practices +## Security best practices for device authorization ### Token storage From d7459c07ce3e62a98487c6488e1a506eb1bb4689 Mon Sep 17 00:00:00 2001 From: ClaireM <127452294+clairekinde11@users.noreply.github.com> Date: Tue, 5 Aug 2025 11:42:12 +1000 Subject: [PATCH 08/14] Copyedit headings and style --- .../device-authorization-flow/troubleshooting.mdx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/content/docs/authenticate/device-authorization-flow/troubleshooting.mdx b/src/content/docs/authenticate/device-authorization-flow/troubleshooting.mdx index fdb38c5e..eebe047c 100644 --- a/src/content/docs/authenticate/device-authorization-flow/troubleshooting.mdx +++ b/src/content/docs/authenticate/device-authorization-flow/troubleshooting.mdx @@ -1,6 +1,6 @@ --- page_id: 545c511c-ce01-4251-be2a-d04407820d6f -title: Troubleshooting & common errors +title: Troubleshooting device authorization sidebar: order: 6 relatedArticles: @@ -9,9 +9,9 @@ relatedArticles: - de937e16-8094-4aad-ada9-e6a37d74f508 --- -This guide helps you diagnose and resolve common issues with Device Authorization Flow. Learn how to handle errors, debug problems, and implement proper error recovery. +This guide helps you diagnose and resolve common issues with device authorization flow. Learn how to handle errors, debug problems, and implement proper error recovery. -## Common error codes +## Common error codes during device authorization ### authorization_pending @@ -77,7 +77,7 @@ if (error === "expired_token") { } ``` -## Polling mistakes +## Polling mistakes during device authorization ### Too frequent polling @@ -103,7 +103,7 @@ function pollForToken(deviceCode) { } ``` -### Not handling slow_down properly +### Not handling `slow_down` properly **Problem**: Not increasing the interval when receiving `slow_down` errors. @@ -160,7 +160,7 @@ function pollForToken(deviceCode) { } ``` -## Network issues +## Network issues during device authorization ### Connection timeouts From 68cffa4225fd61a59e8468911bdf380ce1e4cbe8 Mon Sep 17 00:00:00 2001 From: ClaireM <127452294+clairekinde11@users.noreply.github.com> Date: Tue, 5 Aug 2025 12:03:45 +1000 Subject: [PATCH 09/14] Claire edits and updates --- .../about-m2m/m2m-quick-start-guide.mdx | 63 +++++++++---------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/src/content/docs/machine-to-machine-applications/about-m2m/m2m-quick-start-guide.mdx b/src/content/docs/machine-to-machine-applications/about-m2m/m2m-quick-start-guide.mdx index 9c588fff..43a76be6 100644 --- a/src/content/docs/machine-to-machine-applications/about-m2m/m2m-quick-start-guide.mdx +++ b/src/content/docs/machine-to-machine-applications/about-m2m/m2m-quick-start-guide.mdx @@ -1,6 +1,6 @@ --- page_id: 4cb63554-d6b3-45cf-bdad-2fac4790d3aa -title: Quick start +title: M2M quick start sidebar: order: 2 relatedArticles: @@ -11,55 +11,50 @@ relatedArticles: This guide shows you how to create a Machine-to-Machine (M2M) application in Kinde, authorize it for an API, and use the client credentials flow to get a token and make a secure API request. -## Step 1 - Create a machine-to-machine app +## Step 1: Create a machine-to-machine app -1. Go to the **Settings** > **Applications** section in your Kinde dashboard -2. Select **Add application** -3. Enter a name -4. Choose **Machine-to-machine (M2M)** -5. Select **Save** +1. On the Kinde home page, select **Add application**. +2. Enter a name for the application. +3. Choose **Machine-to-machine (M2M)**. +4. Select **Save**. -## Step 2 - Create an API in Kinde (if you don't have one) +## Step 2: Create an API in Kinde (if you don't have one) You can skip this step if you already have an API registered in Kinde. -1. Go to the **APIs** section in your Kinde dashboard -2. Select **Add API** -3. Enter a name -4. Select **Save** +1. Go to **Settings > APIs**. +2. Select **Add API**. +3. Enter a name for the API. +4. Select **Save**. -For more detail, see [Register and manage APIs](/developer-tools/your-apis/register-manage-apis/). +For details on the full API setup, see [Register and manage APIs](/developer-tools/your-apis/register-manage-apis/). -## Step 3 - Authorize the app to access an API - -1. Open your newly created app -2. Go to the **APIs** tab -3. Select the API (audience) this app should be allowed to call. -4. Select **Save**. +## Step 3: Authorize the app to access an API If you skip this step, token requests will be rejected. -## Step 4 - (Optional) Add scopes - -If your API uses scopes to define permissions: +1. Open the newly created M2M app. +2. Go to **APIs** in the menu. +3. Find the API you want to authorize in the list. +4. Select the three dots on the far right and select **Authorize**. -1. Go to **APIs** in your Kinde dashboard -2. Choose the API you’re protecting -3. Add scopes (e.g. `read:users`, `write:flags`) -4. Go back to your M2M app and assign those scopes +## Step 4: (Optional) Add scopes to define permissions -For more detail, see [Define and manage API scopes](/developer-tools/your-apis/api-scopes-m2m-applications/). +1. Go to **Settings > APIs**. +2. Choose the API you want to protect. +3. Select **Scopes** in the menu and add scopes (e.g. `read:users`, `write:flags`). +4. Once you are finished, open the M2M app and assign the scopes. See [Define and manage API scopes](/developer-tools/your-apis/api-scopes-m2m-applications/). -## Step 5 - Get a token +## Step 5: Get a token to test your M2M app You can test the app in one of two ways: -### Option A - Use the Test tab in Kinde +### Option A - Use the **Test** details in Kinde -1. Open your M2M app -2. Go to the **Test** tab -3. Select the API (audience) -4. Copy the generated token +1. Open your M2M app. +2. Go to **Test** in the menu. +3. Select the API (audience). +4. Copy the generated token. ### Option B - Use the client credentials flow directly @@ -83,7 +78,7 @@ The response will include a bearer token you can use in requests: } ``` -## Step 6 - Use the token in an API call +## Step 6: Use the token in an API call Include the token in the `Authorization` header: From da048a1129a2aa01b7084897e71c84642ee63aa3 Mon Sep 17 00:00:00 2001 From: ClaireM <127452294+clairekinde11@users.noreply.github.com> Date: Tue, 5 Aug 2025 12:04:47 +1000 Subject: [PATCH 10/14] Title update --- .../docs/authenticate/device-authorization-flow/overview.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/authenticate/device-authorization-flow/overview.mdx b/src/content/docs/authenticate/device-authorization-flow/overview.mdx index 5a878a92..b0df8a78 100644 --- a/src/content/docs/authenticate/device-authorization-flow/overview.mdx +++ b/src/content/docs/authenticate/device-authorization-flow/overview.mdx @@ -1,6 +1,6 @@ --- page_id: ab3834cc-4645-4b7a-826a-c7f502eee3dd -title: Overview of the device authorization flow +title: About the device authorization flow sidebar: order: 2 relatedArticles: From 3b0e8f63ab8722b8beffebe8992db2bc5dd4d362 Mon Sep 17 00:00:00 2001 From: ClaireM <127452294+clairekinde11@users.noreply.github.com> Date: Tue, 5 Aug 2025 12:20:28 +1000 Subject: [PATCH 11/14] Code rabbit suggestion --- .../docs/authenticate/device-authorization-flow/overview.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/content/docs/authenticate/device-authorization-flow/overview.mdx b/src/content/docs/authenticate/device-authorization-flow/overview.mdx index b0df8a78..32a50e3b 100644 --- a/src/content/docs/authenticate/device-authorization-flow/overview.mdx +++ b/src/content/docs/authenticate/device-authorization-flow/overview.mdx @@ -69,10 +69,12 @@ Kinde's device authorization flow adheres to `RFC 8628`, also known as the OAuth { "access_token": "eyJ...", "expires_in": 86400, - "scope": "", // granted scopes are in the access token + "scope": "", "token_type": "bearer" } ``` +The scope field may be empty because granted scopes are carried in the access token’s scope claim. + **Example error response**: From f23ce0f6badc6a7e3179f3f0b548fb07e18eee72 Mon Sep 17 00:00:00 2001 From: ClaireM <127452294+clairekinde11@users.noreply.github.com> Date: Tue, 5 Aug 2025 13:41:38 +1000 Subject: [PATCH 12/14] Update front matter --- .../about-m2m/m2m-quick-start-guide.mdx | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/content/docs/machine-to-machine-applications/about-m2m/m2m-quick-start-guide.mdx b/src/content/docs/machine-to-machine-applications/about-m2m/m2m-quick-start-guide.mdx index 43a76be6..073e0337 100644 --- a/src/content/docs/machine-to-machine-applications/about-m2m/m2m-quick-start-guide.mdx +++ b/src/content/docs/machine-to-machine-applications/about-m2m/m2m-quick-start-guide.mdx @@ -1,12 +1,37 @@ --- page_id: 4cb63554-d6b3-45cf-bdad-2fac4790d3aa title: M2M quick start +description: Step-by-step quick start guide for creating and using M2M applications in Kinde including API authorization, scope assignment, and token generation sidebar: order: 2 relatedArticles: - d2c841f1-78b4-47e0-b899-4d32ae857e0a - 961dea3c-d8e2-47a0-8ab7-deabdb2d6a01 - 65d72460-e870-4d6a-a1ea-35740ca0e2cc +topics: + - machine-to-machine-applications + - about-m2m +sdk: [] +languages: + - bash + - json +audience: + - developers + - admins +complexity: beginner +keywords: + - m2m quick start + - machine to machine + - api authorization + - client credentials + - scopes + - access tokens + - bearer token + - curl +updated: 2024-01-15 +featured: false +deprecated: false +ai_summary: Step-by-step quick start guide for creating and using M2M applications in Kinde including API authorization, scope assignment, and token generation. --- This guide shows you how to create a Machine-to-Machine (M2M) application in Kinde, authorize it for an API, and use the client credentials flow to get a token and make a secure API request. From 37de349cd19bff28dc4fd417a581fb5941a3d002 Mon Sep 17 00:00:00 2001 From: Dave Berner Date: Mon, 11 Aug 2025 20:54:19 +1000 Subject: [PATCH 13/14] fix: code samples --- .../device-authorization-flow/api-calls.mdx | 43 +++++++++++-------- .../device-authorization-flow/overview.mdx | 9 ++-- .../device-authorization-flow/quick-start.mdx | 3 +- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/content/docs/authenticate/device-authorization-flow/api-calls.mdx b/src/content/docs/authenticate/device-authorization-flow/api-calls.mdx index 9a110c4a..27ead53d 100644 --- a/src/content/docs/authenticate/device-authorization-flow/api-calls.mdx +++ b/src/content/docs/authenticate/device-authorization-flow/api-calls.mdx @@ -64,23 +64,32 @@ curl -X GET https://.kinde.com/oauth2/v2/user_profile \ You can also validate tokens in your own API by verifying the JWT signature and claims: ```javascript -// Node.js example using jsonwebtoken -const jwt = require("jsonwebtoken"); - -function validateToken(token) { - try { - const decoded = jwt.verify(token, "YOUR_JWT_SECRET"); - return { - valid: true, - user: decoded - }; - } catch (error) { - return { - valid: false, - error: error.message - }; - } -} ++// Node.js example using jsonwebtoken with JWKS ++const jwt = require("jsonwebtoken"); ++const jwksClient = require("jwks-rsa"); ++ ++const client = jwksClient({ ++ jwksUri: "https://.kinde.com/.well-known/jwks" ++}); ++ ++function getKey(header, callback) { ++ client.getSigningKey(header.kid, (err, key) => { ++ const signingKey = key.publicKey || key.rsaPublicKey; ++ callback(null, signingKey); ++ }); ++} ++ ++function validateToken(token) { ++ return new Promise((resolve, reject) => { ++ jwt.verify(token, getKey, { algorithms: ["RS256"] }, (err, decoded) => { ++ if (err) { ++ resolve({ valid: false, error: err.message }); ++ } else { ++ resolve({ valid: true, user: decoded }); ++ } ++ }); ++ }); ++} ``` ## Scope enforcement for device authorization diff --git a/src/content/docs/authenticate/device-authorization-flow/overview.mdx b/src/content/docs/authenticate/device-authorization-flow/overview.mdx index 32a50e3b..e3ed7fc7 100644 --- a/src/content/docs/authenticate/device-authorization-flow/overview.mdx +++ b/src/content/docs/authenticate/device-authorization-flow/overview.mdx @@ -31,7 +31,6 @@ Kinde's device authorization flow adheres to `RFC 8628`, also known as the OAuth **Parameters**: -- `grant_type`: `urn:ietf:params:oauth:grant-type:device_code` - `client_id` (optional): Your application's client ID - can be omitted if you have set an application as the default for device flows - `audience` (optional): The audience to use for the request @@ -69,12 +68,12 @@ Kinde's device authorization flow adheres to `RFC 8628`, also known as the OAuth { "access_token": "eyJ...", "expires_in": 86400, - "scope": "", + "scope": "", "token_type": "bearer" } ``` -The scope field may be empty because granted scopes are carried in the access token’s scope claim. +The scope field may be empty because granted scopes are carried in the access token’s scope claim. **Example error response**: @@ -109,12 +108,12 @@ The device must poll the token endpoint at regular intervals until the user comp - **Verification URI**: Users should verify they're on the correct domain. - **Token expiration**: Access tokens expire after 1 hour by default. -## Specifying an audience in a device authorization request +## Specifying an audience in a device authorization request If an `audience` is specified in the request, the access token will include the audience in the `aud` claim. Kinde supports requesting multiple audiences. The API must be authorized for the device authorization application. -## Scopes and permissions for a device authorization request +## Scopes and permissions for a device authorization request If an audience is specified in the request, any scopes which are belong to that audience that are granted to the user by their role will also be granted to the device. The list of scopes will be displayed on the consent screen. If the user consents, the scopes will be included in the `scope` claim of the access token. diff --git a/src/content/docs/authenticate/device-authorization-flow/quick-start.mdx b/src/content/docs/authenticate/device-authorization-flow/quick-start.mdx index 9cb3339e..e69e3f7d 100644 --- a/src/content/docs/authenticate/device-authorization-flow/quick-start.mdx +++ b/src/content/docs/authenticate/device-authorization-flow/quick-start.mdx @@ -38,8 +38,7 @@ Request a device code from Kinde's authorization endpoint: ```bash curl -X POST https://.kinde.com/oauth2/device/auth \ -H "Content-Type: application/x-www-form-urlencoded" \ - -d "client_id=" \ - -d "grant_type=urn:ietf:params:oauth:grant-type:device_code" + -d "client_id=" ``` The response will include a `device_code`, `user_code`, and `verification_uri`: From 4877d6b0f7c6bc53fc9cae72de81ee1abdf8311b Mon Sep 17 00:00:00 2001 From: Dave Berner Date: Tue, 12 Aug 2025 10:46:15 +1000 Subject: [PATCH 14/14] chore: add res --- .../docs/authenticate/device-authorization-flow/api-calls.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/authenticate/device-authorization-flow/api-calls.mdx b/src/content/docs/authenticate/device-authorization-flow/api-calls.mdx index 27ead53d..19bbbefd 100644 --- a/src/content/docs/authenticate/device-authorization-flow/api-calls.mdx +++ b/src/content/docs/authenticate/device-authorization-flow/api-calls.mdx @@ -159,7 +159,7 @@ function authenticateToken(req, res, next) { Handle common token-related errors: ```javascript -function handleTokenError(error) { +function handleTokenError(res, error) { switch (error.error) { case "invalid_token": // Token is invalid or expired