@tern-secure/nextjs 4.2.0 → 4.2.2

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.
Files changed (87) hide show
  1. package/dist/cjs/app-router/{server → admin}/index.js +4 -14
  2. package/dist/cjs/app-router/admin/index.js.map +1 -0
  3. package/dist/cjs/app-router/admin/sessionTernSecure.js.map +1 -0
  4. package/dist/cjs/components/sign-in.js +1 -1
  5. package/dist/cjs/components/sign-in.js.map +1 -1
  6. package/dist/cjs/components/sign-out-button.js +1 -1
  7. package/dist/cjs/components/sign-out-button.js.map +1 -1
  8. package/dist/cjs/components/sign-out.js +1 -1
  9. package/dist/cjs/components/sign-out.js.map +1 -1
  10. package/dist/cjs/{app-router/server → server}/auth.js +1 -1
  11. package/dist/cjs/server/auth.js.map +1 -0
  12. package/dist/cjs/{app-router/server → server}/edge-session.js +5 -7
  13. package/dist/cjs/server/edge-session.js.map +1 -0
  14. package/dist/cjs/server/index.js +36 -0
  15. package/dist/cjs/server/index.js.map +1 -0
  16. package/dist/cjs/server/jwt-edge.js +123 -0
  17. package/dist/cjs/server/jwt-edge.js.map +1 -0
  18. package/dist/cjs/server/jwt.js.map +1 -0
  19. package/dist/cjs/{app-router/server → server}/ternSecureMiddleware.js +1 -55
  20. package/dist/cjs/server/ternSecureMiddleware.js.map +1 -0
  21. package/dist/cjs/server/types.js +17 -0
  22. package/dist/cjs/server/types.js.map +1 -0
  23. package/dist/esm/app-router/{server → admin}/index.js +1 -7
  24. package/dist/esm/app-router/admin/index.js.map +1 -0
  25. package/dist/esm/app-router/admin/sessionTernSecure.js.map +1 -0
  26. package/dist/esm/components/sign-in.js +1 -1
  27. package/dist/esm/components/sign-in.js.map +1 -1
  28. package/dist/esm/components/sign-out-button.js +1 -1
  29. package/dist/esm/components/sign-out-button.js.map +1 -1
  30. package/dist/esm/components/sign-out.js +1 -1
  31. package/dist/esm/components/sign-out.js.map +1 -1
  32. package/dist/esm/{app-router/server → server}/auth.js +1 -1
  33. package/dist/esm/server/auth.js.map +1 -0
  34. package/dist/esm/{app-router/server → server}/edge-session.js +3 -5
  35. package/dist/esm/server/edge-session.js.map +1 -0
  36. package/dist/esm/server/index.js +9 -0
  37. package/dist/esm/server/index.js.map +1 -0
  38. package/dist/esm/server/jwt-edge.js +99 -0
  39. package/dist/esm/server/jwt-edge.js.map +1 -0
  40. package/dist/esm/server/jwt.js.map +1 -0
  41. package/dist/esm/{app-router/server → server}/ternSecureMiddleware.js +1 -55
  42. package/dist/esm/server/ternSecureMiddleware.js.map +1 -0
  43. package/dist/esm/server/types.js +1 -0
  44. package/dist/esm/server/types.js.map +1 -0
  45. package/dist/types/app-router/admin/index.d.ts +3 -0
  46. package/dist/types/app-router/admin/index.d.ts.map +1 -0
  47. package/dist/types/app-router/admin/sessionTernSecure.d.ts.map +1 -0
  48. package/dist/types/{app-router/server → server}/auth.d.ts +1 -1
  49. package/dist/types/server/auth.d.ts.map +1 -0
  50. package/dist/types/server/edge-session.d.ts +4 -0
  51. package/dist/types/server/edge-session.d.ts.map +1 -0
  52. package/dist/types/server/index.d.ts +5 -0
  53. package/dist/types/server/index.d.ts.map +1 -0
  54. package/dist/types/server/jwt-edge.d.ts +20 -0
  55. package/dist/types/server/jwt-edge.d.ts.map +1 -0
  56. package/dist/types/server/jwt.d.ts.map +1 -0
  57. package/dist/types/{app-router/server → server}/ternSecureMiddleware.d.ts +1 -1
  58. package/dist/types/server/ternSecureMiddleware.d.ts.map +1 -0
  59. package/dist/types/{app-router/server/edge-session.d.ts → server/types.d.ts} +1 -3
  60. package/dist/types/server/types.d.ts.map +1 -0
  61. package/package.json +12 -5
  62. package/server/package.json +5 -0
  63. package/dist/cjs/app-router/server/auth.js.map +0 -1
  64. package/dist/cjs/app-router/server/edge-session.js.map +0 -1
  65. package/dist/cjs/app-router/server/index.js.map +0 -1
  66. package/dist/cjs/app-router/server/jwt.js.map +0 -1
  67. package/dist/cjs/app-router/server/sessionTernSecure.js.map +0 -1
  68. package/dist/cjs/app-router/server/ternSecureMiddleware.js.map +0 -1
  69. package/dist/esm/app-router/server/auth.js.map +0 -1
  70. package/dist/esm/app-router/server/edge-session.js.map +0 -1
  71. package/dist/esm/app-router/server/index.js.map +0 -1
  72. package/dist/esm/app-router/server/jwt.js.map +0 -1
  73. package/dist/esm/app-router/server/sessionTernSecure.js.map +0 -1
  74. package/dist/esm/app-router/server/ternSecureMiddleware.js.map +0 -1
  75. package/dist/types/app-router/server/auth.d.ts.map +0 -1
  76. package/dist/types/app-router/server/edge-session.d.ts.map +0 -1
  77. package/dist/types/app-router/server/index.d.ts +0 -6
  78. package/dist/types/app-router/server/index.d.ts.map +0 -1
  79. package/dist/types/app-router/server/jwt.d.ts.map +0 -1
  80. package/dist/types/app-router/server/sessionTernSecure.d.ts.map +0 -1
  81. package/dist/types/app-router/server/ternSecureMiddleware.d.ts.map +0 -1
  82. /package/dist/cjs/app-router/{server → admin}/sessionTernSecure.js +0 -0
  83. /package/dist/cjs/{app-router/server → server}/jwt.js +0 -0
  84. /package/dist/esm/app-router/{server → admin}/sessionTernSecure.js +0 -0
  85. /package/dist/esm/{app-router/server → server}/jwt.js +0 -0
  86. /package/dist/types/app-router/{server → admin}/sessionTernSecure.d.ts +0 -0
  87. /package/dist/types/{app-router/server → server}/jwt.d.ts +0 -0
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
+ var types_exports = {};
16
+ module.exports = __toCommonJS(types_exports);
17
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/server/types.ts"],"sourcesContent":["export interface UserInfo {\n uid: string\n email: string | null\n emailVerified?: boolean\n authTime?: number\n disabled?: boolean\n }\n \n \n export interface SessionResult {\n isAuthenticated: boolean\n user: UserInfo | null\n error?: string\n }"],"mappings":";;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
@@ -1,15 +1,9 @@
1
- import { adminTernSecureAuth, adminTernSecureDb } from "../../utils/admin-init";
2
- import { ternSecureMiddleware, createRouteMatcher } from "./ternSecureMiddleware";
3
1
  import { verifyTernSessionCookie, createSessionCookie } from "./sessionTernSecure";
4
- import { auth, getUserInfo } from "./auth";
2
+ import { adminTernSecureAuth, adminTernSecureDb } from "../../utils/admin-init";
5
3
  export {
6
4
  adminTernSecureAuth,
7
5
  adminTernSecureDb,
8
- auth,
9
- createRouteMatcher,
10
6
  createSessionCookie,
11
- getUserInfo,
12
- ternSecureMiddleware,
13
7
  verifyTernSessionCookie
14
8
  };
15
9
  //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/app-router/admin/index.ts"],"sourcesContent":["export { verifyTernSessionCookie, createSessionCookie } from './sessionTernSecure'\nexport { adminTernSecureAuth, adminTernSecureDb } from '../../utils/admin-init'"],"mappings":"AAAA,SAAS,yBAAyB,2BAA2B;AAC7D,SAAS,qBAAqB,yBAAyB;","names":[]}
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/app-router/admin/sessionTernSecure.ts"],"sourcesContent":["'use server'\n\nimport { cookies } from 'next/headers';\nimport { adminTernSecureAuth as adminAuth } from '../../utils/admin-init';\n\ninterface FirebaseAuthError extends Error {\n code?: string;\n}\n\nexport interface User {\n uid: string | null;\n email: string | null;\n }\n\nexport interface Session {\n user: User | null;\n token: string | null;\n error: Error | null;\n}\n\nexport async function createSessionCookie(idToken: string) {\n try {\n const expiresIn = 60 * 60 * 24 * 5 * 1000;\n const sessionCookie = await adminAuth.createSessionCookie(idToken, { expiresIn });\n\n const cookieStore = await cookies();\n cookieStore.set('_session_cookie', sessionCookie, {\n maxAge: expiresIn,\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n path: '/',\n });\n return { success: true, message: 'Session created' };\n } catch (error) {\n return { success: false, message: 'Failed to create session' };\n }\n}\n\n\n\nexport async function getServerSessionCookie() {\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\n\n if (!sessionCookie) {\n throw new Error('No session cookie found')\n }\n \n try {\n const decondeClaims = await adminAuth.verifySessionCookie(sessionCookie, true)\n return {\n token: sessionCookie,\n userId: decondeClaims.uid\n }\n } catch (error) {\n console.error('Error verifying session:', error)\n throw new Error('Invalid Session')\n }\n}\n\n\nexport async function getIdToken() {\n const cookieStore = await cookies();\n const token = cookieStore.get('_session_token')?.value;\n\n if (!token) {\n throw new Error('No session cookie found')\n }\n \n try {\n const decodedClaims = await adminAuth.verifyIdToken(token)\n return {\n token: token,\n userId: decodedClaims.uid\n }\n } catch (error) {\n console.error('Error verifying session:', error)\n throw new Error('Invalid Session')\n }\n}\n\nexport async function setServerSession(token: string) {\n try {\n const cookieStore = await cookies();\n cookieStore.set('_session_token', token, {\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'strict',\n maxAge: 60 * 60, // 1 hour\n path: '/',\n });\n return { success: true, message: 'Session created' };\n } catch {\n return { success: false, message: 'Failed to create session' };\n }\n}\n\n export async function verifyTernIdToken(token: string): Promise<{ valid: boolean; uid?: string; error?: string }> {\n try {\n const decodedToken = await adminAuth.verifyIdToken(token, true);\n return { valid: true, uid: decodedToken.uid };\n } catch (error) {\n if (error instanceof Error) {\n const firebaseError = error as FirebaseAuthError;\n if (error.name === 'FirebaseAuthError') {\n // Handle specific Firebase Auth errors\n switch (firebaseError.code) {\n case 'auth/id-token-expired':\n return { valid: false, error: 'Token has expired' };\n case 'auth/id-token-revoked':\n return { valid: false, error: 'Token has been revoked' };\n case 'auth/user-disabled':\n return { valid: false, error: 'User account has been disabled' };\n default:\n return { valid: false, error: 'Invalid token' };\n }\n }\n }\n return { valid: false, error: 'Error verifying token' };\n }\n }\n \n\n export async function verifyTernSessionCookie(session: string): Promise<{ valid: boolean; uid?: any; error?: any }>{\n try {\n const res = await adminAuth.verifySessionCookie(session, true);\n if (res) {\n return { valid: true, uid: res.uid };\n } else {\n return { valid: false, error: 'Invalid session'};\n }\n } catch (error) {\n return {error: error, valid: false}\n }\n }\n\n\n export async function clearSessionCookie() {\n const cookieStore = await cookies()\n \n cookieStore.delete('_session_cookie')\n cookieStore.delete('_session_token')\n cookieStore.delete('_session')\n \n try {\n // Verify if there's an active session before revoking\n const sessionCookie = cookieStore.get('_session_cookie')?.value\n if (sessionCookie) {\n // Get the decoded claims to get the user's ID\n const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie)\n \n // Revoke all sessions for the user\n await adminAuth.revokeRefreshTokens(decodedClaims.uid)\n }\n \n return { success: true, message: 'Session cleared successfully' }\n } catch (error) {\n console.error('Error clearing session:', error)\n // Still return success even if revoking fails, as cookies are cleared\n return { success: true, message: 'Session cookies cleared' }\n }\n }\n\n\n\n/*\n export async function GET(request: NextRequest) {\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get('session')?.value\n \n if (!sessionCookie) {\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\n }\n \n try {\n const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie, true)\n return NextResponse.json({ isAuthenticated: true, user: decodedClaims }, { status: 200 })\n } catch (error) {\n console.error('Error verifying session cookie:', error)\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\n }\n }\n\n*/"],"mappings":";AAEA,SAAS,eAAe;AACxB,SAAS,uBAAuB,iBAAiB;AAiBjD,eAAsB,oBAAoB,SAAiB;AACzD,MAAI;AACF,UAAM,YAAY,KAAK,KAAK,KAAK,IAAI;AACnC,UAAM,gBAAgB,MAAM,UAAU,oBAAoB,SAAS,EAAE,UAAU,CAAC;AAEhF,UAAM,cAAc,MAAM,QAAQ;AAClC,gBAAY,IAAI,mBAAmB,eAAe;AAAA,MAC9C,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,MACjC,MAAM;AAAA,IACV,CAAC;AACD,WAAO,EAAE,SAAS,MAAM,SAAS,kBAAkB;AAAA,EACvD,SAAS,OAAO;AACZ,WAAO,EAAE,SAAS,OAAO,SAAS,2BAA2B;AAAA,EACjE;AACF;AAIA,eAAsB,yBAAyB;AAxC/C;AAyCE,QAAM,cAAc,MAAM,QAAQ;AAClC,QAAM,iBAAgB,iBAAY,IAAI,iBAAiB,MAAjC,mBAAoC;AAE1D,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC3C;AAEA,MAAI;AACF,UAAM,gBAAgB,MAAM,UAAU,oBAAoB,eAAe,IAAI;AAC7E,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,cAAc;AAAA,IACxB;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,4BAA4B,KAAK;AAC/C,UAAM,IAAI,MAAM,iBAAiB;AAAA,EACnC;AACF;AAGA,eAAsB,aAAa;AA7DnC;AA8DE,QAAM,cAAc,MAAM,QAAQ;AAClC,QAAM,SAAQ,iBAAY,IAAI,gBAAgB,MAAhC,mBAAmC;AAEjD,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC3C;AAEA,MAAI;AACF,UAAM,gBAAgB,MAAM,UAAU,cAAc,KAAK;AACzD,WAAO;AAAA,MACL;AAAA,MACA,QAAQ,cAAc;AAAA,IACxB;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,4BAA4B,KAAK;AAC/C,UAAM,IAAI,MAAM,iBAAiB;AAAA,EACnC;AACF;AAEA,eAAsB,iBAAiB,OAAe;AACpD,MAAI;AACF,UAAM,cAAc,MAAM,QAAQ;AAClC,gBAAY,IAAI,kBAAkB,OAAO;AAAA,MACvC,UAAU;AAAA,MACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,MACjC,UAAU;AAAA,MACV,QAAQ,KAAK;AAAA;AAAA,MACb,MAAM;AAAA,IACR,CAAC;AACD,WAAO,EAAE,SAAS,MAAM,SAAS,kBAAkB;AAAA,EACrD,QAAQ;AACN,WAAO,EAAE,SAAS,OAAO,SAAS,2BAA2B;AAAA,EAC/D;AACF;AAEE,eAAsB,kBAAkB,OAA0E;AAChH,MAAI;AACF,UAAM,eAAe,MAAM,UAAU,cAAc,OAAO,IAAI;AAC9D,WAAO,EAAE,OAAO,MAAM,KAAK,aAAa,IAAI;AAAA,EAC9C,SAAS,OAAO;AACd,QAAI,iBAAiB,OAAO;AAC1B,YAAM,gBAAgB;AACtB,UAAI,MAAM,SAAS,qBAAqB;AAEtC,gBAAQ,cAAc,MAAM;AAAA,UAC1B,KAAK;AACH,mBAAO,EAAE,OAAO,OAAO,OAAO,oBAAoB;AAAA,UACpD,KAAK;AACH,mBAAO,EAAE,OAAO,OAAO,OAAO,yBAAyB;AAAA,UACzD,KAAK;AACH,mBAAO,EAAE,OAAO,OAAO,OAAO,iCAAiC;AAAA,UACjE;AACE,mBAAO,EAAE,OAAO,OAAO,OAAO,gBAAgB;AAAA,QAClD;AAAA,MACF;AAAA,IACF;AACA,WAAO,EAAE,OAAO,OAAO,OAAO,wBAAwB;AAAA,EACxD;AACF;AAGA,eAAsB,wBAAwB,SAAqE;AACjH,MAAI;AACF,UAAM,MAAM,MAAM,UAAU,oBAAoB,SAAS,IAAI;AAC7D,QAAI,KAAK;AACP,aAAO,EAAE,OAAO,MAAM,KAAK,IAAI,IAAI;AAAA,IACrC,OAAO;AACL,aAAO,EAAE,OAAO,OAAO,OAAO,kBAAiB;AAAA,IACjD;AAAA,EACF,SAAS,OAAO;AACd,WAAO,EAAC,OAAc,OAAO,MAAK;AAAA,EACpC;AACF;AAGA,eAAsB,qBAAqB;AAzI7C;AA0II,QAAM,cAAc,MAAM,QAAQ;AAElC,cAAY,OAAO,iBAAiB;AACpC,cAAY,OAAO,gBAAgB;AACnC,cAAY,OAAO,UAAU;AAE7B,MAAI;AAEF,UAAM,iBAAgB,iBAAY,IAAI,iBAAiB,MAAjC,mBAAoC;AAC1D,QAAI,eAAe;AAEjB,YAAM,gBAAgB,MAAM,UAAU,oBAAoB,aAAa;AAGvE,YAAM,UAAU,oBAAoB,cAAc,GAAG;AAAA,IACvD;AAEA,WAAO,EAAE,SAAS,MAAM,SAAS,+BAA+B;AAAA,EAClE,SAAS,OAAO;AACd,YAAQ,MAAM,2BAA2B,KAAK;AAE9C,WAAO,EAAE,SAAS,MAAM,SAAS,0BAA0B;AAAA,EAC7D;AACF;","names":[]}
@@ -13,7 +13,7 @@ import { cn } from "../lib/utils";
13
13
  import { Loader2, Eye, EyeOff } from "lucide-react";
14
14
  import { getRedirectResult } from "firebase/auth";
15
15
  import { ternSecureAuth } from "../utils/client-init";
16
- import { createSessionCookie } from "../app-router/server/sessionTernSecure";
16
+ import { createSessionCookie } from "../app-router/admin/sessionTernSecure";
17
17
  import { AuthBackground } from "./background";
18
18
  import { getValidRedirectUrl } from "../utils/construct";
19
19
  import { handleInternalRoute } from "../app-router/route-handler/internal-route";
@@ -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/server/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&apos;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, 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&apos;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"]}
@@ -5,7 +5,7 @@ import { usePathname, useRouter } from "next/navigation";
5
5
  import { signOut } from "firebase/auth";
6
6
  import { Button } from "./ui/button";
7
7
  import { ternSecureAuth } from "../utils/client-init";
8
- import { clearSessionCookie } from "../app-router/server/sessionTernSecure";
8
+ import { clearSessionCookie } from "../app-router/admin/sessionTernSecure";
9
9
  import { cn } from "../lib/utils";
10
10
  import { constructUrlWithRedirect } from "../utils/construct";
11
11
  function SignOutButton({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/sign-out-button.tsx"],"sourcesContent":["'use client'\n\nimport { useState } from 'react'\nimport { usePathname, useRouter } from 'next/navigation'\nimport { signOut } from 'firebase/auth'\nimport { Button, type ButtonProps } from './ui/button'\nimport { ternSecureAuth } from '../utils/client-init'\nimport { clearSessionCookie } from '../app-router/server/sessionTernSecure'\nimport { cn } from '../lib/utils'\nimport { constructUrlWithRedirect } from '../utils/construct'\n\n\ntype SignOutCustomProps = {\n children?: React.ReactNode\n onError?: (error: Error) => void\n onSignOutSuccess?: () => void\n redirectPath?: string\n className?: string\n variant?: ButtonProps['variant']\n size?: ButtonProps['size']\n}\n\ntype SignOutProps = Omit<ButtonProps, 'onClick'> & SignOutCustomProps\n\nexport function SignOutButton({ \n children = 'Sign out', \n onError,\n onSignOutSuccess,\n redirectPath,\n className,\n variant = 'outline',\n size = 'default',\n ...buttonProps \n}: SignOutProps) {\n const pathname = usePathname()\n const router = useRouter()\n const [isLoading, setIsLoading] = useState(false)\n const loginPath = process.env.NEXT_PUBLIC_LOGIN_PATH || '/sign-in'\n\n const handleSignOut = async () => {\n setIsLoading(true)\n try {\n // Sign out from Firebase\n await signOut(ternSecureAuth)\n \n await clearSessionCookie()\n \n // Call success callback if provided\n onSignOutSuccess?.()\n\n // Construct login URL with redirect parameter\n const loginUrl = constructUrlWithRedirect(loginPath, pathname)\n\n // Use router for development and window.location for production\n if (process.env.NODE_ENV === \"production\") {\n window.location.href = loginUrl\n } else {\n router.push(loginUrl)\n }\n } catch (error) {\n console.error('Sign out error:', error)\n onError?.(error instanceof Error ? error : new Error('Failed to sign out'))\n } finally {\n setIsLoading(false)\n }\n }\n\n return (\n <Button\n variant={variant}\n size={size}\n onClick={handleSignOut}\n disabled={isLoading}\n className={cn(\"\", className)}\n {...buttonProps}\n >\n {isLoading ? 'Signing out...' : children}\n </Button>\n )\n}\n\n"],"mappings":";AAoEI;AAlEJ,SAAS,gBAAgB;AACzB,SAAS,aAAa,iBAAiB;AACvC,SAAS,eAAe;AACxB,SAAS,cAAgC;AACzC,SAAS,sBAAsB;AAC/B,SAAS,0BAA0B;AACnC,SAAS,UAAU;AACnB,SAAS,gCAAgC;AAelC,SAAS,cAAc;AAAA,EAC5B,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,OAAO;AAAA,EACP,GAAG;AACL,GAAiB;AACf,QAAM,WAAW,YAAY;AAC7B,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,QAAM,YAAY,QAAQ,IAAI,0BAA0B;AAExD,QAAM,gBAAgB,YAAY;AAChC,iBAAa,IAAI;AACjB,QAAI;AAEF,YAAM,QAAQ,cAAc;AAE5B,YAAM,mBAAmB;AAGzB;AAGA,YAAM,WAAW,yBAAyB,WAAW,QAAQ;AAG7D,UAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,eAAO,SAAS,OAAO;AAAA,MACzB,OAAO;AACL,eAAO,KAAK,QAAQ;AAAA,MACtB;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,mBAAmB,KAAK;AACtC,yCAAU,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,oBAAoB;AAAA,IAC3E,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,UAAU;AAAA,MACV,WAAW,GAAG,IAAI,SAAS;AAAA,MAC1B,GAAG;AAAA,MAEH,sBAAY,mBAAmB;AAAA;AAAA,EAClC;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/sign-out-button.tsx"],"sourcesContent":["'use client'\n\nimport { useState } from 'react'\nimport { usePathname, useRouter } from 'next/navigation'\nimport { signOut } from 'firebase/auth'\nimport { Button, type ButtonProps } from './ui/button'\nimport { ternSecureAuth } from '../utils/client-init'\nimport { clearSessionCookie } from '../app-router/admin/sessionTernSecure'\nimport { cn } from '../lib/utils'\nimport { constructUrlWithRedirect } from '../utils/construct'\n\n\ntype SignOutCustomProps = {\n children?: React.ReactNode\n onError?: (error: Error) => void\n onSignOutSuccess?: () => void\n redirectPath?: string\n className?: string\n variant?: ButtonProps['variant']\n size?: ButtonProps['size']\n}\n\ntype SignOutProps = Omit<ButtonProps, 'onClick'> & SignOutCustomProps\n\nexport function SignOutButton({ \n children = 'Sign out', \n onError,\n onSignOutSuccess,\n redirectPath,\n className,\n variant = 'outline',\n size = 'default',\n ...buttonProps \n}: SignOutProps) {\n const pathname = usePathname()\n const router = useRouter()\n const [isLoading, setIsLoading] = useState(false)\n const loginPath = process.env.NEXT_PUBLIC_LOGIN_PATH || '/sign-in'\n\n const handleSignOut = async () => {\n setIsLoading(true)\n try {\n // Sign out from Firebase\n await signOut(ternSecureAuth)\n \n await clearSessionCookie()\n \n // Call success callback if provided\n onSignOutSuccess?.()\n\n // Construct login URL with redirect parameter\n const loginUrl = constructUrlWithRedirect(loginPath, pathname)\n\n // Use router for development and window.location for production\n if (process.env.NODE_ENV === \"production\") {\n window.location.href = loginUrl\n } else {\n router.push(loginUrl)\n }\n } catch (error) {\n console.error('Sign out error:', error)\n onError?.(error instanceof Error ? error : new Error('Failed to sign out'))\n } finally {\n setIsLoading(false)\n }\n }\n\n return (\n <Button\n variant={variant}\n size={size}\n onClick={handleSignOut}\n disabled={isLoading}\n className={cn(\"\", className)}\n {...buttonProps}\n >\n {isLoading ? 'Signing out...' : children}\n </Button>\n )\n}\n\n"],"mappings":";AAoEI;AAlEJ,SAAS,gBAAgB;AACzB,SAAS,aAAa,iBAAiB;AACvC,SAAS,eAAe;AACxB,SAAS,cAAgC;AACzC,SAAS,sBAAsB;AAC/B,SAAS,0BAA0B;AACnC,SAAS,UAAU;AACnB,SAAS,gCAAgC;AAelC,SAAS,cAAc;AAAA,EAC5B,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,OAAO;AAAA,EACP,GAAG;AACL,GAAiB;AACf,QAAM,WAAW,YAAY;AAC7B,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,QAAM,YAAY,QAAQ,IAAI,0BAA0B;AAExD,QAAM,gBAAgB,YAAY;AAChC,iBAAa,IAAI;AACjB,QAAI;AAEF,YAAM,QAAQ,cAAc;AAE5B,YAAM,mBAAmB;AAGzB;AAGA,YAAM,WAAW,yBAAyB,WAAW,QAAQ;AAG7D,UAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,eAAO,SAAS,OAAO;AAAA,MACzB,OAAO;AACL,eAAO,KAAK,QAAQ;AAAA,MACtB;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,mBAAmB,KAAK;AACtC,yCAAU,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,oBAAoB;AAAA,IAC3E,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT,UAAU;AAAA,MACV,WAAW,GAAG,IAAI,SAAS;AAAA,MAC1B,GAAG;AAAA,MAEH,sBAAY,mBAAmB;AAAA;AAAA,EAClC;AAEJ;","names":[]}
@@ -4,7 +4,7 @@ import { useState } from "react";
4
4
  import { usePathname, useRouter } from "next/navigation";
5
5
  import { signOut } from "firebase/auth";
6
6
  import { ternSecureAuth } from "../utils/client-init";
7
- import { clearSessionCookie } from "../app-router/server/sessionTernSecure";
7
+ import { clearSessionCookie } from "../app-router/admin/sessionTernSecure";
8
8
  import { cn } from "../lib/utils";
9
9
  import Link from "next/link";
10
10
  import { constructUrlWithRedirect } from "../utils/construct";
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/sign-out.tsx"],"sourcesContent":["'use client'\n\nimport { useState } from 'react'\nimport { usePathname, useRouter } from 'next/navigation'\nimport { signOut } from 'firebase/auth'\nimport { ternSecureAuth } from '../utils/client-init'\nimport { clearSessionCookie } from '../app-router/server/sessionTernSecure'\nimport { cn } from '../lib/utils'\nimport Link from 'next/link'\nimport { constructUrlWithRedirect } from '../utils/construct'\n\n\ninterface SignOutLinkProps {\n children?: React.ReactNode\n onError?: (error: Error) => void\n onSignOutSuccess?: () => void\n className?: string\n activeClassName?: string\n disabled?: boolean\n redirectPath?: string\n}\n\nexport function SignOut({\n children = 'Sign out',\n onError,\n onSignOutSuccess,\n className,\n activeClassName,\n disabled = false,\n redirectPath,\n}: SignOutLinkProps) {\n const [isLoading, setIsLoading] = useState(false)\n const pathname = usePathname()\n const router = useRouter()\n const loginPath = process.env.NEXT_PUBLIC_LOGIN_PATH || \"/sign-in\"\n\n const handleSignOut = async (e: React.MouseEvent<HTMLAnchorElement>) => {\n e.preventDefault()\n if (disabled || isLoading) return\n\n setIsLoading(true)\n try {\n // Sign out from Firebase\n await signOut(ternSecureAuth)\n\n // Clear the session cookie\n await clearSessionCookie()\n\n // Call success callback if provided\n onSignOutSuccess?.()\n\n // Construct login URL with redirect parameter\n const loginUrl = constructUrlWithRedirect(loginPath, pathname)\n\n // Use router for development and window.location for production\n if (process.env.NODE_ENV === \"production\") {\n window.location.href = loginUrl\n } else {\n router.push(loginUrl)\n }\n } catch (error) {\n console.error('Sign out error:', error)\n onError?.(error instanceof Error ? error : new Error('Failed to sign out'))\n } finally {\n setIsLoading(false)\n }\n }\n\n return (\n <Link\n href=\"#\"\n onClick={handleSignOut}\n className={cn(\n 'text-sm font-medium transition-colors hover:text-primary',\n disabled && 'pointer-events-none opacity-50',\n isLoading && 'pointer-events-none',\n className,\n isLoading && activeClassName\n )}\n aria-disabled={disabled || isLoading}\n >\n {isLoading ? 'Signing out...' : children}\n </Link>\n )\n}"],"mappings":";AAqEI;AAnEJ,SAAS,gBAAgB;AACzB,SAAS,aAAa,iBAAiB;AACvC,SAAS,eAAe;AACxB,SAAS,sBAAsB;AAC/B,SAAS,0BAA0B;AACnC,SAAS,UAAU;AACnB,OAAO,UAAU;AACjB,SAAS,gCAAgC;AAalC,SAAS,QAAQ;AAAA,EACtB,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AACF,GAAqB;AACnB,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,QAAM,WAAW,YAAY;AAC7B,QAAM,SAAS,UAAU;AACzB,QAAM,YAAY,QAAQ,IAAI,0BAA0B;AAExD,QAAM,gBAAgB,OAAO,MAA2C;AACtE,MAAE,eAAe;AACjB,QAAI,YAAY,UAAW;AAE3B,iBAAa,IAAI;AACjB,QAAI;AAEF,YAAM,QAAQ,cAAc;AAG5B,YAAM,mBAAmB;AAGzB;AAGA,YAAM,WAAW,yBAAyB,WAAW,QAAQ;AAG7D,UAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,eAAO,SAAS,OAAO;AAAA,MACzB,OAAO;AACL,eAAO,KAAK,QAAQ;AAAA,MACtB;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,mBAAmB,KAAK;AACtC,yCAAU,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,oBAAoB;AAAA,IAC3E,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAS;AAAA,MACT,WAAW;AAAA,QACT;AAAA,QACA,YAAY;AAAA,QACZ,aAAa;AAAA,QACb;AAAA,QACA,aAAa;AAAA,MACf;AAAA,MACA,iBAAe,YAAY;AAAA,MAE1B,sBAAY,mBAAmB;AAAA;AAAA,EAClC;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/components/sign-out.tsx"],"sourcesContent":["'use client'\n\nimport { useState } from 'react'\nimport { usePathname, useRouter } from 'next/navigation'\nimport { signOut } from 'firebase/auth'\nimport { ternSecureAuth } from '../utils/client-init'\nimport { clearSessionCookie } from '../app-router/admin/sessionTernSecure'\nimport { cn } from '../lib/utils'\nimport Link from 'next/link'\nimport { constructUrlWithRedirect } from '../utils/construct'\n\n\ninterface SignOutLinkProps {\n children?: React.ReactNode\n onError?: (error: Error) => void\n onSignOutSuccess?: () => void\n className?: string\n activeClassName?: string\n disabled?: boolean\n redirectPath?: string\n}\n\nexport function SignOut({\n children = 'Sign out',\n onError,\n onSignOutSuccess,\n className,\n activeClassName,\n disabled = false,\n redirectPath,\n}: SignOutLinkProps) {\n const [isLoading, setIsLoading] = useState(false)\n const pathname = usePathname()\n const router = useRouter()\n const loginPath = process.env.NEXT_PUBLIC_LOGIN_PATH || \"/sign-in\"\n\n const handleSignOut = async (e: React.MouseEvent<HTMLAnchorElement>) => {\n e.preventDefault()\n if (disabled || isLoading) return\n\n setIsLoading(true)\n try {\n // Sign out from Firebase\n await signOut(ternSecureAuth)\n\n // Clear the session cookie\n await clearSessionCookie()\n\n // Call success callback if provided\n onSignOutSuccess?.()\n\n // Construct login URL with redirect parameter\n const loginUrl = constructUrlWithRedirect(loginPath, pathname)\n\n // Use router for development and window.location for production\n if (process.env.NODE_ENV === \"production\") {\n window.location.href = loginUrl\n } else {\n router.push(loginUrl)\n }\n } catch (error) {\n console.error('Sign out error:', error)\n onError?.(error instanceof Error ? error : new Error('Failed to sign out'))\n } finally {\n setIsLoading(false)\n }\n }\n\n return (\n <Link\n href=\"#\"\n onClick={handleSignOut}\n className={cn(\n 'text-sm font-medium transition-colors hover:text-primary',\n disabled && 'pointer-events-none opacity-50',\n isLoading && 'pointer-events-none',\n className,\n isLoading && activeClassName\n )}\n aria-disabled={disabled || isLoading}\n >\n {isLoading ? 'Signing out...' : children}\n </Link>\n )\n}"],"mappings":";AAqEI;AAnEJ,SAAS,gBAAgB;AACzB,SAAS,aAAa,iBAAiB;AACvC,SAAS,eAAe;AACxB,SAAS,sBAAsB;AAC/B,SAAS,0BAA0B;AACnC,SAAS,UAAU;AACnB,OAAO,UAAU;AACjB,SAAS,gCAAgC;AAalC,SAAS,QAAQ;AAAA,EACtB,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AACF,GAAqB;AACnB,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,QAAM,WAAW,YAAY;AAC7B,QAAM,SAAS,UAAU;AACzB,QAAM,YAAY,QAAQ,IAAI,0BAA0B;AAExD,QAAM,gBAAgB,OAAO,MAA2C;AACtE,MAAE,eAAe;AACjB,QAAI,YAAY,UAAW;AAE3B,iBAAa,IAAI;AACjB,QAAI;AAEF,YAAM,QAAQ,cAAc;AAG5B,YAAM,mBAAmB;AAGzB;AAGA,YAAM,WAAW,yBAAyB,WAAW,QAAQ;AAG7D,UAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,eAAO,SAAS,OAAO;AAAA,MACzB,OAAO;AACL,eAAO,KAAK,QAAQ;AAAA,MACtB;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,mBAAmB,KAAK;AACtC,yCAAU,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,oBAAoB;AAAA,IAC3E,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAS;AAAA,MACT,WAAW;AAAA,QACT;AAAA,QACA,YAAY;AAAA,QACZ,aAAa;AAAA,QACb;AAAA,QACA,aAAa;AAAA,MACf;AAAA,MACA,iBAAe,YAAY;AAAA,MAE1B,sBAAY,mBAAmB;AAAA;AAAA,EAClC;AAEJ;","names":[]}
@@ -27,7 +27,7 @@ async function auth() {
27
27
  error: new Error("No valid session or token found")
28
28
  };
29
29
  } catch (error) {
30
- console.error("Error in getAuthResult:", error);
30
+ console.error("Error in get AuthResult:", error);
31
31
  return {
32
32
  user: null,
33
33
  token: null,
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/server/auth.ts"],"sourcesContent":["'use server'\nimport { cookies, headers } from \"next/headers\"\nimport type { UserInfo } from \"./types\"\n\n\nexport interface AuthResult {\n user: UserInfo | null\n token: string | null\n error: Error | null\n}\n\n\n /**\n * Get the current authenticated user from the session or token\n */\n export async function auth(): Promise<AuthResult> {\n try {\n const headersList = await headers()\n const cookieStore = await cookies()\n\n const userId = headersList.get('x-user-id')\n const authTime = headersList.get('x-auth-time')\n const emailVerified = headersList.get('x-auth-verified') === 'true'\n\n if (userId) {\n const token = cookieStore.get(\"_session_cookie\")?.value || \n cookieStore.get(\"_session_token\")?.value || \n null\n \n return {\n user: {\n uid: userId,\n email: headersList.get('x-user-email') || null,\n emailVerified,\n authTime: authTime ? parseInt(authTime) : undefined\n },\n token,\n error: null\n }\n }\n\n return {\n user: null,\n token: null,\n error: new Error(\"No valid session or token found\"),\n }\n } catch (error) {\n console.error(\"Error in get AuthResult:\", error)\n return {\n user: null,\n token: null,\n error: error instanceof Error ? error : new Error(\"An unknown error occurred\"),\n }\n }\n}\n\n/**\n * Type guard to check if user is authenticated\n */\nexport async function isAuthenticated(): Promise<boolean> {\n const authResult = await auth()\n return authResult.user !== null\n}\n\n/**\n * Get user info from auth result\n */\nexport async function getUserInfo(): Promise<UserInfo | null> {\n const authResult = await auth()\n if (!authResult.user) {\n return null\n }\n\n return {\n uid: authResult.user.uid,\n email: authResult.user.email,\n emailVerified: authResult.user.emailVerified,\n authTime: authResult.user.authTime\n }\n }\n\n"],"mappings":";AACA,SAAS,SAAS,eAAe;AAc/B,eAAsB,OAA4B;AAfpD;AAgBI,MAAI;AACF,UAAM,cAAc,MAAM,QAAQ;AAClC,UAAM,cAAc,MAAM,QAAQ;AAElC,UAAM,SAAS,YAAY,IAAI,WAAW;AAC1C,UAAM,WAAW,YAAY,IAAI,aAAa;AAC9C,UAAM,gBAAgB,YAAY,IAAI,iBAAiB,MAAM;AAE7D,QAAI,QAAQ;AACV,YAAM,UAAQ,iBAAY,IAAI,iBAAiB,MAAjC,mBAAoC,YACrC,iBAAY,IAAI,gBAAgB,MAAhC,mBAAmC,UACnC;AAEb,aAAO;AAAA,QACL,MAAM;AAAA,UACJ,KAAK;AAAA,UACL,OAAO,YAAY,IAAI,cAAc,KAAK;AAAA,UAC1C;AAAA,UACA,UAAU,WAAW,SAAS,QAAQ,IAAI;AAAA,QAC5C;AAAA,QACA;AAAA,QACA,OAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,IAAI,MAAM,iCAAiC;AAAA,IACpD;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,4BAA4B,KAAK;AAC/C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,2BAA2B;AAAA,IAC/E;AAAA,EACF;AACJ;AAKA,eAAsB,kBAAoC;AACxD,QAAM,aAAa,MAAM,KAAK;AAC9B,SAAO,WAAW,SAAS;AAC7B;AAKA,eAAsB,cAAwC;AAC5D,QAAM,aAAa,MAAM,KAAK;AAC9B,MAAI,CAAC,WAAW,MAAM;AACpB,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,KAAK,WAAW,KAAK;AAAA,IACrB,OAAO,WAAW,KAAK;AAAA,IACvB,eAAe,WAAW,KAAK;AAAA,IAC/B,UAAU,WAAW,KAAK;AAAA,EAC5B;AACA;","names":[]}
@@ -1,10 +1,8 @@
1
- import { cookies } from "next/headers";
2
- import { verifyFirebaseToken } from "./jwt";
1
+ import { verifyFirebaseToken } from "./jwt-edge";
3
2
  async function verifySession(request) {
4
3
  var _a, _b, _c, _d, _e, _f;
5
4
  try {
6
- const cookieStore = await cookies();
7
- const sessionCookie = (_a = cookieStore.get("_session_cookie")) == null ? void 0 : _a.value;
5
+ const sessionCookie = (_a = request.cookies.get("_session_cookie")) == null ? void 0 : _a.value;
8
6
  if (sessionCookie) {
9
7
  const result = await verifyFirebaseToken(sessionCookie, true);
10
8
  if (result.valid) {
@@ -20,7 +18,7 @@ async function verifySession(request) {
20
18
  }
21
19
  console.log("Session cookie verification failed:", result.error);
22
20
  }
23
- const idToken = (_d = cookieStore.get("_session_token")) == null ? void 0 : _d.value;
21
+ const idToken = (_d = request.cookies.get("_session_token")) == null ? void 0 : _d.value;
24
22
  if (idToken) {
25
23
  const result = await verifyFirebaseToken(idToken, false);
26
24
  if (result.valid) {
@@ -0,0 +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 return {\n isAuthenticated: true,\n user: {\n uid: result.uid ?? '',\n email: result.email || null,\n emailVerified: result.emailVerified ?? false,\n disabled: false,\n },\n }\n }\n console.log(\"Session cookie verification failed:\", result.error)\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 return {\n isAuthenticated: true,\n user: {\n uid: result.uid ?? '',\n email: result.email || null,\n emailVerified: result.emailVerified ?? false,\n disabled: false,\n },\n }\n }\n console.log(\"ID token verification failed:\", result.error)\n }\n\n return {\n isAuthenticated: false,\n user: null,\n error: \"No valid session found\",\n }\n } catch (error) {\n console.error(\"Session verification error:\", error)\n return {\n isAuthenticated: false,\n user: null,\n error: error instanceof Error ? error.message : \"Session verification failed\",\n }\n }\n}"],"mappings":"AAAA,SAAS,2BAA2B;AAKpC,eAAsB,cAAc,SAA8C;AALlF;AAME,MAAI;AAIF,UAAM,iBAAgB,aAAQ,QAAQ,IAAI,iBAAiB,MAArC,mBAAwC;AAC9D,QAAI,eAAe;AACjB,YAAM,SAAS,MAAM,oBAAoB,eAAe,IAAI;AAC5D,UAAI,OAAO,OAAO;AAChB,eAAO;AAAA,UACL,iBAAiB;AAAA,UACjB,MAAM;AAAA,YACJ,MAAK,YAAO,QAAP,YAAc;AAAA,YACnB,OAAO,OAAO,SAAS;AAAA,YACvB,gBAAe,YAAO,kBAAP,YAAwB;AAAA,YACvC,UAAU;AAAA,UACZ;AAAA,QACF;AAAA,MACF;AACA,cAAQ,IAAI,uCAAuC,OAAO,KAAK;AAAA,IACjE;AAGA,UAAM,WAAU,aAAQ,QAAQ,IAAI,gBAAgB,MAApC,mBAAuC;AACvD,QAAI,SAAS;AACX,YAAM,SAAS,MAAM,oBAAoB,SAAS,KAAK;AACvD,UAAI,OAAO,OAAO;AAChB,eAAO;AAAA,UACL,iBAAiB;AAAA,UACjB,MAAM;AAAA,YACJ,MAAK,YAAO,QAAP,YAAc;AAAA,YACnB,OAAO,OAAO,SAAS;AAAA,YACvB,gBAAe,YAAO,kBAAP,YAAwB;AAAA,YACvC,UAAU;AAAA,UACZ;AAAA,QACF;AAAA,MACF;AACA,cAAQ,IAAI,iCAAiC,OAAO,KAAK;AAAA,IAC3D;AAEA,WAAO;AAAA,MACL,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,OAAO;AAAA,IACT;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,+BAA+B,KAAK;AAClD,WAAO;AAAA,MACL,iBAAiB;AAAA,MACjB,MAAM;AAAA,MACN,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAClD;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,9 @@
1
+ import { ternSecureMiddleware, createRouteMatcher } from "./ternSecureMiddleware";
2
+ import { auth, getUserInfo } from "./auth";
3
+ export {
4
+ auth,
5
+ createRouteMatcher,
6
+ getUserInfo,
7
+ ternSecureMiddleware
8
+ };
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/server/index.ts"],"sourcesContent":["\n\nexport { ternSecureMiddleware, createRouteMatcher } from './ternSecureMiddleware'\nexport { auth, getUserInfo } from './auth'\nexport type { AuthResult } from './auth'\nexport type { UserInfo, SessionResult } from './types'"],"mappings":"AAEA,SAAS,sBAAsB,0BAA0B;AACzD,SAAS,MAAM,mBAAmB;","names":[]}
@@ -0,0 +1,99 @@
1
+ import { jwtVerify, createRemoteJWKSet } from "jose";
2
+ import { cache } from "react";
3
+ const FIREBASE_ID_TOKEN_URL = "https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com";
4
+ const FIREBASE_SESSION_CERT_URL = "https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys";
5
+ const getIdTokenJWKS = cache(() => {
6
+ return createRemoteJWKSet(new URL(FIREBASE_ID_TOKEN_URL), {
7
+ cacheMaxAge: 36e5,
8
+ // 1 hour
9
+ timeoutDuration: 5e3,
10
+ // 5 seconds
11
+ cooldownDuration: 3e4
12
+ // 30 seconds between retries
13
+ });
14
+ });
15
+ const getSessionJWKS = cache(() => {
16
+ return createRemoteJWKSet(new URL(FIREBASE_SESSION_CERT_URL), {
17
+ cacheMaxAge: 36e5,
18
+ // 1 hour
19
+ timeoutDuration: 5e3,
20
+ // 5 seconds
21
+ cooldownDuration: 3e4
22
+ // 30 seconds between retries
23
+ });
24
+ });
25
+ function decodeJwt(token) {
26
+ try {
27
+ const [headerB64, payloadB64] = token.split(".");
28
+ const header = JSON.parse(Buffer.from(headerB64, "base64").toString());
29
+ const payload = JSON.parse(Buffer.from(payloadB64, "base64").toString());
30
+ return { header, payload };
31
+ } catch (error) {
32
+ console.error("Error decoding JWT:", error);
33
+ return null;
34
+ }
35
+ }
36
+ async function verifyFirebaseToken(token, isSessionCookie = false) {
37
+ try {
38
+ const projectId = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID;
39
+ if (!projectId) {
40
+ throw new Error("Firebase Project ID is not configured");
41
+ }
42
+ const decoded = decodeJwt(token);
43
+ if (!decoded) {
44
+ throw new Error("Invalid token format");
45
+ }
46
+ console.log("Token details:", {
47
+ header: decoded.header,
48
+ type: isSessionCookie ? "session_cookie" : "id_token"
49
+ });
50
+ const JWKS = isSessionCookie ? await getSessionJWKS() : await getIdTokenJWKS();
51
+ const { payload } = await jwtVerify(token, JWKS, {
52
+ issuer: isSessionCookie ? "https://session.firebase.google.com/" + projectId : "https://securetoken.google.com/" + projectId,
53
+ audience: projectId,
54
+ algorithms: ["RS256"]
55
+ });
56
+ const firebasePayload = payload;
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
+ if (!firebasePayload.sub) {
65
+ throw new Error("Token subject is empty");
66
+ }
67
+ if (firebasePayload.auth_time > now) {
68
+ throw new Error("Token auth time is in the future");
69
+ }
70
+ return {
71
+ valid: true,
72
+ uid: firebasePayload.sub,
73
+ email: firebasePayload.email,
74
+ emailVerified: firebasePayload.email_verified,
75
+ authTime: firebasePayload.auth_time,
76
+ issuedAt: firebasePayload.iat,
77
+ expiresAt: firebasePayload.exp
78
+ };
79
+ } catch (error) {
80
+ console.error("Token verification details:", {
81
+ error: error instanceof Error ? {
82
+ name: error.name,
83
+ message: error.message,
84
+ stack: error.stack
85
+ } : error,
86
+ decoded: decodeJwt(token),
87
+ //projectId,
88
+ isSessionCookie
89
+ });
90
+ return {
91
+ valid: false,
92
+ error: error instanceof Error ? error.message : "Invalid token"
93
+ };
94
+ }
95
+ }
96
+ export {
97
+ verifyFirebaseToken
98
+ };
99
+ //# sourceMappingURL=jwt-edge.js.map
@@ -0,0 +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 // Verify token claims\n if (firebasePayload.exp <= now) {\n throw new Error(\"Token has expired\")\n }\n\n if (firebasePayload.iat > now) {\n throw new Error(\"Token issued time is in the future\")\n }\n\n if (!firebasePayload.sub) {\n throw new Error(\"Token subject is empty\")\n }\n\n if (firebasePayload.auth_time > now) {\n throw new Error(\"Token auth time is in the future\")\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;AAGvC,QAAI,gBAAgB,OAAO,KAAK;AAC3B,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACzC;AAEA,QAAI,gBAAgB,MAAM,KAAK;AACzB,YAAM,IAAI,MAAM,oCAAoC;AAAA,IAC1D;AAEA,QAAI,CAAC,gBAAgB,KAAK;AACpB,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC9C;AAEA,QAAI,gBAAgB,YAAY,KAAK;AAC/B,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACxD;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":[]}
@@ -0,0 +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 const now = Math.floor(Date.now() / 1000)\n\n // Verify token claims\n if (firebasePayload.exp <= now) {\n throw new Error(\"Token has expired\")\n }\n\n if (firebasePayload.iat > now) {\n throw new Error(\"Token issued time is in the future\")\n }\n\n if (!firebasePayload.sub) {\n throw new Error(\"Token subject is empty\")\n }\n\n if (firebasePayload.auth_time > now) {\n throw new Error(\"Token auth time is in the future\")\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":[]}
@@ -1,7 +1,5 @@
1
1
  import { NextResponse } from "next/server";
2
- import { cookies } from "next/headers";
3
2
  import { verifySession } from "./edge-session";
4
- import { verifyFirebaseToken } from "./jwt";
5
3
  const runtime = "edge";
6
4
  function createRouteMatcher(patterns) {
7
5
  return (request) => {
@@ -15,58 +13,6 @@ function createRouteMatcher(patterns) {
15
13
  };
16
14
  }
17
15
  async function edgeAuth(request) {
18
- var _a, _b, _c, _d, _e, _f;
19
- const cookieStore = await cookies();
20
- async function protect() {
21
- const { pathname } = request.nextUrl;
22
- throw new Error("Unauthorized access");
23
- }
24
- try {
25
- const sessionCookie = (_a = cookieStore.get("_session_cookie")) == null ? void 0 : _a.value;
26
- if (sessionCookie) {
27
- const userInfo = await verifyFirebaseToken(sessionCookie, true);
28
- console.log("userInfo", userInfo);
29
- if (userInfo.valid) {
30
- return {
31
- user: {
32
- uid: (_b = userInfo.uid) != null ? _b : "",
33
- email: (_c = userInfo.email) != null ? _c : null
34
- },
35
- token: sessionCookie,
36
- protect: async () => {
37
- }
38
- };
39
- }
40
- }
41
- const idToken = (_d = cookieStore.get("_session_token")) == null ? void 0 : _d.value;
42
- if (idToken) {
43
- const userInfo = await verifyFirebaseToken(idToken, false);
44
- if (userInfo.valid) {
45
- return {
46
- user: {
47
- uid: (_e = userInfo.uid) != null ? _e : "",
48
- email: (_f = userInfo.email) != null ? _f : null
49
- },
50
- token: idToken,
51
- protect: async () => {
52
- }
53
- };
54
- }
55
- }
56
- return {
57
- user: null,
58
- token: null,
59
- protect
60
- };
61
- } catch (error) {
62
- return {
63
- user: null,
64
- token: null,
65
- protect
66
- };
67
- }
68
- }
69
- async function edgeAuthSecond(request) {
70
16
  var _a, _b;
71
17
  async function protect() {
72
18
  throw new Error("Unauthorized access");
@@ -98,7 +44,7 @@ async function edgeAuthSecond(request) {
98
44
  function ternSecureMiddleware(callback) {
99
45
  return async function middleware(request) {
100
46
  try {
101
- const auth = await edgeAuthSecond(request);
47
+ const auth = await edgeAuth(request);
102
48
  try {
103
49
  await callback(auth, request);
104
50
  const response = NextResponse.next();
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/server/ternSecureMiddleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server';\nimport { verifySession } from './edge-session'\nimport type { UserInfo } from './types'\n\n\nexport const runtime = \"edge\"\n\n\ninterface Auth {\n user: UserInfo | null\n token: string | null\n protect: () => Promise<void>\n}\n\ntype MiddlewareCallback = (\n auth: Auth,\n request: NextRequest\n) => Promise<void>\n\n\n/**\n * Create a route matcher function for public paths\n */\nexport function createRouteMatcher(patterns: string[]) {\n return (request: NextRequest): boolean => {\n const { pathname } = request.nextUrl\n return patterns.some(pattern => {\n // Convert route pattern to regex\n const regexPattern = new RegExp(\n `^${pattern.replace(/\\*/g, '.*').replace(/\\((.*)\\)/, '(?:$1)?')}$`\n )\n return regexPattern.test(pathname)\n })\n }\n}\n\n\n/**\n * Edge-compatible auth check\n */\nasync function edgeAuth(request: NextRequest): Promise<Auth> {\n async function protect() {\n throw new Error(\"Unauthorized access\")\n }\n\n try {\n const sessionResult = await verifySession(request)\n\n if (sessionResult.isAuthenticated && sessionResult.user) {\n return {\n user: sessionResult.user,\n token: request.cookies.get(\"_session_cookie\")?.value || request.cookies.get(\"_session_token\")?.value || null,\n protect: async () => {},\n }\n }\n\n return {\n user: null,\n token: null,\n protect,\n }\n } catch (error) {\n console.error(\"Auth check error:\", error)\n return {\n user: null,\n token: null,\n protect,\n }\n }\n}\n\n\n\n/**\n * Middleware factory that handles authentication and custom logic\n * @param customHandler Optional function for additional custom logic\n */\n\nexport function ternSecureMiddleware(callback: MiddlewareCallback) {\n return async function middleware(request: NextRequest) {\n try {\n const auth = await edgeAuth(request)\n\n try {\n \n await callback(auth, request)\n\n const response = NextResponse.next()\n\n if (auth.user) {\n // Set auth headers\n response.headers.set(\"x-user-id\", auth.user.uid)\n if (auth.user.email) {\n response.headers.set(\"x-user-email\", auth.user.email)\n }\n if (auth.user.emailVerified !== undefined) {\n response.headers.set(\"x-email-verified\", auth.user.emailVerified.toString())\n }\n if (auth.user.authTime) {\n response.headers.set(\"x-auth-time\", auth.user.authTime.toString())\n }\n }\n\n return response\n } catch (error) {\n // Handle unauthorized access\n if (error instanceof Error && error.message === 'Unauthorized access') {\n const redirectUrl = new URL('/sign-in', request.url)\n redirectUrl.searchParams.set('redirect', request.nextUrl.pathname)\n return NextResponse.redirect(redirectUrl)\n }\n throw error\n }\n\n } catch (error) {\n console.error(\"Middleware error:\", {\n error:\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : error,\n path: request.nextUrl.pathname,\n })\n\n const redirectUrl = new URL(\"/sign-in\", request.url)\n return NextResponse.redirect(redirectUrl)\n }\n }\n}"],"mappings":"AAAA,SAAsB,oBAAoB;AAC1C,SAAS,qBAAqB;AAIvB,MAAM,UAAU;AAkBhB,SAAS,mBAAmB,UAAoB;AACrD,SAAO,CAAC,YAAkC;AACxC,UAAM,EAAE,SAAS,IAAI,QAAQ;AAC7B,WAAO,SAAS,KAAK,aAAW;AAE9B,YAAM,eAAe,IAAI;AAAA,QACvB,IAAI,QAAQ,QAAQ,OAAO,IAAI,EAAE,QAAQ,YAAY,SAAS,CAAC;AAAA,MACjE;AACA,aAAO,aAAa,KAAK,QAAQ;AAAA,IACnC,CAAC;AAAA,EACH;AACF;AAMA,eAAe,SAAS,SAAqC;AAxC7D;AAyCE,iBAAe,UAAU;AACvB,UAAM,IAAI,MAAM,qBAAqB;AAAA,EACvC;AAEA,MAAI;AACF,UAAM,gBAAgB,MAAM,cAAc,OAAO;AAEjD,QAAI,cAAc,mBAAmB,cAAc,MAAM;AACvD,aAAO;AAAA,QACL,MAAM,cAAc;AAAA,QACpB,SAAO,aAAQ,QAAQ,IAAI,iBAAiB,MAArC,mBAAwC,YAAS,aAAQ,QAAQ,IAAI,gBAAgB,MAApC,mBAAuC,UAAS;AAAA,QACxG,SAAS,YAAY;AAAA,QAAC;AAAA,MACxB;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,qBAAqB,KAAK;AACxC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP;AAAA,IACF;AAAA,EACF;AACF;AASO,SAAS,qBAAqB,UAA8B;AACjE,SAAO,eAAe,WAAW,SAAsB;AACrD,QAAI;AACF,YAAM,OAAO,MAAM,SAAS,OAAO;AAEnC,UAAI;AAEF,cAAM,SAAS,MAAM,OAAO;AAE5B,cAAM,WAAW,aAAa,KAAK;AAEnC,YAAI,KAAK,MAAM;AAEb,mBAAS,QAAQ,IAAI,aAAa,KAAK,KAAK,GAAG;AAC/C,cAAI,KAAK,KAAK,OAAO;AACnB,qBAAS,QAAQ,IAAI,gBAAgB,KAAK,KAAK,KAAK;AAAA,UACtD;AACA,cAAI,KAAK,KAAK,kBAAkB,QAAW;AACzC,qBAAS,QAAQ,IAAI,oBAAoB,KAAK,KAAK,cAAc,SAAS,CAAC;AAAA,UAC7E;AACA,cAAI,KAAK,KAAK,UAAU;AACtB,qBAAS,QAAQ,IAAI,eAAe,KAAK,KAAK,SAAS,SAAS,CAAC;AAAA,UACnE;AAAA,QACF;AAEA,eAAO;AAAA,MACT,SAAS,OAAO;AAEd,YAAI,iBAAiB,SAAS,MAAM,YAAY,uBAAuB;AACrE,gBAAM,cAAc,IAAI,IAAI,YAAY,QAAQ,GAAG;AACnD,sBAAY,aAAa,IAAI,YAAY,QAAQ,QAAQ,QAAQ;AACjE,iBAAO,aAAa,SAAS,WAAW;AAAA,QAC1C;AACA,cAAM;AAAA,MACR;AAAA,IAEF,SAAS,OAAO;AACd,cAAQ,MAAM,qBAAqB;AAAA,QACjC,OACE,iBAAiB,QACb;AAAA,UACE,MAAM,MAAM;AAAA,UACZ,SAAS,MAAM;AAAA,UACf,OAAO,MAAM;AAAA,QACf,IACA;AAAA,QACN,MAAM,QAAQ,QAAQ;AAAA,MACxB,CAAC;AAED,YAAM,cAAc,IAAI,IAAI,YAAY,QAAQ,GAAG;AACnD,aAAO,aAAa,SAAS,WAAW;AAAA,IAC1C;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,3 @@
1
+ export { verifyTernSessionCookie, createSessionCookie } from './sessionTernSecure';
2
+ export { adminTernSecureAuth, adminTernSecureDb } from '../../utils/admin-init';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/app-router/admin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAClF,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionTernSecure.d.ts","sourceRoot":"","sources":["../../../../src/app-router/admin/sessionTernSecure.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,IAAI;IACjB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAEH,MAAM,WAAW,OAAO;IACpB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACvB;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,MAAM;;;GAgBxD;AAID,wBAAsB,sBAAsB;;;GAkB3C;AAGD,wBAAsB,UAAU;;;GAkB/B;AAED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,MAAM;;;GAcnD;AAEC,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAuBhH;AAGD,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,GAAG,CAAC;IAAC,KAAK,CAAC,EAAE,GAAG,CAAA;CAAE,CAAC,CAWlH;AAGD,wBAAsB,kBAAkB;;;GAwBvC"}
@@ -1,4 +1,4 @@
1
- import type { UserInfo } from "./edge-session";
1
+ import type { UserInfo } from "./types";
2
2
  export interface AuthResult {
3
3
  user: UserInfo | null;
4
4
  token: string | null;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/server/auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAGvC,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAA;IACrB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;CACpB;AAGC;;GAEG;AACH,wBAAsB,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC,CAuClD;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAGxD;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAY1D"}
@@ -0,0 +1,4 @@
1
+ import type { NextRequest } from "next/server";
2
+ import type { SessionResult } from "./types";
3
+ export declare function verifySession(request: NextRequest): Promise<SessionResult>;
4
+ //# sourceMappingURL=edge-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge-session.d.ts","sourceRoot":"","sources":["../../../src/server/edge-session.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAG5C,wBAAsB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAqDhF"}
@@ -0,0 +1,5 @@
1
+ export { ternSecureMiddleware, createRouteMatcher } from './ternSecureMiddleware';
2
+ export { auth, getUserInfo } from './auth';
3
+ export type { AuthResult } from './auth';
4
+ export type { UserInfo, SessionResult } from './types';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AACjF,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAC1C,YAAY,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AACxC,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA"}