From b9599f2a19819fb2b2711ee8dcf44ac61b7dadb2 Mon Sep 17 00:00:00 2001 From: JunghwanNA <70629228+shaun0927@users.noreply.github.com> Date: Sat, 18 Apr 2026 00:44:34 +0900 Subject: [PATCH] Prevent false OAuth success pages before callback validation completes The callback server was acknowledging success before the asynchronous validation/token-exchange path had actually finished, which could leave users looking at a success page while the flow failed in an unhandled rejection. The handler now awaits callback completion and returns an error page when callback processing fails. Constraint: Needs to remain compatible with the existing full-callback-URL OAuth flow added in prior fixes Rejected: Catch-and-log callback errors without changing the response body | preserves the misleading success UX and hides failure state from users Confidence: high Scope-risk: narrow Reversibility: clean Directive: Keep the auth callback response coupled to actual callback completion; do not move async failures back onto an unobserved path Tested: pnpm install; pnpm run deps; apps/main npm run build; source-backed auth callback failure validation JSON Not-tested: Live provider OAuth round-trip against real credentials --- apps/x/apps/main/src/auth-server.ts | 67 +++++++++++++++++++---------- 1 file changed, 45 insertions(+), 22 deletions(-) diff --git a/apps/x/apps/main/src/auth-server.ts b/apps/x/apps/main/src/auth-server.ts index ad184451..d2be7e82 100644 --- a/apps/x/apps/main/src/auth-server.ts +++ b/apps/x/apps/main/src/auth-server.ts @@ -29,7 +29,7 @@ export function createAuthServer( onCallback: (callbackUrl: URL) => void | Promise ): Promise { return new Promise((resolve, reject) => { - const server = createServer((req, res) => { + const server = createServer(async (req, res) => { if (!req.url) { res.writeHead(400); res.end('Bad Request'); @@ -64,27 +64,51 @@ export function createAuthServer( return; } - // Handle callback - pass full URL so params like iss (OpenID Connect) are preserved for token exchange - onCallback(url); + try { + // Handle callback - pass full URL so params like iss (OpenID Connect) + // are preserved for token exchange. + await onCallback(url); - res.writeHead(200, { 'Content-Type': 'text/html' }); - res.end(` - - - - Authorization Successful - - - -

Authorization Successful

-

You can close this window.

- - - - `); + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end(` + + + + Authorization Successful + + + +

Authorization Successful

+

You can close this window.

+ + + + `); + } catch (callbackError) { + const message = callbackError instanceof Error ? callbackError.message : String(callbackError); + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end(` + + + + OAuth Error + + + +

Authorization Failed

+

Error: ${escapeHtml(message)}

+

You can close this window.

+ + + + `); + } } else { res.writeHead(404); res.end('Not Found'); @@ -104,4 +128,3 @@ export function createAuthServer( }); }); } -