import { CALLBACK_PATH, CALLBACK_TIMEOUT_MS } from './config.ts'; const SUCCESS_HTML = ` Logged in

You're logged in to Oriyn.

You can close this tab and return to your terminal.

`; const errorHtml = (message: string): string => ` Login failed

Login failed

${message.replace(/[<>&]/g, '')}

`; export interface CallbackResult { code: string; state: string; } export interface CallbackHandle { port: number; redirectUri: string; result: Promise; close: () => void; } export const startCallbackServer = (input: { expectedState: string }): CallbackHandle => { let resolve!: (value: CallbackResult) => void; let reject!: (err: Error) => void; const result = new Promise((res, rej) => { resolve = res; reject = rej; }); const server = Bun.serve({ hostname: '127.0.0.1', port: 0, fetch(req) { const url = new URL(req.url); if (url.pathname !== CALLBACK_PATH) { return new Response('Not found', { status: 404 }); } const error = url.searchParams.get('error'); if (error) { const description = url.searchParams.get('error_description') ?? error; reject(new Error(`OAuth provider returned error: ${description}`)); return new Response(errorHtml(description), { status: 400, headers: { 'content-type': 'text/html; charset=utf-8' }, }); } const code = url.searchParams.get('code'); const state = url.searchParams.get('state'); if (!code || !state) { reject(new Error('OAuth callback missing code or state')); return new Response(errorHtml('Missing code or state.'), { status: 400, headers: { 'content-type': 'text/html; charset=utf-8' }, }); } if (state !== input.expectedState) { reject(new Error('OAuth state mismatch (possible CSRF attempt)')); return new Response(errorHtml('State mismatch.'), { status: 400, headers: { 'content-type': 'text/html; charset=utf-8' }, }); } resolve({ code, state }); return new Response(SUCCESS_HTML, { status: 200, headers: { 'content-type': 'text/html; charset=utf-8' }, }); }, }); const timeout = setTimeout(() => { reject(new Error('Login timed out waiting for browser callback')); }, CALLBACK_TIMEOUT_MS); const close = () => { clearTimeout(timeout); server.stop(); }; // Auto-close after either resolution or rejection. result.finally(close).catch(() => {}); const port = server.port; if (port == null) { close(); throw new Error('Failed to bind callback server'); } return { port, redirectUri: `http://127.0.0.1:${port}${CALLBACK_PATH}`, result, close, }; };