export enum AuthErrorType { REDIRECT_FAILED = 'REDIRECT_FAILED', CALLBACK_FAILED = 'CALLBACK_FAILED', NETWORK_ERROR = 'NETWORK_ERROR', USER_CANCELLED = 'USER_CANCELLED', } export interface AuthError { type: AuthErrorType; message: string; retryable: boolean; } export function parseOidcError(error: unknown): AuthError { const errorMessage = error instanceof Error ? error.message : String(error); const errorString = errorMessage.toLowerCase(); // Check for popup/redirect blocked errors if (errorString.includes('popup') || errorString.includes('blocked') || errorString.includes('window')) { return { type: AuthErrorType.REDIRECT_FAILED, message: 'Unable to redirect. Please check if popups are blocked.', retryable: true, }; } // Check for user cancellation if (errorString.includes('cancel') || errorString.includes('closed') || errorString.includes('denied')) { return { type: AuthErrorType.USER_CANCELLED, message: 'Sign in was cancelled.', retryable: true, }; } // Check for network errors if (errorString.includes('network') || errorString.includes('fetch') || errorString.includes('timeout') || errorString.includes('failed to fetch')) { return { type: AuthErrorType.NETWORK_ERROR, message: 'Unable to reach authentication server. Please check your connection.', retryable: true, }; } // Check for callback/state errors if (errorString.includes('state') || errorString.includes('invalid') || errorString.includes('mismatch') || errorString.includes('no matching state')) { return { type: AuthErrorType.CALLBACK_FAILED, message: 'Login verification failed. Please try again.', retryable: true, }; } // Default error return { type: AuthErrorType.CALLBACK_FAILED, message: errorMessage || 'An unexpected error occurred during sign in.', retryable: true, }; }