import * as http from 'http'; import { TokenData } from '../types'; export declare const PRIMARY_PORT = 8080; export declare const PORT_RANGE_SIZE = 20; /** * Bind an HTTP server to the first available port in * PRIMARY_PORT..PRIMARY_PORT+PORT_RANGE_SIZE-1. * * Retries at the `.listen()` level (no separate probe) to avoid TOCTOU races. * Installs a persistent post-bind error listener to prevent process crash on * later server errors (e.g., EMFILE during connection accept). * * @param handler - the request handler * @returns { server, port } once the server is successfully listening * @throws Error with code='EADDRINUSE_ALL' if ALL ports in range are in use * @throws Original error if a non-EADDRINUSE error fires (EACCES, etc.) * * Callers MUST wrap this in try/catch to fire the appropriate auth-failure * beacon BEFORE rejecting — otherwise the outer auth-cli fallback downgrades * the failure to `unknown` and we lose port_range_exhausted telemetry. */ export declare function bindOAuthServer(handler: http.RequestListener): Promise<{ server: http.Server; port: number; }>; /** * Authentication service for OAuth flows */ export declare class AuthService { private static instance; private constructor(); static getInstance(): AuthService; /** * Open URL in the user's default browser. Cross-platform: macOS, Linux, * WSL, Windows. Always prints the URL to stderr first as a fallback — * if no browser-opening command is available, the user can copy-paste. * (stderr, not stdout, because install.sh's auth stage discards stdout * via `2>&1 >/dev/null`. See body comment.) * * On WSL, prefers opening the Windows host browser via WSL interop * (wslview → cmd.exe → powershell.exe) before falling back to xdg-open. */ private openBrowser; /** * Returns the list of browser-opening commands to try in order, based on * the current platform. On WSL, returns WSL interop commands first so the * Windows browser opens (which is what users actually want on WSL). */ private getBrowserCommands; /** * Detect whether we're running inside WSL (1 or 2). Returns false on * any non-Linux platform or if /proc/sys/kernel/osrelease is not readable. */ private isRunningInWSL; /** * Try each browser-opening command in order. Advances to the next fallback on: * - Spawn failure (ENOENT / the command not being installed) * - Synchronous throw from spawn() * - Runtime failure where the command spawns but exits with a non-zero * code (e.g. wslview when WSL interop is disabled, xdg-open when no * default browser is registered, cmd.exe failing to launch start) * - Process terminated by signal * * Stays on the current command when: * - Process exits with code 0 (success) * - Process is still running after 3 seconds (assumed success — opener * is doing real work like launching a slow app, not hung) * * If all attempts exhaust, logs at debug level — the user still has the * sign-in URL printed to stderr above as a copy-paste fallback. */ private tryBrowserCommand; /** * Generate state for CSRF protection */ private generateState; /** * Build authorization URL with dynamic redirect_uri (port-range fix). */ private buildAuthUrl; /** * Exchange authorization code for tokens. * * `redirectUri` MUST match the one passed to buildAuthUrl earlier — Cognito * compares them at the token endpoint and rejects mismatches. This is the * load-bearing change for the port-range fix to work end-to-end: if the * authorize URL used port 8081 and the token POST uses 8080, Cognito * returns redirect_uri_mismatch. */ private exchangeCodeForTokens; /** * Decode JWT payload */ private decodeJwt; /** * Refresh tokens */ refreshTokens(refreshToken: string): Promise<{ accessToken: string; idToken: string; expiresIn: number; }>; /** * Login via OAuth browser flow */ login(): Promise; /** * Logout */ logout(): Promise; /** * Get current auth status */ getStatus(): Promise<{ authenticated: boolean; tokens?: TokenData; }>; } export declare const authService: AuthService;