From 15d853b96c0ac318dd4ca515e812b41b72ac3802 Mon Sep 17 00:00:00 2001 From: Matt Jenkinson <75292329+mattdjenkinson@users.noreply.github.com> Date: Wed, 24 Jun 2026 16:58:18 +0100 Subject: [PATCH] fix: treat already-handled device authorization as success The /signedin page completes the device authorization flow during a Server Component render, which the App Router can evaluate more than once per navigation. The first call authorizes the grant; subsequent calls fail with FAILED_PRECONDITION ("Device Authorization Request has already been handled") and surfaced a spurious error even though login succeeded. Treat that error code as success so the flow is idempotent. Closes #89 --- apps/login/src/lib/server/device.ts | 31 +++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/apps/login/src/lib/server/device.ts b/apps/login/src/lib/server/device.ts index 5e36facfc8..a83f4f6e88 100644 --- a/apps/login/src/lib/server/device.ts +++ b/apps/login/src/lib/server/device.ts @@ -11,10 +11,29 @@ export async function completeDeviceAuthorization( const _headers = await headers(); const { serviceUrl } = getServiceUrlFromHeaders(_headers); - // without the session, device auth request is denied - return authorizeOrDenyDeviceAuthorization({ - serviceUrl, - deviceAuthorizationId, - session, - }); + try { + // without the session, device auth request is denied + return await authorizeOrDenyDeviceAuthorization({ + serviceUrl, + deviceAuthorizationId, + session, + }); + } catch (error) { + // The /signedin page completes the device flow during a Server Component + // render, which the App Router may evaluate more than once per navigation + // (RSC refetch, prefetch, refresh, retries). The first call authorizes the + // grant successfully; subsequent calls fail with FAILED_PRECONDITION + // ("Device Authorization Request has already been handled"). Treat that as + // success so the user isn't shown a spurious error after a working login. + if ( + error && + typeof error === "object" && + "code" in error && + error.code === 9 /* FAILED_PRECONDITION */ + ) { + return {}; + } + + throw error; + } }