@tern-secure/nextjs 4.2.2 → 4.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/app-router/admin/sessionTernSecure.js +29 -25
- package/dist/cjs/app-router/admin/sessionTernSecure.js.map +1 -1
- package/dist/cjs/components/sign-in.js +3 -0
- package/dist/cjs/components/sign-in.js.map +1 -1
- package/dist/cjs/server/auth.js +59 -44
- package/dist/cjs/server/auth.js.map +1 -1
- package/dist/cjs/server/crypto.js +43 -0
- package/dist/cjs/server/crypto.js.map +1 -0
- package/dist/cjs/server/ctx-store.js +65 -0
- package/dist/cjs/server/ctx-store.js.map +1 -0
- package/dist/cjs/server/edge-session.js +23 -19
- package/dist/cjs/server/edge-session.js.map +1 -1
- package/dist/cjs/server/index.js +0 -2
- package/dist/cjs/server/index.js.map +1 -1
- package/dist/cjs/server/jwt-edge.js +0 -9
- package/dist/cjs/server/jwt-edge.js.map +1 -1
- package/dist/cjs/server/jwt.js +0 -10
- package/dist/cjs/server/jwt.js.map +1 -1
- package/dist/cjs/server/session-store.js +72 -0
- package/dist/cjs/server/session-store.js.map +1 -0
- package/dist/cjs/server/ternSecureMiddleware.js +25 -53
- package/dist/cjs/server/ternSecureMiddleware.js.map +1 -1
- package/dist/cjs/server/types.js.map +1 -1
- package/dist/cjs/server/utils.js +108 -0
- package/dist/cjs/server/utils.js.map +1 -0
- package/dist/esm/app-router/admin/sessionTernSecure.js +29 -25
- package/dist/esm/app-router/admin/sessionTernSecure.js.map +1 -1
- package/dist/esm/components/sign-in.js +3 -0
- package/dist/esm/components/sign-in.js.map +1 -1
- package/dist/esm/server/auth.js +57 -43
- package/dist/esm/server/auth.js.map +1 -1
- package/dist/esm/server/crypto.js +18 -0
- package/dist/esm/server/crypto.js.map +1 -0
- package/dist/esm/server/ctx-store.js +41 -0
- package/dist/esm/server/ctx-store.js.map +1 -0
- package/dist/esm/server/edge-session.js +23 -19
- package/dist/esm/server/edge-session.js.map +1 -1
- package/dist/esm/server/index.js +1 -2
- package/dist/esm/server/index.js.map +1 -1
- package/dist/esm/server/jwt-edge.js +0 -9
- package/dist/esm/server/jwt-edge.js.map +1 -1
- package/dist/esm/server/jwt.js +0 -10
- package/dist/esm/server/jwt.js.map +1 -1
- package/dist/esm/server/session-store.js +47 -0
- package/dist/esm/server/session-store.js.map +1 -0
- package/dist/esm/server/ternSecureMiddleware.js +25 -52
- package/dist/esm/server/ternSecureMiddleware.js.map +1 -1
- package/dist/esm/server/utils.js +84 -0
- package/dist/esm/server/utils.js.map +1 -0
- package/dist/types/app-router/admin/sessionTernSecure.d.ts +9 -10
- package/dist/types/app-router/admin/sessionTernSecure.d.ts.map +1 -1
- package/dist/types/components/sign-in.d.ts.map +1 -1
- package/dist/types/server/auth.d.ts +8 -4
- package/dist/types/server/auth.d.ts.map +1 -1
- package/dist/types/server/crypto.d.ts +3 -0
- package/dist/types/server/crypto.d.ts.map +1 -0
- package/dist/types/server/ctx-store.d.ts +24 -0
- package/dist/types/server/ctx-store.d.ts.map +1 -0
- package/dist/types/server/edge-session.d.ts.map +1 -1
- package/dist/types/server/index.d.ts +1 -2
- package/dist/types/server/index.d.ts.map +1 -1
- package/dist/types/server/jwt-edge.d.ts.map +1 -1
- package/dist/types/server/jwt.d.ts.map +1 -1
- package/dist/types/server/session-store.d.ts +30 -0
- package/dist/types/server/session-store.d.ts.map +1 -0
- package/dist/types/server/ternSecureMiddleware.d.ts +2 -3
- package/dist/types/server/ternSecureMiddleware.d.ts.map +1 -1
- package/dist/types/server/types.d.ts +2 -1
- package/dist/types/server/types.d.ts.map +1 -1
- package/dist/types/server/utils.d.ts +22 -0
- package/dist/types/server/utils.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -21,6 +21,9 @@ import { useAuth } from "../boundary/hooks/useAuth";
|
|
|
21
21
|
import { getErrorAlertVariant } from "../errors";
|
|
22
22
|
const authDomain = process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN;
|
|
23
23
|
const appName = process.env.NEXT_PUBLIC_FIREBASE_APP_NAME || "TernSecure";
|
|
24
|
+
const prefix = (classes) => {
|
|
25
|
+
return classes.split(" ").map((cls) => `tern-${cls}`).join(" ");
|
|
26
|
+
};
|
|
24
27
|
function SignIn({
|
|
25
28
|
redirectUrl,
|
|
26
29
|
onError,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/sign-in.tsx"],"sourcesContent":["'use client'\n\nimport React, { useState, useCallback, useEffect } from 'react'\nimport { useSearchParams, useRouter, usePathname} from 'next/navigation'\nimport { signInWithEmail, signInWithRedirectGoogle, signInWithMicrosoft } from '../app-router/client/actions'\nimport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from \"./ui/card\"\nimport { Input } from \"./ui/input\"\nimport { Label } from \"./ui/label\"\nimport { Button } from \"./ui/button\"\nimport { Alert, AlertDescription } from \"./ui/alert\"\nimport { Separator } from \"./ui/separator\"\nimport { cn } from \"../lib/utils\"\nimport { Loader2, Eye, EyeOff } from 'lucide-react'\nimport { getRedirectResult, User } from 'firebase/auth'\nimport { ternSecureAuth } from '../utils/client-init'\nimport { createSessionCookie } from '../app-router/admin/sessionTernSecure'\nimport { AuthBackground } from './background'\nimport { getValidRedirectUrl } from '../utils/construct'\nimport { handleInternalRoute } from '../app-router/route-handler/internal-route'\nimport type { SignInResponse } from '../types'\nimport { useAuth } from '../boundary/hooks/useAuth'\nimport { getErrorAlertVariant, ErrorCode } from '../errors'\n\n\n\nconst authDomain = process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN;\nconst appName = process.env.NEXT_PUBLIC_FIREBASE_APP_NAME || 'TernSecure';\n\n\nexport interface SignInProps {\n redirectUrl?: string\n onError?: (error: Error) => void\n onSuccess?: () => void\n className?: string\n customStyles?: {\n card?: string\n input?: string\n button?: string\n label?: string\n separator?: string\n title?: string\n description?: string\n socialButton?: string\n }\n}\n\n\nexport function SignIn({\n redirectUrl,\n onError,\n onSuccess,\n className,\n customStyles = {}\n}: SignInProps) {\n const [loading, setLoading] = useState(false)\n const [checkingRedirect, setCheckingRedirect] = useState(true)\n const [formError, setFormError] = useState<SignInResponse | null>(null)\n const [error, setError] = useState('')\n const [email, setEmail] = useState('')\n const [password, setPassword] = useState('')\n const [showPassword, setShowPassword] = useState(false)\n const [passwordFocused, setPasswordFocused] = useState(false)\n const [authResponse, setAuthResponse] = useState<SignInResponse | null>(null)\n const [authErrorMessage, setAuthErrorMessage] = useState<string | null>(null)\n const searchParams = useSearchParams()\n const isRedirectSignIn = searchParams.get('signInRedirect') === 'true'\n const router = useRouter()\n const pathname = usePathname()\n const InternalComponent = handleInternalRoute(pathname || \"\")\n const { requiresVerification, error: authError, status } = useAuth()\n const validRedirectUrl = getValidRedirectUrl(searchParams, redirectUrl)\n\n\n if (InternalComponent) {\n return <InternalComponent />\n }\n\n useEffect(() => {\n if (authError && status !== \"loading\" && status !== \"unauthenticated\") {\n\n const message = authError.message || \"Authentication failed\"\n setAuthErrorMessage(message)\n\n if(!authResponse || authResponse.message !== message) {\n setAuthResponse(authError as SignInResponse)\n }\n } else {\n setAuthErrorMessage(null)\n }\n }, [authError, status, authResponse])\n\n const handleSuccessfulAuth = useCallback(\n async (user: User) => {\n try {\n const idToken = await user.getIdToken()\n const sessionResult = await createSessionCookie(idToken)\n\n if (!sessionResult.success) {\n setFormError({\n success: false, \n message: sessionResult.message || \"Failed to create session\", \n error: 'INTERNAL_ERROR', \n user: null\n })\n }\n\n onSuccess?.()\n\n // Use the finalRedirectUrl for navigation\n if (process.env.NODE_ENV === \"production\") {\n // Use window.location.href in production for a full page reload\n window.location.href = validRedirectUrl\n } else {\n // Use router.push in development\n router.push(validRedirectUrl)\n }\n } catch (err) {\n setFormError({\n success: false, \n message: \"Failed to complete authentication\", \n error: 'INTERNAL_ERROR', \n user: null\n })\n }\n },\n [validRedirectUrl, router, onSuccess],\n )\n\n\n const handleRedirectResult = useCallback(async () => {\n if (!isRedirectSignIn) return false\n setCheckingRedirect(true)\n try {\n console.log('Checking redirect result...');\n console.log('Current hostname:', window.location.hostname);\n console.log('Auth domain hostname:', authDomain);\n\n const isOnAuth = authDomain && \n window.location.hostname === authDomain.replace(/https?:\\/\\//, '');\n console.log('Is on AuthDomain:', isOnAuth);\n\n\n const result = await getRedirectResult(ternSecureAuth)\n console.log('Redirect result:', result);\n if (result) {\n const idToken = await result.user.getIdToken()\n const sessionResult = await createSessionCookie(idToken)\n if (!sessionResult.success) {\n throw new Error('Failed to create session')\n }\n const storedRedirectUrl = sessionStorage.getItem('auth_return_url')\n sessionStorage.removeItem('auth_redirect_url') \n onSuccess?.()\n window.location.href = storedRedirectUrl || getValidRedirectUrl(searchParams, redirectUrl)\n return true\n }\n setCheckingRedirect(false)\n } catch (err) { \n const errorMessage = err as SignInResponse\n setFormError(errorMessage)\n if (onError && err instanceof Error) {\n onError(err)\n }\n sessionStorage.removeItem('auth_redirect_url')\n return false\n }\n }, [isRedirectSignIn, redirectUrl, searchParams, onSuccess, onError])\n\n //const REDIRECT_TIMEOUT = 5000;\n\n useEffect(() => {\n if (isRedirectSignIn) {\n handleRedirectResult()\n }\n }, [handleRedirectResult, isRedirectSignIn])\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n setLoading(true)\n setFormError(null)\n setAuthResponse(null)\n\n try {\n const response= await signInWithEmail(email, password)\n setAuthResponse(response)\n\n if (!response.success) {\n setFormError({\n success: false, \n message: response.message, \n error: response.error, \n user: null\n })\n return\n }\n\n if (response.user) {\n if(requiresVerification && !response.user.emailVerified) {\n setFormError({\n success: false, \n message: 'Email verification required', \n error: 'REQUIRES_VERIFICATION', \n user: response.user\n })\n return\n }\n\n await handleSuccessfulAuth(response.user)\n }\n } catch (err) {\n const errorMessage = err as SignInResponse\n setFormError(errorMessage)\n if (onError && err instanceof Error) {\n onError(err)\n }\n } finally {\n setLoading(false)\n }\n }\n\n const handleSocialSignIn = async (provider: 'google' | 'microsoft') => {\n setLoading(true)\n try {\n\n const validRedirectUrl = getValidRedirectUrl(searchParams, redirectUrl)\n sessionStorage.setItem('auth_redirect_url', validRedirectUrl)\n\n const currentUrl = new URL(window.location.href)\n currentUrl.searchParams.set('signInRedirect', 'true')\n window.history.replaceState({}, '', currentUrl.toString())\n\n const result = provider === 'google' ? await signInWithRedirectGoogle() : await signInWithMicrosoft()\n if (!result.success) {\n throw new Error(result.error)\n }\n } catch (err) {\n const errorMessage = err as SignInResponse\n setFormError(errorMessage)\n if (onError && err instanceof Error) {\n onError(err)\n }\n setLoading(false)\n sessionStorage.removeItem('auth_redirect_url')\n }\n }\n\n const handleVerificationRedirect = (e: React.MouseEvent) => {\n e.preventDefault()\n router.push(\"/sign-in/verify\")\n }\n\n\n if (checkingRedirect && isRedirectSignIn) {\n return (\n <div className=\"flex min-h-screen items-center justify-center\">\n <div className=\"text-center space-y-4\">\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto\" />\n \n </div>\n </div>\n )\n }\n\n\nconst activeError = formError || authResponse\nconst showEmailVerificationButton =\n activeError?.error === \"EMAIL_NOT_VERIFIED\" || activeError?.error === \"REQUIRES_VERIFICATION\"\n\n return (\n <div className=\"relative flex items-center justify-center\">\n <AuthBackground />\n <Card className={cn(\"w-full max-w-md mx-auto mt-8\", className, customStyles.card)}>\n <CardHeader className=\"space-y-1 text-center\">\n <CardTitle className={cn(\"font-bold\", customStyles.title)}>Sign in to {`${appName}`} </CardTitle>\n <CardDescription className={cn(\"text-muted-foreground\", customStyles.description)}>\n Please sign in to continue\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n {activeError && (\n <Alert variant={getErrorAlertVariant(activeError)} className=\"animate-in fade-in-50\">\n <AlertDescription>\n <span>{activeError.message}</span>\n {showEmailVerificationButton && (\n <Button\n type='button'\n variant=\"link\"\n className=\"p-0 h-auto font-normal text-sm hover:underline\"\n onClick={handleVerificationRedirect}\n >\n Request new verification email →\n </Button>\n )}\n </AlertDescription>\n </Alert>\n )}\n <div className=\"space-y-2\">\n <Label htmlFor=\"email\" className={cn(customStyles.label)}>Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n placeholder=\"m@example.com\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n disabled={loading}\n className={cn(customStyles.input)}\n required\n aria-invalid={activeError?.error === \"INVALID_EMAIL\"}\n aria-describedby={activeError ? \"error-message\" : undefined}\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"password\" className={cn(customStyles.label)}>Password</Label>\n <div className=\"relative\">\n <Input\n id=\"password\"\n name=\"password\"\n type={showPassword ? \"text\" : \"password\"}\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n onFocus={() => setPasswordFocused(true)}\n onBlur={() => setPasswordFocused(false)}\n disabled={loading}\n className={cn(customStyles.input)}\n required\n aria-invalid={activeError?.error === \"INVALID_CREDENTIALS\"}\n aria-describedby={activeError ? \"error-message\" : undefined}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"absolute right-2 top-1/2 -translate-y-1/2 h-8 w-8 hover:bg-transparent\"\n onClick={() => setShowPassword(!showPassword)}\n >\n {showPassword ? (\n <EyeOff className=\"h-4 w-4 text-muted-foreground hover:text-foreground\" />\n ) : (\n <Eye className=\"h-4 w-4 text-muted-foreground hover:text-foreground\" />\n )}\n <span className=\"sr-only\">{showPassword ? \"Hide password\" : \"Show password\"}</span>\n </Button>\n </div>\n </div>\n <Button type=\"submit\" disabled={loading} className={cn(\"w-full\", customStyles.button)}>\n {loading ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n Signing in...\n </>\n ) : (\n 'Sign in'\n )}\n </Button>\n </form>\n <div className=\"relative\">\n <Separator className={cn(customStyles.separator)} />\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <span className=\"bg-background px-2 text-muted-foreground text-sm\">Or continue with</span>\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <Button \n variant=\"outline\" \n disabled={loading} \n onClick={() => handleSocialSignIn('google')} \n className={cn(\"flex items-center justify-center\", customStyles.socialButton)}\n >\n <svg className=\"w-5 h-5 mr-2\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z\" fill=\"#4285F4\"/>\n <path d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\" fill=\"#34A853\"/>\n <path d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" fill=\"#FBBC05\"/>\n <path d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" fill=\"#EA4335\"/>\n </svg>\n Google\n </Button>\n <Button \n variant=\"outline\" \n disabled={loading} \n onClick={() => handleSocialSignIn('microsoft')} \n className={cn(\"flex items-center justify-center\", customStyles.socialButton)}\n >\n <svg className=\"w-5 h-5 mr-2\" viewBox=\"0 0 23 23\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill=\"#f3f3f3\" d=\"M0 0h23v23H0z\"/>\n <path fill=\"#f35325\" d=\"M1 1h10v10H1z\"/>\n <path fill=\"#81bc06\" d=\"M12 1h10v10H12z\"/>\n <path fill=\"#05a6f0\" d=\"M1 12h10v10H1z\"/>\n <path fill=\"#ffba08\" d=\"M12 12h10v10H12z\"/>\n </svg>\n Microsoft\n </Button>\n </div>\n </CardContent>\n <CardFooter className=\"flex justify-center\">\n <p className=\"text-sm text-muted-foreground\">\n Don't have an account?{' '}\n <a href=\"/sign-up\" className=\"text-primary hover:underline\">\n Sign up\n </a>\n </p>\n </CardFooter>\n </Card>\n </div>\n )\n}\n\n"],"mappings":"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","names":["validRedirectUrl"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/sign-in.tsx"],"sourcesContent":["'use client'\n\nimport React, { useState, useCallback, useEffect } from 'react'\nimport { useSearchParams, useRouter, usePathname} from 'next/navigation'\nimport { signInWithEmail, signInWithRedirectGoogle, signInWithMicrosoft } from '../app-router/client/actions'\nimport { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from \"./ui/card\"\nimport { Input } from \"./ui/input\"\nimport { Label } from \"./ui/label\"\nimport { Button } from \"./ui/button\"\nimport { Alert, AlertDescription } from \"./ui/alert\"\nimport { Separator } from \"./ui/separator\"\nimport { cn } from \"../lib/utils\"\nimport { Loader2, Eye, EyeOff } from 'lucide-react'\nimport { getRedirectResult, User } from 'firebase/auth'\nimport { ternSecureAuth } from '../utils/client-init'\nimport { createSessionCookie } from '../app-router/admin/sessionTernSecure'\nimport { AuthBackground } from './background'\nimport { getValidRedirectUrl } from '../utils/construct'\nimport { handleInternalRoute } from '../app-router/route-handler/internal-route'\nimport type { SignInResponse } from '../types'\nimport { useAuth } from '../boundary/hooks/useAuth'\nimport { getErrorAlertVariant } from '../errors'\nimport { twMerge } from 'tailwind-merge'\n\n\n\nconst authDomain = process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN;\nconst appName = process.env.NEXT_PUBLIC_FIREBASE_APP_NAME || 'TernSecure';\n\n\nexport interface SignInProps {\n redirectUrl?: string\n onError?: (error: Error) => void\n onSuccess?: () => void\n className?: string\n customStyles?: {\n card?: string\n input?: string\n button?: string\n label?: string\n separator?: string\n title?: string\n description?: string\n socialButton?: string\n }\n}\n\nconst prefix = (classes: string) => {\n return classes.split(' ').map(cls => `tern-${cls}`).join(' ')\n}\n\n\nexport function SignIn({\n redirectUrl,\n onError,\n onSuccess,\n className,\n customStyles = {}\n}: SignInProps) {\n const [loading, setLoading] = useState(false)\n const [checkingRedirect, setCheckingRedirect] = useState(true)\n const [formError, setFormError] = useState<SignInResponse | null>(null)\n const [error, setError] = useState('')\n const [email, setEmail] = useState('')\n const [password, setPassword] = useState('')\n const [showPassword, setShowPassword] = useState(false)\n const [passwordFocused, setPasswordFocused] = useState(false)\n const [authResponse, setAuthResponse] = useState<SignInResponse | null>(null)\n const [authErrorMessage, setAuthErrorMessage] = useState<string | null>(null)\n const searchParams = useSearchParams()\n const isRedirectSignIn = searchParams.get('signInRedirect') === 'true'\n const router = useRouter()\n const pathname = usePathname()\n const InternalComponent = handleInternalRoute(pathname || \"\")\n const { requiresVerification, error: authError, status } = useAuth()\n const validRedirectUrl = getValidRedirectUrl(searchParams, redirectUrl)\n\n\n if (InternalComponent) {\n return <InternalComponent />\n }\n\n useEffect(() => {\n if (authError && status !== \"loading\" && status !== \"unauthenticated\") {\n\n const message = authError.message || \"Authentication failed\"\n setAuthErrorMessage(message)\n\n if(!authResponse || authResponse.message !== message) {\n setAuthResponse(authError as SignInResponse)\n }\n } else {\n setAuthErrorMessage(null)\n }\n }, [authError, status, authResponse])\n\n const handleSuccessfulAuth = useCallback(\n async (user: User) => {\n try {\n const idToken = await user.getIdToken()\n const sessionResult = await createSessionCookie(idToken)\n\n if (!sessionResult.success) {\n setFormError({\n success: false, \n message: sessionResult.message || \"Failed to create session\", \n error: 'INTERNAL_ERROR', \n user: null\n })\n }\n\n onSuccess?.()\n\n // Use the finalRedirectUrl for navigation\n if (process.env.NODE_ENV === \"production\") {\n // Use window.location.href in production for a full page reload\n window.location.href = validRedirectUrl\n } else {\n // Use router.push in development\n router.push(validRedirectUrl)\n }\n } catch (err) {\n setFormError({\n success: false, \n message: \"Failed to complete authentication\", \n error: 'INTERNAL_ERROR', \n user: null\n })\n }\n },\n [validRedirectUrl, router, onSuccess],\n )\n\n\n const handleRedirectResult = useCallback(async () => {\n if (!isRedirectSignIn) return false\n setCheckingRedirect(true)\n try {\n console.log('Checking redirect result...');\n console.log('Current hostname:', window.location.hostname);\n console.log('Auth domain hostname:', authDomain);\n\n const isOnAuth = authDomain && \n window.location.hostname === authDomain.replace(/https?:\\/\\//, '');\n console.log('Is on AuthDomain:', isOnAuth);\n\n\n const result = await getRedirectResult(ternSecureAuth)\n console.log('Redirect result:', result);\n if (result) {\n const idToken = await result.user.getIdToken()\n const sessionResult = await createSessionCookie(idToken)\n if (!sessionResult.success) {\n throw new Error('Failed to create session')\n }\n const storedRedirectUrl = sessionStorage.getItem('auth_return_url')\n sessionStorage.removeItem('auth_redirect_url') \n onSuccess?.()\n window.location.href = storedRedirectUrl || getValidRedirectUrl(searchParams, redirectUrl)\n return true\n }\n setCheckingRedirect(false)\n } catch (err) { \n const errorMessage = err as SignInResponse\n setFormError(errorMessage)\n if (onError && err instanceof Error) {\n onError(err)\n }\n sessionStorage.removeItem('auth_redirect_url')\n return false\n }\n }, [isRedirectSignIn, redirectUrl, searchParams, onSuccess, onError])\n\n //const REDIRECT_TIMEOUT = 5000;\n\n useEffect(() => {\n if (isRedirectSignIn) {\n handleRedirectResult()\n }\n }, [handleRedirectResult, isRedirectSignIn])\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault()\n setLoading(true)\n setFormError(null)\n setAuthResponse(null)\n\n try {\n const response= await signInWithEmail(email, password)\n setAuthResponse(response)\n\n if (!response.success) {\n setFormError({\n success: false, \n message: response.message, \n error: response.error, \n user: null\n })\n return\n }\n\n if (response.user) {\n if(requiresVerification && !response.user.emailVerified) {\n setFormError({\n success: false, \n message: 'Email verification required', \n error: 'REQUIRES_VERIFICATION', \n user: response.user\n })\n return\n }\n\n await handleSuccessfulAuth(response.user)\n }\n } catch (err) {\n const errorMessage = err as SignInResponse\n setFormError(errorMessage)\n if (onError && err instanceof Error) {\n onError(err)\n }\n } finally {\n setLoading(false)\n }\n }\n\n const handleSocialSignIn = async (provider: 'google' | 'microsoft') => {\n setLoading(true)\n try {\n\n const validRedirectUrl = getValidRedirectUrl(searchParams, redirectUrl)\n sessionStorage.setItem('auth_redirect_url', validRedirectUrl)\n\n const currentUrl = new URL(window.location.href)\n currentUrl.searchParams.set('signInRedirect', 'true')\n window.history.replaceState({}, '', currentUrl.toString())\n\n const result = provider === 'google' ? await signInWithRedirectGoogle() : await signInWithMicrosoft()\n if (!result.success) {\n throw new Error(result.error)\n }\n } catch (err) {\n const errorMessage = err as SignInResponse\n setFormError(errorMessage)\n if (onError && err instanceof Error) {\n onError(err)\n }\n setLoading(false)\n sessionStorage.removeItem('auth_redirect_url')\n }\n }\n\n const handleVerificationRedirect = (e: React.MouseEvent) => {\n e.preventDefault()\n router.push(\"/sign-in/verify\")\n }\n\n\n if (checkingRedirect && isRedirectSignIn) {\n return (\n <div className=\"flex min-h-screen items-center justify-center\">\n <div className=\"text-center space-y-4\">\n <div className=\"animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto\" />\n \n </div>\n </div>\n )\n }\n\n\nconst activeError = formError || authResponse\nconst showEmailVerificationButton =\n activeError?.error === \"EMAIL_NOT_VERIFIED\" || activeError?.error === \"REQUIRES_VERIFICATION\"\n\n return (\n <div className=\"relative flex items-center justify-center\">\n <AuthBackground />\n <Card className={cn(\"w-full max-w-md mx-auto mt-8\", className, customStyles.card)}>\n <CardHeader className=\"space-y-1 text-center\">\n <CardTitle className={cn(\"font-bold\", customStyles.title)}>Sign in to {`${appName}`} </CardTitle>\n <CardDescription className={cn(\"text-muted-foreground\", customStyles.description)}>\n Please sign in to continue\n </CardDescription>\n </CardHeader>\n <CardContent className=\"space-y-4\">\n <form onSubmit={handleSubmit} className=\"space-y-4\">\n {activeError && (\n <Alert variant={getErrorAlertVariant(activeError)} className=\"animate-in fade-in-50\">\n <AlertDescription>\n <span>{activeError.message}</span>\n {showEmailVerificationButton && (\n <Button\n type='button'\n variant=\"link\"\n className=\"p-0 h-auto font-normal text-sm hover:underline\"\n onClick={handleVerificationRedirect}\n >\n Request new verification email →\n </Button>\n )}\n </AlertDescription>\n </Alert>\n )}\n <div className=\"space-y-2\">\n <Label htmlFor=\"email\" className={cn(customStyles.label)}>Email</Label>\n <Input\n id=\"email\"\n type=\"email\"\n placeholder=\"m@example.com\"\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n disabled={loading}\n className={cn(customStyles.input)}\n required\n aria-invalid={activeError?.error === \"INVALID_EMAIL\"}\n aria-describedby={activeError ? \"error-message\" : undefined}\n />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"password\" className={cn(customStyles.label)}>Password</Label>\n <div className=\"relative\">\n <Input\n id=\"password\"\n name=\"password\"\n type={showPassword ? \"text\" : \"password\"}\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n onFocus={() => setPasswordFocused(true)}\n onBlur={() => setPasswordFocused(false)}\n disabled={loading}\n className={cn(customStyles.input)}\n required\n aria-invalid={activeError?.error === \"INVALID_CREDENTIALS\"}\n aria-describedby={activeError ? \"error-message\" : undefined}\n />\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"absolute right-2 top-1/2 -translate-y-1/2 h-8 w-8 hover:bg-transparent\"\n onClick={() => setShowPassword(!showPassword)}\n >\n {showPassword ? (\n <EyeOff className=\"h-4 w-4 text-muted-foreground hover:text-foreground\" />\n ) : (\n <Eye className=\"h-4 w-4 text-muted-foreground hover:text-foreground\" />\n )}\n <span className=\"sr-only\">{showPassword ? \"Hide password\" : \"Show password\"}</span>\n </Button>\n </div>\n </div>\n <Button type=\"submit\" disabled={loading} className={cn(\"w-full\", customStyles.button)}>\n {loading ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n Signing in...\n </>\n ) : (\n 'Sign in'\n )}\n </Button>\n </form>\n <div className=\"relative\">\n <Separator className={cn(customStyles.separator)} />\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <span className=\"bg-background px-2 text-muted-foreground text-sm\">Or continue with</span>\n </div>\n </div>\n <div className=\"grid grid-cols-2 gap-4\">\n <Button \n variant=\"outline\" \n disabled={loading} \n onClick={() => handleSocialSignIn('google')} \n className={cn(\"flex items-center justify-center\", customStyles.socialButton)}\n >\n <svg className=\"w-5 h-5 mr-2\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z\" fill=\"#4285F4\"/>\n <path d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\" fill=\"#34A853\"/>\n <path d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\" fill=\"#FBBC05\"/>\n <path d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\" fill=\"#EA4335\"/>\n </svg>\n Google\n </Button>\n <Button \n variant=\"outline\" \n disabled={loading} \n onClick={() => handleSocialSignIn('microsoft')} \n className={cn(\"flex items-center justify-center\", customStyles.socialButton)}\n >\n <svg className=\"w-5 h-5 mr-2\" viewBox=\"0 0 23 23\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill=\"#f3f3f3\" d=\"M0 0h23v23H0z\"/>\n <path fill=\"#f35325\" d=\"M1 1h10v10H1z\"/>\n <path fill=\"#81bc06\" d=\"M12 1h10v10H12z\"/>\n <path fill=\"#05a6f0\" d=\"M1 12h10v10H1z\"/>\n <path fill=\"#ffba08\" d=\"M12 12h10v10H12z\"/>\n </svg>\n Microsoft\n </Button>\n </div>\n </CardContent>\n <CardFooter className=\"flex justify-center\">\n <p className=\"text-sm text-muted-foreground\">\n Don't have an account?{' '}\n <a href=\"/sign-up\" className=\"text-primary hover:underline\">\n Sign up\n </a>\n </p>\n </CardFooter>\n </Card>\n </div>\n )\n}\n\n"],"mappings":"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","names":["validRedirectUrl"]}
|
package/dist/esm/server/auth.js
CHANGED
|
@@ -1,59 +1,73 @@
|
|
|
1
|
-
|
|
2
|
-
import { cookies
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { cache } from "react";
|
|
2
|
+
import { cookies } from "next/headers";
|
|
3
|
+
import { verifyFirebaseToken } from "./jwt-edge";
|
|
4
|
+
import { TernSecureError } from "../errors";
|
|
5
|
+
const auth = cache(async () => {
|
|
6
|
+
var _a, _b, _c, _d;
|
|
5
7
|
try {
|
|
6
|
-
|
|
8
|
+
console.log("auth: Starting auth check...");
|
|
7
9
|
const cookieStore = await cookies();
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
const sessionCookie = (_a = cookieStore.get("_session_cookie")) == null ? void 0 : _a.value;
|
|
11
|
+
if (sessionCookie) {
|
|
12
|
+
const result = await verifyFirebaseToken(sessionCookie, true);
|
|
13
|
+
if (result.valid && result.uid) {
|
|
14
|
+
const user = {
|
|
15
|
+
uid: (_b = result.uid) != null ? _b : "",
|
|
16
|
+
email: result.email || null,
|
|
17
|
+
authTime: result.authTime
|
|
18
|
+
};
|
|
19
|
+
return { user, error: null };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const idToken = (_c = cookieStore.get("_session_token")) == null ? void 0 : _c.value;
|
|
23
|
+
if (idToken) {
|
|
24
|
+
const result = await verifyFirebaseToken(idToken, false);
|
|
25
|
+
if (result.valid) {
|
|
26
|
+
const user = {
|
|
27
|
+
uid: (_d = result.uid) != null ? _d : "",
|
|
28
|
+
email: result.email || null,
|
|
29
|
+
authTime: result.authTime
|
|
30
|
+
};
|
|
31
|
+
return { user, error: null };
|
|
32
|
+
}
|
|
23
33
|
}
|
|
24
34
|
return {
|
|
25
35
|
user: null,
|
|
26
|
-
|
|
27
|
-
error: new Error("No valid session or token found")
|
|
36
|
+
error: new TernSecureError("UNAUTHENTICATED", "No valid session found")
|
|
28
37
|
};
|
|
29
38
|
} catch (error) {
|
|
30
|
-
console.error("Error in
|
|
39
|
+
console.error("Error in Auth:", error);
|
|
40
|
+
if (error instanceof TernSecureError) {
|
|
41
|
+
return {
|
|
42
|
+
user: null,
|
|
43
|
+
error
|
|
44
|
+
};
|
|
45
|
+
}
|
|
31
46
|
return {
|
|
32
47
|
user: null,
|
|
33
|
-
|
|
34
|
-
error: error instanceof Error ? error : new Error("An unknown error occurred")
|
|
48
|
+
error: new TernSecureError("INTERNAL_ERROR", "An unexpected error occurred")
|
|
35
49
|
};
|
|
36
50
|
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
return
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
51
|
+
});
|
|
52
|
+
const isAuthenticated = cache(async () => {
|
|
53
|
+
const { user } = await auth();
|
|
54
|
+
return user !== null;
|
|
55
|
+
});
|
|
56
|
+
const getUser = cache(async () => {
|
|
57
|
+
const { user } = await auth();
|
|
58
|
+
return user;
|
|
59
|
+
});
|
|
60
|
+
const requireAuth = cache(async () => {
|
|
61
|
+
const { user, error } = await auth();
|
|
62
|
+
if (!user) {
|
|
63
|
+
throw error || new Error("Authentication required");
|
|
46
64
|
}
|
|
47
|
-
return
|
|
48
|
-
|
|
49
|
-
email: authResult.user.email,
|
|
50
|
-
emailVerified: authResult.user.emailVerified,
|
|
51
|
-
authTime: authResult.user.authTime
|
|
52
|
-
};
|
|
53
|
-
}
|
|
65
|
+
return user;
|
|
66
|
+
});
|
|
54
67
|
export {
|
|
55
68
|
auth,
|
|
56
|
-
|
|
57
|
-
isAuthenticated
|
|
69
|
+
getUser,
|
|
70
|
+
isAuthenticated,
|
|
71
|
+
requireAuth
|
|
58
72
|
};
|
|
59
73
|
//# sourceMappingURL=auth.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/auth.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../../src/server/auth.ts"],"sourcesContent":["import { cache } from \"react\"\nimport { cookies } from \"next/headers\"\nimport type { UserInfo } from \"./types\"\nimport { verifyFirebaseToken } from \"./jwt-edge\"\nimport { TernSecureError } from \"../errors\"\n\n\n\nexport interface AuthResult {\n user: UserInfo | null\n error: Error | null\n}\n\n /**\n * Get the current authenticated user from the session or token\n */\nexport const auth = cache(async (): Promise<AuthResult> => {\n try {\n // Get all active sessions for debugging\n console.log(\"auth: Starting auth check...\")\n const cookieStore = await cookies()\n\n // First try session cookie as it's more secure\n const sessionCookie = cookieStore.get(\"_session_cookie\")?.value\n if (sessionCookie) {\n const result = await verifyFirebaseToken(sessionCookie, true)\n if (result.valid && result.uid) {\n const user: UserInfo = {\n uid: result.uid ?? '',\n email: result.email || null,\n authTime: result.authTime\n }\n return { user, error: null }\n }\n }\n\n // Fallback to ID token\n const idToken = cookieStore.get(\"_session_token\")?.value\n if (idToken) {\n const result = await verifyFirebaseToken(idToken, false)\n if (result.valid) {\n const user: UserInfo = {\n uid: result.uid ?? '',\n email: result.email || null,\n authTime: result.authTime\n }\n return { user, error: null }\n }\n }\n\n return {\n user: null,\n error: new TernSecureError('UNAUTHENTICATED', 'No valid session found')\n }\n\n } catch (error) {\n console.error(\"Error in Auth:\", error)\n if (error instanceof TernSecureError) {\n return {\n user: null,\n error\n }\n }\n return {\n user: null,\n error: new TernSecureError('INTERNAL_ERROR', 'An unexpected error occurred')\n }\n }\n })\n\n/**\n * Type guard to check if user is authenticated\n */\nexport const isAuthenticated = cache(async (): Promise<boolean> => {\n const { user } = await auth()\n return user !== null\n})\n\n/**\n * Get user info from auth result\n */\nexport const getUser = cache(async (): Promise<UserInfo | null> => {\n const { user } = await auth()\n return user\n})\n\n/**\n * Require authentication\n * Throws error if not authenticated\n */\nexport const requireAuth = cache(async (): Promise<UserInfo> => {\n const { user, error } = await auth()\n\n if (!user) {\n throw error || new Error(\"Authentication required\")\n }\n\n return user\n})"],"mappings":"AAAA,SAAS,aAAa;AACtB,SAAS,eAAe;AAExB,SAAS,2BAA2B;AACpC,SAAS,uBAAuB;AAYzB,MAAM,OAAO,MAAM,YAAiC;AAhB3D;AAiBE,MAAI;AAEH,YAAQ,IAAI,8BAA8B;AAC1C,UAAM,cAAc,MAAM,QAAQ;AAGjC,UAAM,iBAAgB,iBAAY,IAAI,iBAAiB,MAAjC,mBAAoC;AAC1D,QAAI,eAAe;AACjB,YAAM,SAAS,MAAM,oBAAoB,eAAe,IAAI;AAC5D,UAAI,OAAO,SAAS,OAAO,KAAK;AAC9B,cAAM,OAAiB;AAAA,UACrB,MAAK,YAAO,QAAP,YAAc;AAAA,UACnB,OAAO,OAAO,SAAS;AAAA,UACvB,UAAU,OAAO;AAAA,QACnB;AACA,eAAO,EAAE,MAAM,OAAO,KAAK;AAAA,MAC7B;AAAA,IACF;AAGA,UAAM,WAAU,iBAAY,IAAI,gBAAgB,MAAhC,mBAAmC;AACnD,QAAI,SAAS;AACX,YAAM,SAAS,MAAM,oBAAoB,SAAS,KAAK;AACvD,UAAI,OAAO,OAAO;AAChB,cAAM,OAAiB;AAAA,UACrB,MAAK,YAAO,QAAP,YAAc;AAAA,UACnB,OAAO,OAAO,SAAS;AAAA,UACvB,UAAU,OAAO;AAAA,QACnB;AACA,eAAO,EAAE,MAAM,OAAO,KAAK;AAAA,MAC7B;AAAA,IACF;AAEE,WAAO;AAAA,MACH,MAAM;AAAA,MACN,OAAO,IAAI,gBAAgB,mBAAmB,wBAAwB;AAAA,IAC1E;AAAA,EAEF,SAAS,OAAO;AACd,YAAQ,MAAM,kBAAkB,KAAK;AACrC,QAAI,iBAAiB,iBAAiB;AACpC,aAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO,IAAI,gBAAgB,kBAAkB,8BAA8B;AAAA,IAC7E;AAAA,EACF;AACF,CAAC;AAKI,MAAM,kBAAkB,MAAM,YAA+B;AAClE,QAAM,EAAE,KAAK,IAAI,MAAM,KAAK;AAC5B,SAAO,SAAS;AAClB,CAAC;AAKM,MAAM,UAAU,MAAM,YAAsC;AACjE,QAAM,EAAE,KAAK,IAAI,MAAM,KAAK;AAC5B,SAAO;AACT,CAAC;AAMM,MAAM,cAAc,MAAM,YAA+B;AAC9D,QAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK;AAEnC,MAAI,CAAC,MAAM;AACT,UAAM,SAAS,IAAI,MAAM,yBAAyB;AAAA,EACpD;AAEA,SAAO;AACT,CAAC;","names":[]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const ENCRYPTION_KEY = process.env.TERN_ENCRYPTION_KEY || "default-key-32-chars-exactly!!!!!";
|
|
2
|
+
function encrypt(text) {
|
|
3
|
+
const textBytes = new TextEncoder().encode(text);
|
|
4
|
+
const encrypted = textBytes.map((byte, i) => byte ^ ENCRYPTION_KEY.charCodeAt(i % ENCRYPTION_KEY.length));
|
|
5
|
+
return Buffer.from(encrypted).toString("base64url");
|
|
6
|
+
}
|
|
7
|
+
function decrypt(encoded) {
|
|
8
|
+
const encrypted = Buffer.from(encoded, "base64url");
|
|
9
|
+
const decrypted = new Uint8Array(encrypted).map(
|
|
10
|
+
(byte, i) => byte ^ ENCRYPTION_KEY.charCodeAt(i % ENCRYPTION_KEY.length)
|
|
11
|
+
);
|
|
12
|
+
return new TextDecoder().decode(decrypted);
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
decrypt,
|
|
16
|
+
encrypt
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/server/crypto.ts"],"sourcesContent":["const ENCRYPTION_KEY = process.env.TERN_ENCRYPTION_KEY || \"default-key-32-chars-exactly!!!!!\"\n\n// Simple encryption for cookie data\nexport function encrypt(text: string): string {\n const textBytes = new TextEncoder().encode(text)\n const encrypted = textBytes.map((byte, i) => byte ^ ENCRYPTION_KEY.charCodeAt(i % ENCRYPTION_KEY.length))\n return Buffer.from(encrypted).toString(\"base64url\")\n}\n\nexport function decrypt(encoded: string): string {\n const encrypted = Buffer.from(encoded, \"base64url\")\n const decrypted = new Uint8Array(encrypted).map(\n (byte, i) => byte ^ ENCRYPTION_KEY.charCodeAt(i % ENCRYPTION_KEY.length),\n )\n return new TextDecoder().decode(decrypted)\n}\n"],"mappings":"AAAA,MAAM,iBAAiB,QAAQ,IAAI,uBAAuB;AAGnD,SAAS,QAAQ,MAAsB;AAC5C,QAAM,YAAY,IAAI,YAAY,EAAE,OAAO,IAAI;AAC/C,QAAM,YAAY,UAAU,IAAI,CAAC,MAAM,MAAM,OAAO,eAAe,WAAW,IAAI,eAAe,MAAM,CAAC;AACxG,SAAO,OAAO,KAAK,SAAS,EAAE,SAAS,WAAW;AACpD;AAEO,SAAS,QAAQ,SAAyB;AAC/C,QAAM,YAAY,OAAO,KAAK,SAAS,WAAW;AAClD,QAAM,YAAY,IAAI,WAAW,SAAS,EAAE;AAAA,IAC1C,CAAC,MAAM,MAAM,OAAO,eAAe,WAAW,IAAI,eAAe,MAAM;AAAA,EACzE;AACA,SAAO,IAAI,YAAY,EAAE,OAAO,SAAS;AAC3C;","names":[]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
if (typeof global.__ternSecure === "undefined") {
|
|
2
|
+
global.__ternSecure = {
|
|
3
|
+
context: null,
|
|
4
|
+
sessions: /* @__PURE__ */ new Map()
|
|
5
|
+
};
|
|
6
|
+
console.log("ContextStore: Initialized global state");
|
|
7
|
+
}
|
|
8
|
+
class ContextStore {
|
|
9
|
+
static setContext(context) {
|
|
10
|
+
console.log("ContextStore: Setting context:", context);
|
|
11
|
+
global.__ternSecure.context = context;
|
|
12
|
+
console.log("ContextStore: Context set successfully");
|
|
13
|
+
}
|
|
14
|
+
static getContext() {
|
|
15
|
+
const context = global.__ternSecure.context;
|
|
16
|
+
console.log("ContextStore: Getting context:", context);
|
|
17
|
+
return context;
|
|
18
|
+
}
|
|
19
|
+
static setSession(sessionId, user) {
|
|
20
|
+
console.log("ContextStore: Setting session:", { sessionId, user });
|
|
21
|
+
global.__ternSecure.sessions.set(sessionId, user);
|
|
22
|
+
console.log("ContextStore: Session set successfully");
|
|
23
|
+
}
|
|
24
|
+
static getSession(sessionId) {
|
|
25
|
+
const user = global.__ternSecure.sessions.get(sessionId) || null;
|
|
26
|
+
console.log("ContextStore: Getting session:", { sessionId, user });
|
|
27
|
+
return user;
|
|
28
|
+
}
|
|
29
|
+
static debug() {
|
|
30
|
+
var _a;
|
|
31
|
+
return {
|
|
32
|
+
sessionsCount: global.__ternSecure.sessions.size,
|
|
33
|
+
currentSessionId: ((_a = global.__ternSecure.context) == null ? void 0 : _a.sessionId) || null,
|
|
34
|
+
sessions: Array.from(global.__ternSecure.sessions.entries())
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
ContextStore
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=ctx-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/server/ctx-store.ts"],"sourcesContent":["import type { UserInfo } from \"./types\"\n\ninterface RequestContext {\n user: UserInfo\n sessionId: string\n}\n\n// Use Node.js global for server-side persistence\ndeclare global {\n var __ternSecure: {\n context: RequestContext | null\n sessions: Map<string, UserInfo>\n }\n}\n\n// Initialize global state if not exists\nif (typeof global.__ternSecure === 'undefined') {\n global.__ternSecure = {\n context: null,\n sessions: new Map(),\n }\n console.log(\"ContextStore: Initialized global state\")\n}\n\nexport class ContextStore {\n static setContext(context: RequestContext) {\n console.log(\"ContextStore: Setting context:\", context)\n global.__ternSecure.context = context\n console.log(\"ContextStore: Context set successfully\")\n }\n\n static getContext(): RequestContext | null {\n const context = global.__ternSecure.context\n console.log(\"ContextStore: Getting context:\", context)\n return context\n }\n\n static setSession(sessionId: string, user: UserInfo) {\n console.log(\"ContextStore: Setting session:\", { sessionId, user })\n global.__ternSecure.sessions.set(sessionId, user)\n console.log(\"ContextStore: Session set successfully\")\n }\n\n static getSession(sessionId: string): UserInfo | null {\n const user = global.__ternSecure.sessions.get(sessionId) || null\n console.log(\"ContextStore: Getting session:\", { sessionId, user })\n return user\n }\n\n static debug() {\n return {\n sessionsCount: global.__ternSecure.sessions.size,\n currentSessionId: global.__ternSecure.context?.sessionId || null,\n sessions: Array.from(global.__ternSecure.sessions.entries()),\n }\n }\n}\n\n"],"mappings":"AAgBA,IAAI,OAAO,OAAO,iBAAiB,aAAa;AAC5C,SAAO,eAAe;AAAA,IACpB,SAAS;AAAA,IACT,UAAU,oBAAI,IAAI;AAAA,EACpB;AACF,UAAQ,IAAI,wCAAwC;AACtD;AAEO,MAAM,aAAa;AAAA,EACxB,OAAO,WAAW,SAAyB;AACzC,YAAQ,IAAI,kCAAkC,OAAO;AACrD,WAAO,aAAa,UAAU;AAC9B,YAAQ,IAAI,wCAAwC;AAAA,EACtD;AAAA,EAEA,OAAO,aAAoC;AACzC,UAAM,UAAU,OAAO,aAAa;AACpC,YAAQ,IAAI,kCAAkC,OAAO;AACrD,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,WAAW,WAAmB,MAAgB;AACnD,YAAQ,IAAI,kCAAkC,EAAE,WAAW,KAAK,CAAC;AACjE,WAAO,aAAa,SAAS,IAAI,WAAW,IAAI;AAChD,YAAQ,IAAI,wCAAwC;AAAA,EACtD;AAAA,EAEA,OAAO,WAAW,WAAoC;AACpD,UAAM,OAAO,OAAO,aAAa,SAAS,IAAI,SAAS,KAAK;AAC5D,YAAQ,IAAI,kCAAkC,EAAE,WAAW,KAAK,CAAC;AACjE,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,QAAQ;AAjDjB;AAkDI,WAAO;AAAA,MACL,eAAe,OAAO,aAAa,SAAS;AAAA,MAC5C,oBAAkB,YAAO,aAAa,YAApB,mBAA6B,cAAa;AAAA,MAC5D,UAAU,MAAM,KAAK,OAAO,aAAa,SAAS,QAAQ,CAAC;AAAA,IAC7D;AAAA,EACF;AACF;","names":[]}
|
|
@@ -3,47 +3,51 @@ async function verifySession(request) {
|
|
|
3
3
|
var _a, _b, _c, _d, _e, _f;
|
|
4
4
|
try {
|
|
5
5
|
const sessionCookie = (_a = request.cookies.get("_session_cookie")) == null ? void 0 : _a.value;
|
|
6
|
+
const idToken = (_b = request.cookies.get("_session_token")) == null ? void 0 : _b.value;
|
|
6
7
|
if (sessionCookie) {
|
|
7
8
|
const result = await verifyFirebaseToken(sessionCookie, true);
|
|
8
9
|
if (result.valid) {
|
|
10
|
+
const user = {
|
|
11
|
+
uid: (_c = result.uid) != null ? _c : "",
|
|
12
|
+
email: result.email || null,
|
|
13
|
+
emailVerified: (_d = result.emailVerified) != null ? _d : false,
|
|
14
|
+
authTime: result.authTime
|
|
15
|
+
};
|
|
9
16
|
return {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
email: result.email || null,
|
|
14
|
-
emailVerified: (_c = result.emailVerified) != null ? _c : false,
|
|
15
|
-
disabled: false
|
|
16
|
-
}
|
|
17
|
+
user,
|
|
18
|
+
token: sessionCookie,
|
|
19
|
+
sessionId: sessionCookie
|
|
17
20
|
};
|
|
18
21
|
}
|
|
19
|
-
console.log("Session cookie verification failed:", result.error);
|
|
20
22
|
}
|
|
21
|
-
const idToken = (_d = request.cookies.get("_session_token")) == null ? void 0 : _d.value;
|
|
22
23
|
if (idToken) {
|
|
23
24
|
const result = await verifyFirebaseToken(idToken, false);
|
|
24
25
|
if (result.valid) {
|
|
26
|
+
const user = {
|
|
27
|
+
uid: (_e = result.uid) != null ? _e : "",
|
|
28
|
+
email: result.email || null,
|
|
29
|
+
emailVerified: (_f = result.emailVerified) != null ? _f : false,
|
|
30
|
+
authTime: result.authTime
|
|
31
|
+
};
|
|
25
32
|
return {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
email: result.email || null,
|
|
30
|
-
emailVerified: (_f = result.emailVerified) != null ? _f : false,
|
|
31
|
-
disabled: false
|
|
32
|
-
}
|
|
33
|
+
user,
|
|
34
|
+
token: idToken,
|
|
35
|
+
sessionId: idToken
|
|
33
36
|
};
|
|
34
37
|
}
|
|
35
|
-
console.log("ID token verification failed:", result.error);
|
|
36
38
|
}
|
|
37
39
|
return {
|
|
38
|
-
isAuthenticated: false,
|
|
39
40
|
user: null,
|
|
41
|
+
token: null,
|
|
42
|
+
sessionId: null,
|
|
40
43
|
error: "No valid session found"
|
|
41
44
|
};
|
|
42
45
|
} catch (error) {
|
|
43
46
|
console.error("Session verification error:", error);
|
|
44
47
|
return {
|
|
45
|
-
isAuthenticated: false,
|
|
46
48
|
user: null,
|
|
49
|
+
token: null,
|
|
50
|
+
sessionId: null,
|
|
47
51
|
error: error instanceof Error ? error.message : "Session verification failed"
|
|
48
52
|
};
|
|
49
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/edge-session.ts"],"sourcesContent":["import { verifyFirebaseToken } from \"./jwt-edge\"\nimport type { NextRequest } from \"next/server\"\nimport type { SessionResult } from \"./types\"\n\n\nexport async function verifySession(request: NextRequest): Promise<SessionResult> {\n try {\n //const cookieStore = await cookies()\n\n // First try session cookie\n const sessionCookie = request.cookies.get(\"_session_cookie\")?.value\n if (sessionCookie) {\n const result = await verifyFirebaseToken(sessionCookie, true)\n if (result.valid) {\n
|
|
1
|
+
{"version":3,"sources":["../../../src/server/edge-session.ts"],"sourcesContent":["import { verifyFirebaseToken } from \"./jwt-edge\"\nimport type { NextRequest } from \"next/server\"\nimport type { SessionResult, UserInfo } from \"./types\"\n\n\n\nexport async function verifySession(request: NextRequest): Promise<SessionResult> {\n try {\n //const cookieStore = await cookies()\n\n // First try session cookie\n\n const sessionCookie = request.cookies.get(\"_session_cookie\")?.value\n const idToken = request.cookies.get(\"_session_token\")?.value\n\n //const sessionCookie = request.cookies.get(\"_session_cookie\")?.value\n if (sessionCookie) {\n const result = await verifyFirebaseToken(sessionCookie, true)\n if (result.valid) {\n const user: UserInfo = {\n uid: result.uid ?? '',\n email: result.email || null,\n emailVerified: result.emailVerified ?? false,\n authTime: result.authTime,\n }\n\n return {\n user,\n token: sessionCookie,\n sessionId: sessionCookie,\n }\n }\n }\n\n // Then try ID token\n //const idToken = request.cookies.get(\"_session_token\")?.value\n if (idToken) {\n const result = await verifyFirebaseToken(idToken, false)\n if (result.valid) {\n const user: UserInfo = {\n uid: result.uid ?? '',\n email: result.email || null,\n emailVerified: result.emailVerified ?? false,\n authTime: result.authTime,\n }\n\n\n return {\n user,\n token: idToken,\n sessionId: idToken,\n }\n }\n }\n\n return {\n user: null,\n token: null,\n sessionId: null,\n error: \"No valid session found\",\n }\n } catch (error) {\n console.error(\"Session verification error:\", error)\n return {\n user: null,\n token: null,\n sessionId: null,\n error: error instanceof Error ? error.message : \"Session verification failed\",\n }\n }\n}"],"mappings":"AAAA,SAAS,2BAA2B;AAMpC,eAAsB,cAAc,SAA8C;AANlF;AAOE,MAAI;AAKF,UAAM,iBAAgB,aAAQ,QAAQ,IAAI,iBAAiB,MAArC,mBAAwC;AAC9D,UAAM,WAAU,aAAQ,QAAQ,IAAI,gBAAgB,MAApC,mBAAuC;AAGvD,QAAI,eAAe;AACjB,YAAM,SAAS,MAAM,oBAAoB,eAAe,IAAI;AAC5D,UAAI,OAAO,OAAO;AACd,cAAM,OAAiB;AAAA,UACrB,MAAK,YAAO,QAAP,YAAc;AAAA,UACnB,OAAO,OAAO,SAAS;AAAA,UACvB,gBAAe,YAAO,kBAAP,YAAwB;AAAA,UACvC,UAAU,OAAO;AAAA,QACrB;AAEA,eAAO;AAAA,UACL;AAAA,UACA,OAAO;AAAA,UACP,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAIA,QAAI,SAAS;AACX,YAAM,SAAS,MAAM,oBAAoB,SAAS,KAAK;AACvD,UAAI,OAAO,OAAO;AAChB,cAAM,OAAkB;AAAA,UACpB,MAAK,YAAO,QAAP,YAAc;AAAA,UACnB,OAAO,OAAO,SAAS;AAAA,UACvB,gBAAe,YAAO,kBAAP,YAAwB;AAAA,UACvC,UAAU,OAAO;AAAA,QACrB;AAGA,eAAO;AAAA,UACL;AAAA,UACA,OAAO;AAAA,UACP,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,WAAW;AAAA,MACX,OAAO;AAAA,IACT;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,+BAA+B,KAAK;AAClD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,WAAW;AAAA,MACX,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAClD;AAAA,EACF;AACF;","names":[]}
|
package/dist/esm/server/index.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { ternSecureMiddleware, createRouteMatcher } from "./ternSecureMiddleware";
|
|
2
|
-
import { auth
|
|
2
|
+
import { auth } from "./auth";
|
|
3
3
|
export {
|
|
4
4
|
auth,
|
|
5
5
|
createRouteMatcher,
|
|
6
|
-
getUserInfo,
|
|
7
6
|
ternSecureMiddleware
|
|
8
7
|
};
|
|
9
8
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/index.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../../src/server/index.ts"],"sourcesContent":["export { ternSecureMiddleware, createRouteMatcher } from './ternSecureMiddleware'\nexport { auth, type AuthResult } from './auth'\nexport type { UserInfo, SessionResult } from './types'"],"mappings":"AAAA,SAAS,sBAAsB,0BAA0B;AACzD,SAAS,YAA6B;","names":[]}
|
|
@@ -55,18 +55,9 @@ async function verifyFirebaseToken(token, isSessionCookie = false) {
|
|
|
55
55
|
});
|
|
56
56
|
const firebasePayload = payload;
|
|
57
57
|
const now = Math.floor(Date.now() / 1e3);
|
|
58
|
-
if (firebasePayload.exp <= now) {
|
|
59
|
-
throw new Error("Token has expired");
|
|
60
|
-
}
|
|
61
|
-
if (firebasePayload.iat > now) {
|
|
62
|
-
throw new Error("Token issued time is in the future");
|
|
63
|
-
}
|
|
64
58
|
if (!firebasePayload.sub) {
|
|
65
59
|
throw new Error("Token subject is empty");
|
|
66
60
|
}
|
|
67
|
-
if (firebasePayload.auth_time > now) {
|
|
68
|
-
throw new Error("Token auth time is in the future");
|
|
69
|
-
}
|
|
70
61
|
return {
|
|
71
62
|
valid: true,
|
|
72
63
|
uid: firebasePayload.sub,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/jwt-edge.ts"],"sourcesContent":["import { jwtVerify, createRemoteJWKSet } from \"jose\"\nimport { cache } from \"react\"\n\ninterface FirebaseIdTokenPayload {\n iss: string\n aud: string\n auth_time: number\n user_id: string\n sub: string\n iat: number\n exp: number\n email?: string\n email_verified?: boolean\n firebase: {\n identities: {\n [key: string]: any\n }\n sign_in_provider: string\n }\n}\n\n// Firebase public key endpoints\nconst FIREBASE_ID_TOKEN_URL = \"https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com\"\nconst FIREBASE_SESSION_CERT_URL = \"https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys\"\n\n// Cache the JWKS using React cache\nconst getIdTokenJWKS = cache(() => {\n return createRemoteJWKSet(new URL(FIREBASE_ID_TOKEN_URL), {\n cacheMaxAge: 3600000, // 1 hour\n timeoutDuration: 5000, // 5 seconds\n cooldownDuration: 30000, // 30 seconds between retries\n })\n})\n\nconst getSessionJWKS = cache(() => {\n return createRemoteJWKSet(new URL(FIREBASE_SESSION_CERT_URL), {\n cacheMaxAge: 3600000, // 1 hour\n timeoutDuration: 5000, // 5 seconds\n cooldownDuration: 30000, // 30 seconds between retries\n })\n})\n\n// Helper to decode JWT without verification\nfunction decodeJwt(token: string) {\n try {\n const [headerB64, payloadB64] = token.split(\".\")\n const header = JSON.parse(Buffer.from(headerB64, \"base64\").toString())\n const payload = JSON.parse(Buffer.from(payloadB64, \"base64\").toString())\n return { header, payload }\n } catch (error) {\n console.error(\"Error decoding JWT:\", error)\n return null\n }\n}\n\nexport async function verifyFirebaseToken(token: string, isSessionCookie = false) {\n try {\n const projectId = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID\n if (!projectId) {\n throw new Error(\"Firebase Project ID is not configured\")\n }\n\n // Decode token for debugging and type checking\n const decoded = decodeJwt(token)\n if (!decoded) {\n throw new Error(\"Invalid token format\")\n }\n\n console.log(\"Token details:\", {\n header: decoded.header,\n type: isSessionCookie ? \"session_cookie\" : \"id_token\",\n })\n\n\n // Use different JWKS based on token type\n const JWKS = isSessionCookie ? await getSessionJWKS() : await getIdTokenJWKS()\n\n const { payload } = await jwtVerify(token, JWKS, {\n issuer: isSessionCookie\n ? \"https://session.firebase.google.com/\" + projectId\n : \"https://securetoken.google.com/\" + projectId,\n audience: projectId,\n algorithms: [\"RS256\"],\n })\n\n const firebasePayload = payload as unknown as FirebaseIdTokenPayload\n const now = Math.floor(Date.now() / 1000)\n\n
|
|
1
|
+
{"version":3,"sources":["../../../src/server/jwt-edge.ts"],"sourcesContent":["import { jwtVerify, createRemoteJWKSet } from \"jose\"\nimport { cache } from \"react\"\n\ninterface FirebaseIdTokenPayload {\n iss: string\n aud: string\n auth_time: number\n user_id: string\n sub: string\n iat: number\n exp: number\n email?: string\n email_verified?: boolean\n firebase: {\n identities: {\n [key: string]: any\n }\n sign_in_provider: string\n }\n}\n\n// Firebase public key endpoints\nconst FIREBASE_ID_TOKEN_URL = \"https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com\"\nconst FIREBASE_SESSION_CERT_URL = \"https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys\"\n\n// Cache the JWKS using React cache\nconst getIdTokenJWKS = cache(() => {\n return createRemoteJWKSet(new URL(FIREBASE_ID_TOKEN_URL), {\n cacheMaxAge: 3600000, // 1 hour\n timeoutDuration: 5000, // 5 seconds\n cooldownDuration: 30000, // 30 seconds between retries\n })\n})\n\nconst getSessionJWKS = cache(() => {\n return createRemoteJWKSet(new URL(FIREBASE_SESSION_CERT_URL), {\n cacheMaxAge: 3600000, // 1 hour\n timeoutDuration: 5000, // 5 seconds\n cooldownDuration: 30000, // 30 seconds between retries\n })\n})\n\n// Helper to decode JWT without verification\nfunction decodeJwt(token: string) {\n try {\n const [headerB64, payloadB64] = token.split(\".\")\n const header = JSON.parse(Buffer.from(headerB64, \"base64\").toString())\n const payload = JSON.parse(Buffer.from(payloadB64, \"base64\").toString())\n return { header, payload }\n } catch (error) {\n console.error(\"Error decoding JWT:\", error)\n return null\n }\n}\n\nexport async function verifyFirebaseToken(token: string, isSessionCookie = false) {\n try {\n const projectId = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID\n if (!projectId) {\n throw new Error(\"Firebase Project ID is not configured\")\n }\n\n // Decode token for debugging and type checking\n const decoded = decodeJwt(token)\n if (!decoded) {\n throw new Error(\"Invalid token format\")\n }\n\n console.log(\"Token details:\", {\n header: decoded.header,\n type: isSessionCookie ? \"session_cookie\" : \"id_token\",\n })\n\n\n // Use different JWKS based on token type\n const JWKS = isSessionCookie ? await getSessionJWKS() : await getIdTokenJWKS()\n\n const { payload } = await jwtVerify(token, JWKS, {\n issuer: isSessionCookie\n ? \"https://session.firebase.google.com/\" + projectId\n : \"https://securetoken.google.com/\" + projectId,\n audience: projectId,\n algorithms: [\"RS256\"],\n })\n\n const firebasePayload = payload as unknown as FirebaseIdTokenPayload\n const now = Math.floor(Date.now() / 1000)\n\n\n if (!firebasePayload.sub) {\n throw new Error(\"Token subject is empty\")\n }\n\n return {\n valid: true,\n uid: firebasePayload.sub,\n email: firebasePayload.email,\n emailVerified: firebasePayload.email_verified,\n authTime: firebasePayload.auth_time,\n issuedAt: firebasePayload.iat,\n expiresAt: firebasePayload.exp,\n }\n } catch (error) {\n console.error(\"Token verification details:\", {\n error:\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : error,\n decoded: decodeJwt(token),\n //projectId,\n isSessionCookie,\n })\n \n return {\n valid: false,\n error: error instanceof Error ? error.message : \"Invalid token\",\n }\n }\n }"],"mappings":"AAAA,SAAS,WAAW,0BAA0B;AAC9C,SAAS,aAAa;AAqBtB,MAAM,wBAAwB;AAC9B,MAAM,4BAA4B;AAGlC,MAAM,iBAAiB,MAAM,MAAM;AACjC,SAAO,mBAAmB,IAAI,IAAI,qBAAqB,GAAG;AAAA,IACxD,aAAa;AAAA;AAAA,IACb,iBAAiB;AAAA;AAAA,IACjB,kBAAkB;AAAA;AAAA,EACpB,CAAC;AACH,CAAC;AAED,MAAM,iBAAiB,MAAM,MAAM;AACjC,SAAO,mBAAmB,IAAI,IAAI,yBAAyB,GAAG;AAAA,IAC5D,aAAa;AAAA;AAAA,IACb,iBAAiB;AAAA;AAAA,IACjB,kBAAkB;AAAA;AAAA,EACpB,CAAC;AACH,CAAC;AAGD,SAAS,UAAU,OAAe;AAChC,MAAI;AACF,UAAM,CAAC,WAAW,UAAU,IAAI,MAAM,MAAM,GAAG;AAC/C,UAAM,SAAS,KAAK,MAAM,OAAO,KAAK,WAAW,QAAQ,EAAE,SAAS,CAAC;AACrE,UAAM,UAAU,KAAK,MAAM,OAAO,KAAK,YAAY,QAAQ,EAAE,SAAS,CAAC;AACvE,WAAO,EAAE,QAAQ,QAAQ;AAAA,EAC3B,SAAS,OAAO;AACd,YAAQ,MAAM,uBAAuB,KAAK;AAC1C,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,oBAAoB,OAAe,kBAAkB,OAAO;AAChF,MAAI;AACF,UAAM,YAAY,QAAQ,IAAI;AAC9B,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AAGA,UAAM,UAAU,UAAU,KAAK;AAC/B,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,sBAAsB;AAAA,IACxC;AAEA,YAAQ,IAAI,kBAAkB;AAAA,MAC5B,QAAQ,QAAQ;AAAA,MAChB,MAAM,kBAAkB,mBAAmB;AAAA,IAC7C,CAAC;AAID,UAAM,OAAO,kBAAkB,MAAM,eAAe,IAAI,MAAM,eAAe;AAE7E,UAAM,EAAE,QAAQ,IAAI,MAAM,UAAU,OAAO,MAAM;AAAA,MAC3C,QAAQ,kBACJ,yCAAyC,YACzC,oCAAoC;AAAA,MACxC,UAAU;AAAA,MACV,YAAY,CAAC,OAAO;AAAA,IAC1B,CAAC;AAED,UAAM,kBAAkB;AACxB,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAGxC,QAAI,CAAC,gBAAgB,KAAK;AACpB,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC9C;AAEA,WAAO;AAAA,MACD,OAAO;AAAA,MACP,KAAK,gBAAgB;AAAA,MACrB,OAAO,gBAAgB;AAAA,MACvB,eAAe,gBAAgB;AAAA,MAC/B,UAAU,gBAAgB;AAAA,MAC1B,UAAU,gBAAgB;AAAA,MAC1B,WAAW,gBAAgB;AAAA,IAC7B;AAAA,EACJ,SAAS,OAAO;AACZ,YAAQ,MAAM,+BAA+B;AAAA,MAC3C,OACE,iBAAiB,QACb;AAAA,QACE,MAAM,MAAM;AAAA,QACZ,SAAS,MAAM;AAAA,QACf,OAAO,MAAM;AAAA,MACf,IACA;AAAA,MACN,SAAS,UAAU,KAAK;AAAA;AAAA,MAExB;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAClD;AAAA,EACF;AACF;","names":[]}
|
package/dist/esm/server/jwt.js
CHANGED
|
@@ -58,19 +58,9 @@ async function verifyFirebaseToken(token, isSessionCookie = false) {
|
|
|
58
58
|
algorithms: ["RS256"]
|
|
59
59
|
});
|
|
60
60
|
const firebasePayload = payload;
|
|
61
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
62
|
-
if (firebasePayload.exp <= now) {
|
|
63
|
-
throw new Error("Token has expired");
|
|
64
|
-
}
|
|
65
|
-
if (firebasePayload.iat > now) {
|
|
66
|
-
throw new Error("Token issued time is in the future");
|
|
67
|
-
}
|
|
68
61
|
if (!firebasePayload.sub) {
|
|
69
62
|
throw new Error("Token subject is empty");
|
|
70
63
|
}
|
|
71
|
-
if (firebasePayload.auth_time > now) {
|
|
72
|
-
throw new Error("Token auth time is in the future");
|
|
73
|
-
}
|
|
74
64
|
return {
|
|
75
65
|
valid: true,
|
|
76
66
|
uid: firebasePayload.sub,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/server/jwt.ts"],"sourcesContent":["import { jwtVerify, createRemoteJWKSet } from \"jose\"\nimport { cache } from \"react\"\n\ninterface FirebaseIdTokenPayload {\n iss: string\n aud: string\n auth_time: number\n user_id: string\n sub: string\n iat: number\n exp: number\n email?: string\n email_verified?: boolean\n firebase: {\n identities: {\n [key: string]: any\n }\n sign_in_provider: string\n }\n}\n\n// Firebase public key endpoints\nconst FIREBASE_ID_TOKEN_URL = \"https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com\"\nconst FIREBASE_SESSION_CERT_URL = \"https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys\"\n\n// Cache the JWKS using React cache\nconst getIdTokenJWKS = cache(() => {\n return createRemoteJWKSet(new URL(FIREBASE_ID_TOKEN_URL), {\n cacheMaxAge: 3600000, // 1 hour\n timeoutDuration: 5000, // 5 seconds\n cooldownDuration: 30000, // 30 seconds between retries\n })\n})\n\nconst getSessionJWKS = cache(() => {\n return createRemoteJWKSet(new URL(FIREBASE_SESSION_CERT_URL), {\n cacheMaxAge: 3600000, // 1 hour\n timeoutDuration: 5000, // 5 seconds\n cooldownDuration: 30000, // 30 seconds between retries\n })\n})\n\n// Helper to decode JWT without verification\nfunction decodeJwt(token: string) {\n try {\n const [headerB64, payloadB64] = token.split(\".\")\n const header = JSON.parse(Buffer.from(headerB64, \"base64\").toString())\n const payload = JSON.parse(Buffer.from(payloadB64, \"base64\").toString())\n return { header, payload }\n } catch (error) {\n console.error(\"Error decoding JWT:\", error)\n return null\n }\n}\n\nexport async function verifyFirebaseToken(token: string, isSessionCookie = false) {\n try {\n const projectId = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID\n if (!projectId) {\n throw new Error(\"Firebase Project ID is not configured\")\n }\n\n // Decode token for debugging and type checking\n const decoded = decodeJwt(token)\n if (!decoded) {\n throw new Error(\"Invalid token format\")\n }\n\n console.log(\"Token details:\", {\n header: decoded.header,\n type: isSessionCookie ? \"session_cookie\" : \"id_token\",\n })\n\n let retries = 3\n let lastError: Error | null = null\n\n while (retries > 0) {\n try {\n // Use different JWKS based on token type\n const JWKS = isSessionCookie ? await getSessionJWKS() : await getIdTokenJWKS()\n\n const { payload } = await jwtVerify(token, JWKS, {\n issuer: isSessionCookie\n ? \"https://session.firebase.google.com/\" + projectId\n : \"https://securetoken.google.com/\" + projectId,\n audience: projectId,\n algorithms: [\"RS256\"],\n })\n\n const firebasePayload = payload as unknown as FirebaseIdTokenPayload\n
|
|
1
|
+
{"version":3,"sources":["../../../src/server/jwt.ts"],"sourcesContent":["import { jwtVerify, createRemoteJWKSet } from \"jose\"\nimport { cache } from \"react\"\n\ninterface FirebaseIdTokenPayload {\n iss: string\n aud: string\n auth_time: number\n user_id: string\n sub: string\n iat: number\n exp: number\n email?: string\n email_verified?: boolean\n firebase: {\n identities: {\n [key: string]: any\n }\n sign_in_provider: string\n }\n}\n\n// Firebase public key endpoints\nconst FIREBASE_ID_TOKEN_URL = \"https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com\"\nconst FIREBASE_SESSION_CERT_URL = \"https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys\"\n\n// Cache the JWKS using React cache\nconst getIdTokenJWKS = cache(() => {\n return createRemoteJWKSet(new URL(FIREBASE_ID_TOKEN_URL), {\n cacheMaxAge: 3600000, // 1 hour\n timeoutDuration: 5000, // 5 seconds\n cooldownDuration: 30000, // 30 seconds between retries\n })\n})\n\nconst getSessionJWKS = cache(() => {\n return createRemoteJWKSet(new URL(FIREBASE_SESSION_CERT_URL), {\n cacheMaxAge: 3600000, // 1 hour\n timeoutDuration: 5000, // 5 seconds\n cooldownDuration: 30000, // 30 seconds between retries\n })\n})\n\n// Helper to decode JWT without verification\nfunction decodeJwt(token: string) {\n try {\n const [headerB64, payloadB64] = token.split(\".\")\n const header = JSON.parse(Buffer.from(headerB64, \"base64\").toString())\n const payload = JSON.parse(Buffer.from(payloadB64, \"base64\").toString())\n return { header, payload }\n } catch (error) {\n console.error(\"Error decoding JWT:\", error)\n return null\n }\n}\n\nexport async function verifyFirebaseToken(token: string, isSessionCookie = false) {\n try {\n const projectId = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID\n if (!projectId) {\n throw new Error(\"Firebase Project ID is not configured\")\n }\n\n // Decode token for debugging and type checking\n const decoded = decodeJwt(token)\n if (!decoded) {\n throw new Error(\"Invalid token format\")\n }\n\n console.log(\"Token details:\", {\n header: decoded.header,\n type: isSessionCookie ? \"session_cookie\" : \"id_token\",\n })\n\n let retries = 3\n let lastError: Error | null = null\n\n while (retries > 0) {\n try {\n // Use different JWKS based on token type\n const JWKS = isSessionCookie ? await getSessionJWKS() : await getIdTokenJWKS()\n\n const { payload } = await jwtVerify(token, JWKS, {\n issuer: isSessionCookie\n ? \"https://session.firebase.google.com/\" + projectId\n : \"https://securetoken.google.com/\" + projectId,\n audience: projectId,\n algorithms: [\"RS256\"],\n })\n\n const firebasePayload = payload as unknown as FirebaseIdTokenPayload\n\n if (!firebasePayload.sub) {\n throw new Error(\"Token subject is empty\")\n }\n\n return {\n valid: true,\n uid: firebasePayload.sub,\n email: firebasePayload.email,\n emailVerified: firebasePayload.email_verified,\n authTime: firebasePayload.auth_time,\n issuedAt: firebasePayload.iat,\n expiresAt: firebasePayload.exp,\n }\n } catch (error) {\n lastError = error as Error\n if (error instanceof Error && error.name === \"JWKSNoMatchingKey\") {\n console.warn(`JWKS retry attempt ${4 - retries}:`, error.message)\n retries--\n if (retries > 0) {\n await new Promise((resolve) => setTimeout(resolve, 1000))\n continue\n }\n }\n throw error\n }\n }\n\n throw lastError || new Error(\"Failed to verify token after retries\")\n } catch (error) {\n console.error(\"Token verification details:\", {\n error:\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : error,\n decoded: decodeJwt(token),\n //projectId,\n isSessionCookie,\n })\n\n return {\n valid: false,\n error: error instanceof Error ? error.message : \"Invalid token\",\n }\n }\n}"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { cache } from "react";
|
|
2
|
+
class SessionStore {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.currentSessionId = null;
|
|
5
|
+
this.sessions = /* @__PURE__ */ new Map();
|
|
6
|
+
}
|
|
7
|
+
static getInstance() {
|
|
8
|
+
if (!SessionStore.instance) {
|
|
9
|
+
SessionStore.instance = new SessionStore();
|
|
10
|
+
}
|
|
11
|
+
return SessionStore.instance;
|
|
12
|
+
}
|
|
13
|
+
setUser(sessionId, user) {
|
|
14
|
+
console.log("SessionStore: Setting user:", { sessionId, user });
|
|
15
|
+
this.sessions.set(sessionId, user);
|
|
16
|
+
this.currentSessionId = sessionId;
|
|
17
|
+
}
|
|
18
|
+
getUser(sessionId) {
|
|
19
|
+
return this.sessions.get(sessionId) || null;
|
|
20
|
+
}
|
|
21
|
+
getCurrentUser() {
|
|
22
|
+
if (!this.currentSessionId) return null;
|
|
23
|
+
return this.sessions.get(this.currentSessionId) || null;
|
|
24
|
+
}
|
|
25
|
+
removeUser(sessionId) {
|
|
26
|
+
this.sessions.delete(sessionId);
|
|
27
|
+
}
|
|
28
|
+
clear() {
|
|
29
|
+
this.sessions.clear();
|
|
30
|
+
}
|
|
31
|
+
debug() {
|
|
32
|
+
return {
|
|
33
|
+
sessionsCount: this.sessions.size,
|
|
34
|
+
currentSessionId: this.currentSessionId,
|
|
35
|
+
sessions: Array.from(this.sessions.entries())
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const sessionStore = SessionStore.getInstance();
|
|
40
|
+
const getVerifiedUser = cache((sessionId) => {
|
|
41
|
+
return sessionStore.getUser(sessionId);
|
|
42
|
+
});
|
|
43
|
+
export {
|
|
44
|
+
getVerifiedUser,
|
|
45
|
+
sessionStore
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=session-store.js.map
|