UNPKG

@analog-tools/auth

Version:
125 lines (124 loc) 4.15 kB
import { H3Event } from 'h3'; import { AnalogAuthConfig } from '../types/auth.types'; /** * Service for handling OAuth authentication in a Backend-for-Frontend pattern */ export declare class OAuthAuthenticationService { private logger; private inflightRefreshes; constructor(config: AnalogAuthConfig); private readonly config; private openIDConfigCache; private configLastFetched; private readonly CONFIG_CACHE_TTL; private TOKEN_REFRESH_SAFETY_MARGIN; private normalizedWhitelistExtensions; private jwks?; private jwksUri?; /** * Validate that the service has been properly initialized * @throws Error if mandatory configuration is missing */ private validateConfiguration; /** * Initialize session for the request */ initSession(event: H3Event): Promise<void>; getConfig(): AnalogAuthConfig; /** * Safely access a configuration value * @param key The configuration key to retrieve * @param fallbackValue Optional fallback value if the config value doesn't exist * @returns The configuration value or fallback value * @throws Error if the configuration value doesn't exist and no fallback is provided */ getConfigValue<K extends keyof AnalogAuthConfig>(key: K, fallbackValue?: AnalogAuthConfig[K]): AnalogAuthConfig[K]; /** * Check if the route is unprotected * @param path The request path * @returns True if the route is unprotected, false otherwise */ isUnprotectedRoute(path: string): boolean; /** * Get OAuth authorization URL for login */ getAuthorizationUrl(params: { state: string; codeChallenge: string; nonce: string; redirectUri?: string; }): Promise<string>; /** * Exchange authorization code for tokens */ private exchangeCodeForTokens; /** * Refresh access token using refresh token */ private refreshTokens; private refreshTokensDeduped; /** * Get user info from OAuth provider with improved error handling and retry logic */ private getUserInfo; /** * Verify an OIDC ID token: signature (via the provider's JWKS), `iss`, `aud`, * `exp`/`nbf`, the per-login `nonce`, `azp` (when present), and — when the * provider sends it — `at_hash` binding the token to `accessToken`. Returns * the verified claims * so the caller can anchor identity in the cryptographically validated token. */ private validateIdToken; /** * Handle OAuth callback */ handleCallback(event: H3Event, code: string, state: string): Promise<{ user: any; tokens: any; }>; private resolveUserIdentity; private resolveSessionIdentity; private invalidateOtherUserSessions; /** * Calculate if token needs refresh based on safety margin * @param expiresAt Timestamp when token expires * @returns True if token should be refreshed */ private shouldRefreshToken; /** * Serverless-compatible method to refresh expiring tokens * This should be called by a scheduled function/CRON job * rather than using setInterval which doesn't work reliably in serverless */ refreshExpiringTokens(): Promise<{ refreshed: number; failed: number; total: number; }>; /** * Check if user is authenticated */ isAuthenticated(event: H3Event): Promise<boolean>; /** * Get authenticated user */ getAuthenticatedUser(event: H3Event): Promise<any>; /** * Revoke an access token */ private revokeToken; /** * Logout user */ logout(event: H3Event): Promise<string>; /** * Fetch OpenID Configuration from the well-known endpoint */ private getOpenIDConfiguration; /** * Validate a fetched OpenID configuration before trusting its endpoints: * the document's `issuer` must match the configured issuer (OIDC Discovery * §4.3), and every advertised endpoint we use must be https (localhost aside). */ private assertTrustedOpenIDConfiguration; }