UNPKG

@frank-auth/react

Version:

Flexible and customizable React UI components for Frank Authentication

1 lines 29.6 kB
{"version":3,"file":"redirect-handler.cjs","sources":["../../../../../src/components/auth/common/redirect-handler.tsx"],"sourcesContent":["/**\n * @frank-auth/react - Redirect Handler Component\n *\n * Handles authentication redirects for OAuth, magic links, invitations,\n * and other authentication flows with proper state management.\n */\n\n'use client';\n\nimport React from 'react';\nimport {motion} from 'framer-motion';\nimport {useOAuth} from '../../../hooks/use-oauth';\nimport {useMagicLink} from '../../../hooks/use-magic-link';\nimport {useOrganization} from '../../../hooks/use-organization';\nimport {LoadingSpinner} from './loading-spinner';\nimport {ErrorBoundary} from './error-boundary';\n\n// ============================================================================\n// Redirect Handler Types\n// ============================================================================\n\nexport interface RedirectHandlerProps {\n /**\n * Redirect type to handle\n */\n type?: 'oauth' | 'magic-link' | 'invitation' | 'verification' | 'auto';\n\n /**\n * Success redirect URL\n */\n successUrl?: string;\n\n /**\n * Error redirect URL\n */\n errorUrl?: string;\n\n /**\n * Callback after successful redirect\n */\n onSuccess?: (result: any) => void;\n\n /**\n * Callback after failed redirect\n */\n onError?: (error: Error) => void;\n\n /**\n * Custom loading component\n */\n loadingComponent?: React.ReactNode;\n\n /**\n * Custom error component\n */\n errorComponent?: React.ComponentType<{ error: Error; retry: () => void }>;\n\n /**\n * Whether to show loading state\n */\n showLoading?: boolean;\n\n /**\n * Loading text\n */\n loadingText?: string;\n\n /**\n * Custom className\n */\n className?: string;\n\n /**\n * Children to render instead of default handling\n */\n children?: React.ReactNode;\n}\n\n// ============================================================================\n// URL Parameter Extraction\n// ============================================================================\n\nfunction getUrlParams(): URLSearchParams {\n if (typeof window === 'undefined') return new URLSearchParams();\n return new URLSearchParams(window.location.search);\n}\n\nfunction getUrlHash(): URLSearchParams {\n if (typeof window === 'undefined') return new URLSearchParams();\n const hash = window.location.hash;\n return new URLSearchParams(hash.startsWith('#') ? hash.slice(1) : hash);\n}\n\nfunction getAllParams(): URLSearchParams {\n const params = getUrlParams();\n const hashParams = getUrlHash();\n\n // Merge hash params into query params\n hashParams.forEach((value, key) => {\n if (!params.has(key)) {\n params.set(key, value);\n }\n });\n\n return params;\n}\n\n// ============================================================================\n// Redirect Type Detection\n// ============================================================================\n\nfunction detectRedirectType(): string | null {\n const params = getAllParams();\n\n // OAuth callback detection\n if (params.has('code') && params.has('state')) {\n return 'oauth';\n }\n\n // Magic link detection\n if (params.has('token') && params.has('type')) {\n const type = params.get('type');\n if (type === 'magic_link' || type === 'email_verification') {\n return 'magic-link';\n }\n }\n\n // Invitation detection\n if (params.has('invitation_token') || params.has('invite')) {\n return 'invitation';\n }\n\n // Verification detection\n if (params.has('verification_token') || params.has('verify')) {\n return 'verification';\n }\n\n // Error detection\n if (params.has('error') || params.has('error_description')) {\n return 'error';\n }\n\n return null;\n}\n\n// ============================================================================\n// OAuth Redirect Handler\n// ============================================================================\n\nfunction OAuthRedirectHandler({\n onSuccess,\n onError,\n successUrl,\n errorUrl\n }: {\n onSuccess?: (result: any) => void;\n onError?: (error: Error) => void;\n successUrl?: string;\n errorUrl?: string;\n}) {\n const { handleCallback } = useOAuth();\n const [isProcessing, setIsProcessing] = React.useState(true);\n const [error, setError] = React.useState<Error | null>(null);\n\n React.useEffect(() => {\n const processOAuthCallback = async () => {\n try {\n const params = getAllParams();\n const code = params.get('code');\n const state = params.get('state');\n const provider = params.get('provider') || 'google';\n const errorParam = params.get('error');\n\n if (errorParam) {\n const errorDescription = params.get('error_description') || 'OAuth authentication failed';\n throw new Error(`OAuth Error: ${errorParam} - ${errorDescription}`);\n }\n\n if (!code) {\n throw new Error('No authorization code received from OAuth provider');\n }\n\n const result = await handleCallback(provider, code, state);\n\n if (result.success) {\n onSuccess?.(result);\n\n // Redirect to success URL\n if (successUrl) {\n window.location.href = successUrl;\n } else {\n // Clean up URL and redirect to dashboard\n window.history.replaceState({}, document.title, window.location.pathname);\n window.location.href = '/dashboard';\n }\n } else {\n throw new Error(result.error || 'OAuth authentication failed');\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error('OAuth processing failed');\n setError(error);\n onError?.(error);\n\n // Redirect to error URL\n if (errorUrl) {\n setTimeout(() => {\n window.location.href = errorUrl;\n }, 3000);\n }\n } finally {\n setIsProcessing(false);\n }\n };\n\n processOAuthCallback();\n }, [handleCallback, onSuccess, onError, successUrl, errorUrl]);\n\n if (error) {\n return (\n <div className=\"text-center\">\n <div className=\"text-danger-600 mb-4\">\n <svg className=\"w-12 h-12 mx-auto mb-2\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.732 16.5c-.77.833.192 2.5 1.732 2.5z\" />\n </svg>\n <h3 className=\"text-lg font-semibold\">Authentication Failed</h3>\n <p className=\"text-sm text-default-500 mt-2\">{error.message}</p>\n </div>\n {errorUrl && (\n <p className=\"text-xs text-default-400\">\n Redirecting to sign in page...\n </p>\n )}\n </div>\n );\n }\n\n return (\n <LoadingSpinner\n variant=\"spinner\"\n size=\"lg\"\n showText\n text=\"Completing sign in...\"\n centered\n />\n );\n}\n\n// ============================================================================\n// Magic Link Redirect Handler\n// ============================================================================\n\nfunction MagicLinkRedirectHandler({\n onSuccess,\n onError,\n successUrl,\n errorUrl\n }: {\n onSuccess?: (result: any) => void;\n onError?: (error: Error) => void;\n successUrl?: string;\n errorUrl?: string;\n}) {\n const { verifyFromUrl } = useMagicLink();\n const [isProcessing, setIsProcessing] = React.useState(true);\n const [error, setError] = React.useState<Error | null>(null);\n\n React.useEffect(() => {\n const processMagicLink = async () => {\n try {\n const result = await verifyFromUrl();\n\n if (result.success) {\n onSuccess?.(result);\n\n // Handle MFA requirement\n if (result.requiresAdditionalVerification) {\n const params = new URLSearchParams();\n params.set('mfa_token', result.mfaToken || '');\n window.location.href = `/auth/mfa?${params.toString()}`;\n return;\n }\n\n // Redirect to success URL\n if (successUrl) {\n window.location.href = successUrl;\n } else {\n // Clean up URL and redirect\n window.history.replaceState({}, document.title, window.location.pathname);\n window.location.href = '/dashboard';\n }\n } else {\n throw new Error(result.error || 'Magic link verification failed');\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Magic link processing failed');\n setError(error);\n onError?.(error);\n\n // Redirect to error URL\n if (errorUrl) {\n setTimeout(() => {\n window.location.href = errorUrl;\n }, 3000);\n }\n } finally {\n setIsProcessing(false);\n }\n };\n\n processMagicLink();\n }, [verifyFromUrl, onSuccess, onError, successUrl, errorUrl]);\n\n if (error) {\n return (\n <div className=\"text-center\">\n <div className=\"text-danger-600 mb-4\">\n <svg className=\"w-12 h-12 mx-auto mb-2\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.732 16.5c-.77.833.192 2.5 1.732 2.5z\" />\n </svg>\n <h3 className=\"text-lg font-semibold\">Verification Failed</h3>\n <p className=\"text-sm text-default-500 mt-2\">{error.message}</p>\n </div>\n {errorUrl && (\n <p className=\"text-xs text-default-400\">\n Redirecting to sign in page...\n </p>\n )}\n </div>\n );\n }\n\n return (\n <LoadingSpinner\n variant=\"pulse\"\n size=\"lg\"\n showText\n text=\"Verifying magic link...\"\n centered\n />\n );\n}\n\n// ============================================================================\n// Invitation Redirect Handler\n// ============================================================================\n\nfunction InvitationRedirectHandler({\n onSuccess,\n onError,\n successUrl,\n errorUrl\n }: {\n onSuccess?: (result: any) => void;\n onError?: (error: Error) => void;\n successUrl?: string;\n errorUrl?: string;\n}) {\n const { acceptInvitation } = useOrganization();\n const [isProcessing, setIsProcessing] = React.useState(true);\n const [error, setError] = React.useState<Error | null>(null);\n\n React.useEffect(() => {\n const processInvitation = async () => {\n try {\n const params = getAllParams();\n const invitationToken = params.get('invitation_token') || params.get('invite');\n\n if (!invitationToken) {\n throw new Error('No invitation token found');\n }\n\n await acceptInvitation(invitationToken);\n\n onSuccess?.({ invitationToken });\n\n // Redirect to success URL\n if (successUrl) {\n window.location.href = successUrl;\n } else {\n // Clean up URL and redirect\n window.history.replaceState({}, document.title, window.location.pathname);\n window.location.href = '/dashboard';\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Invitation processing failed');\n setError(error);\n onError?.(error);\n\n // Redirect to error URL\n if (errorUrl) {\n setTimeout(() => {\n window.location.href = errorUrl;\n }, 3000);\n }\n } finally {\n setIsProcessing(false);\n }\n };\n\n processInvitation();\n }, [acceptInvitation, onSuccess, onError, successUrl, errorUrl]);\n\n if (error) {\n return (\n <div className=\"text-center\">\n <div className=\"text-danger-600 mb-4\">\n <svg className=\"w-12 h-12 mx-auto mb-2\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.732 16.5c-.77.833.192 2.5 1.732 2.5z\" />\n </svg>\n <h3 className=\"text-lg font-semibold\">Invitation Failed</h3>\n <p className=\"text-sm text-default-500 mt-2\">{error.message}</p>\n </div>\n {errorUrl && (\n <p className=\"text-xs text-default-400\">\n Redirecting to sign in page...\n </p>\n )}\n </div>\n );\n }\n\n return (\n <LoadingSpinner\n variant=\"dots\"\n size=\"lg\"\n showText\n text=\"Processing invitation...\"\n centered\n />\n );\n}\n\n// ============================================================================\n// Main Redirect Handler Component\n// ============================================================================\n\nexport function RedirectHandler({\n type = 'auto',\n successUrl,\n errorUrl,\n onSuccess,\n onError,\n loadingComponent,\n errorComponent: ErrorComponent,\n showLoading = true,\n loadingText = 'Processing...',\n className = '',\n children,\n }: RedirectHandlerProps) {\n // Auto-detect redirect type if not specified\n const detectedType = type === 'auto' ? detectRedirectType() : type;\n\n // If no redirect type detected and no children, don't render anything\n if (!detectedType && !children) {\n return null;\n }\n\n // Render children if provided\n if (children) {\n return <div className={className}>{children}</div>;\n }\n\n // Default loading component\n const defaultLoading = showLoading ? (\n loadingComponent || (\n <div className=\"flex items-center justify-center min-h-64\">\n <LoadingSpinner\n variant=\"spinner\"\n size=\"lg\"\n showText\n text={loadingText}\n centered\n />\n </div>\n )\n ) : null;\n\n // Render appropriate handler based on type\n const renderHandler = () => {\n switch (detectedType) {\n case 'oauth':\n return (\n <OAuthRedirectHandler\n onSuccess={onSuccess}\n onError={onError}\n successUrl={successUrl}\n errorUrl={errorUrl}\n />\n );\n\n case 'magic-link':\n return (\n <MagicLinkRedirectHandler\n onSuccess={onSuccess}\n onError={onError}\n successUrl={successUrl}\n errorUrl={errorUrl}\n />\n );\n\n case 'invitation':\n return (\n <InvitationRedirectHandler\n onSuccess={onSuccess}\n onError={onError}\n successUrl={successUrl}\n errorUrl={errorUrl}\n />\n );\n\n case 'error':\n const params = getAllParams();\n const errorMessage = params.get('error_description') || params.get('error') || 'An error occurred';\n const error = new Error(errorMessage);\n\n if (ErrorComponent) {\n return <ErrorComponent error={error} retry={() => window.location.reload()} />;\n }\n\n return (\n <div className=\"text-center\">\n <div className=\"text-danger-600 mb-4\">\n <svg className=\"w-12 h-12 mx-auto mb-2\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.732 16.5c-.77.833.192 2.5 1.732 2.5z\" />\n </svg>\n <h3 className=\"text-lg font-semibold\">Authentication Error</h3>\n <p className=\"text-sm text-default-500 mt-2\">{errorMessage}</p>\n </div>\n {errorUrl && (\n <p className=\"text-xs text-default-400\">\n Redirecting to sign in page...\n </p>\n )}\n </div>\n );\n\n default:\n return defaultLoading;\n }\n };\n\n return (\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n className={`${className}`}\n >\n <ErrorBoundary\n title=\"Redirect Processing Error\"\n subtitle=\"There was a problem processing the authentication redirect.\"\n onError={onError}\n showDetails={process.env.NODE_ENV === 'development'}\n >\n {renderHandler()}\n </ErrorBoundary>\n </motion.div>\n );\n}\n\n// ============================================================================\n// Redirect Handler Hook\n// ============================================================================\n\nexport function useRedirectHandler() {\n const [redirectType, setRedirectType] = React.useState<string | null>(null);\n const [isProcessing, setIsProcessing] = React.useState(false);\n const [error, setError] = React.useState<Error | null>(null);\n\n React.useEffect(() => {\n const type = detectRedirectType();\n setRedirectType(type);\n setIsProcessing(!!type);\n }, []);\n\n const handleSuccess = React.useCallback((result: any) => {\n setIsProcessing(false);\n setError(null);\n }, []);\n\n const handleError = React.useCallback((error: Error) => {\n setIsProcessing(false);\n setError(error);\n }, []);\n\n return {\n redirectType,\n isProcessing,\n error,\n handleSuccess,\n handleError,\n hasRedirect: !!redirectType,\n };\n}\n\n// ============================================================================\n// Export\n// ============================================================================\n\nexport default RedirectHandler;"],"names":["getUrlParams","getUrlHash","hash","getAllParams","params","value","key","detectRedirectType","type","OAuthRedirectHandler","onSuccess","onError","successUrl","errorUrl","handleCallback","useOAuth","isProcessing","setIsProcessing","React","error","setError","code","state","provider","errorParam","errorDescription","result","err","jsxs","jsx","LoadingSpinner","MagicLinkRedirectHandler","verifyFromUrl","useMagicLink","InvitationRedirectHandler","acceptInvitation","useOrganization","invitationToken","RedirectHandler","loadingComponent","ErrorComponent","showLoading","loadingText","className","children","detectedType","defaultLoading","renderHandler","errorMessage","motion","ErrorBoundary","useRedirectHandler","redirectType","setRedirectType","handleSuccess","handleError","redirect_handler_default"],"mappings":"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"}