Skip to content
  • Auth and access
  • Device authorization flow

Troubleshooting device authorization

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 during device authorization

Link to this section

authorization_pending

Link to this section

Error: authorization_pending Description: The user hasn’t completed the authorization process yet.

Solution: Continue polling the token endpoint. This is normal behavior.

// 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);
}

Error: slow_down Description: You’re polling too frequently.

Solution: Increase the polling interval by 5 seconds.

// 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);
}

Error: access_denied Description: The user denied the authorization request.

Solution: Stop polling and inform the user they need to try again.

// Example: Handle access_denied
if (error === "access_denied") {
console.log("User denied authorization");
showErrorMessage("Authorization was denied. Please try again.");
stopPolling();
}

Error: expired_token Description: The device code has expired (typically after 30 minutes).

Solution: Request a new device code.

// 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 during device authorization

Link to this section

Too frequent polling

Link to this section

Problem: Polling more frequently than the recommended interval.

Solution: Always respect the interval value from the device authorization response.

// 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

Link to this section

Problem: Not increasing the interval when receiving slow_down errors.

Solution: Implement exponential backoff.

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

Link to this section

Problem: Continuing to poll after receiving fatal errors.

Solution: Stop polling for non-recoverable errors.

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 during device authorization

Link to this section

Connection timeouts

Link to this section

Problem: Network requests timing out.

Solution: Implement proper timeout handling and retry logic.

function checkTokenStatus(deviceCode) {
return fetch("https://<your-subdomain>.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: "<YOUR_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

Link to this section

Problem: Cannot resolve the Kinde domain.

Solution: Verify your domain configuration and network connectivity.

Terminal window
# Test DNS resolution
nslookup <your-subdomain>.kinde.com
# Test connectivity
curl -I https://<your-subdomain>.kinde.com/oauth2/v2/device_authorization