@tern-secure/nextjs 3.2.26 → 3.2.28

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.
@@ -53,7 +53,7 @@ async function getServerSessionCookie() {
53
53
  throw new Error("No session cookie found");
54
54
  }
55
55
  try {
56
- const decondeClaims = await import_admin_init.adminTernSecureAuth.verifySessionCookie(sessionCookie);
56
+ const decondeClaims = await import_admin_init.adminTernSecureAuth.verifySessionCookie(sessionCookie, true);
57
57
  return {
58
58
  token: sessionCookie,
59
59
  userId: decondeClaims.uid
@@ -106,7 +106,7 @@ async function verifyTernIDToken(token) {
106
106
  }
107
107
  async function verifyTernSessionCookie(session) {
108
108
  try {
109
- const res = await import_admin_init.adminTernSecureAuth.verifySessionCookie(session);
109
+ const res = await import_admin_init.adminTernSecureAuth.verifySessionCookie(session, true);
110
110
  if (res) {
111
111
  return { valid: true, uid: res.uid };
112
112
  } else {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/server/sessionTernSecure.ts"],"sourcesContent":["'use server'\r\n\r\nimport { cookies } from 'next/headers';\r\nimport { adminTernSecureAuth as adminAuth } from '../../utils/admin-init';\r\n\r\n\r\nexport interface User {\r\n uid: string;\r\n email: string;\r\n }\r\n\r\nexport interface Session {\r\n user: User | null;\r\n token: string | null;\r\n error: Error | null;\r\n}\r\n\r\nexport async function createSessionCookie(idToken: string) {\r\n try {\r\n const expiresIn = 60 * 60 * 24 * 5 * 1000;\r\n const sessionCookie = await adminAuth.createSessionCookie(idToken, { expiresIn });\r\n\r\n const cookieStore = await cookies();\r\n cookieStore.set('_session_cookie', sessionCookie, {\r\n maxAge: expiresIn,\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n path: '/',\r\n });\r\n return { success: true, message: 'Session created' };\r\n } catch (error) {\r\n return { success: false, message: 'Failed to create session' };\r\n }\r\n}\r\n\r\n\r\n\r\nexport async function getServerSessionCookie() {\r\n const cookieStore = await cookies();\r\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\r\n\r\n if (!sessionCookie) {\r\n throw new Error('No session cookie found')\r\n }\r\n \r\n try {\r\n const decondeClaims = await adminAuth.verifySessionCookie(sessionCookie)\r\n return {\r\n token: sessionCookie,\r\n userId: decondeClaims.uid\r\n }\r\n } catch (error) {\r\n console.error('Error verifying session:', error)\r\n throw new Error('Invalid Session')\r\n }\r\n}\r\n\r\n\r\nexport async function getIdToken() {\r\n const cookieStore = await cookies();\r\n const token = cookieStore.get('_session_token')?.value;\r\n\r\n if (!token) {\r\n throw new Error('No session cookie found')\r\n }\r\n \r\n try {\r\n const decodedClaims = await adminAuth.verifyIdToken(token)\r\n return {\r\n token: token,\r\n userId: decodedClaims.uid\r\n }\r\n } catch (error) {\r\n console.error('Error verifying session:', error)\r\n throw new Error('Invalid Session')\r\n }\r\n}\r\n\r\nexport async function setServerSession(token: string) {\r\n const cookieStore = await cookies();\r\n cookieStore.set('_session', token, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n maxAge: 60 * 60, // 1 hour\r\n path: '/',\r\n });\r\n }\r\n\r\n export async function verifyTernIDToken(token: string): Promise<{ valid: boolean; uid?: any; error?: any }>{\r\n try {\r\n const res = await adminAuth.verifyIdToken(token);\r\n if (res) {\r\n return { valid: true, uid: res.uid };\r\n } else {\r\n return { valid: false, error: 'Invalid token'};\r\n }\r\n } catch (error) {\r\n return {error: error, valid: false}\r\n }\r\n }\r\n\r\n export async function verifyTernSessionCookie(session: string): Promise<{ valid: boolean; uid?: any; error?: any }>{\r\n try {\r\n const res = await adminAuth.verifySessionCookie(session);\r\n if (res) {\r\n return { valid: true, uid: res.uid };\r\n } else {\r\n return { valid: false, error: 'Invalid session'};\r\n }\r\n } catch (error) {\r\n return {error: error, valid: false}\r\n }\r\n }\r\n\r\n\r\n\r\n/*\r\n export async function GET(request: NextRequest) {\r\n const cookieStore = await cookies();\r\n const sessionCookie = cookieStore.get('session')?.value\r\n \r\n if (!sessionCookie) {\r\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\r\n }\r\n \r\n try {\r\n const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie, true)\r\n return NextResponse.json({ isAuthenticated: true, user: decodedClaims }, { status: 200 })\r\n } catch (error) {\r\n console.error('Error verifying session cookie:', error)\r\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\r\n }\r\n }\r\n\r\n*/"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,qBAAwB;AACxB,wBAAiD;AAcjD,eAAsB,oBAAoB,SAAiB;AACzD,MAAI;AACF,UAAM,YAAY,KAAK,KAAK,KAAK,IAAI;AACnC,UAAM,gBAAgB,MAAM,kBAAAA,oBAAU,oBAAoB,SAAS,EAAE,UAAU,CAAC;AAEhF,UAAM,cAAc,UAAM,wBAAQ;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;AArC/C;AAsCE,QAAM,cAAc,UAAM,wBAAQ;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,kBAAAA,oBAAU,oBAAoB,aAAa;AACvE,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;AA1DnC;AA2DE,QAAM,cAAc,UAAM,wBAAQ;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,kBAAAA,oBAAU,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;AAClD,QAAM,cAAc,UAAM,wBAAQ;AAClC,cAAY,IAAI,YAAY,OAAO;AAAA,IACjC,UAAU;AAAA,IACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,IACjC,UAAU;AAAA,IACV,QAAQ,KAAK;AAAA;AAAA,IACb,MAAM;AAAA,EACR,CAAC;AACH;AAEA,eAAsB,kBAAkB,OAAmE;AACzG,MAAI;AACF,UAAM,MAAM,MAAM,kBAAAA,oBAAU,cAAc,KAAK;AAC/C,QAAI,KAAK;AACP,aAAO,EAAE,OAAO,MAAM,KAAK,IAAI,IAAI;AAAA,IACrC,OAAO;AACL,aAAO,EAAE,OAAO,OAAO,OAAO,gBAAe;AAAA,IAC/C;AAAA,EACF,SAAS,OAAO;AACd,WAAO,EAAC,OAAc,OAAO,MAAK;AAAA,EACpC;AACF;AAEA,eAAsB,wBAAwB,SAAqE;AACjH,MAAI;AACF,UAAM,MAAM,MAAM,kBAAAA,oBAAU,oBAAoB,OAAO;AACvD,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;","names":["adminAuth"]}
1
+ {"version":3,"sources":["../../../../src/app-router/server/sessionTernSecure.ts"],"sourcesContent":["'use server'\r\n\r\nimport { cookies } from 'next/headers';\r\nimport { adminTernSecureAuth as adminAuth } from '../../utils/admin-init';\r\n\r\n\r\nexport interface User {\r\n uid: string;\r\n email: string;\r\n }\r\n\r\nexport interface Session {\r\n user: User | null;\r\n token: string | null;\r\n error: Error | null;\r\n}\r\n\r\nexport async function createSessionCookie(idToken: string) {\r\n try {\r\n const expiresIn = 60 * 60 * 24 * 5 * 1000;\r\n const sessionCookie = await adminAuth.createSessionCookie(idToken, { expiresIn });\r\n\r\n const cookieStore = await cookies();\r\n cookieStore.set('_session_cookie', sessionCookie, {\r\n maxAge: expiresIn,\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n path: '/',\r\n });\r\n return { success: true, message: 'Session created' };\r\n } catch (error) {\r\n return { success: false, message: 'Failed to create session' };\r\n }\r\n}\r\n\r\n\r\n\r\nexport async function getServerSessionCookie() {\r\n const cookieStore = await cookies();\r\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\r\n\r\n if (!sessionCookie) {\r\n throw new Error('No session cookie found')\r\n }\r\n \r\n try {\r\n const decondeClaims = await adminAuth.verifySessionCookie(sessionCookie, true)\r\n return {\r\n token: sessionCookie,\r\n userId: decondeClaims.uid\r\n }\r\n } catch (error) {\r\n console.error('Error verifying session:', error)\r\n throw new Error('Invalid Session')\r\n }\r\n}\r\n\r\n\r\nexport async function getIdToken() {\r\n const cookieStore = await cookies();\r\n const token = cookieStore.get('_session_token')?.value;\r\n\r\n if (!token) {\r\n throw new Error('No session cookie found')\r\n }\r\n \r\n try {\r\n const decodedClaims = await adminAuth.verifyIdToken(token)\r\n return {\r\n token: token,\r\n userId: decodedClaims.uid\r\n }\r\n } catch (error) {\r\n console.error('Error verifying session:', error)\r\n throw new Error('Invalid Session')\r\n }\r\n}\r\n\r\nexport async function setServerSession(token: string) {\r\n const cookieStore = await cookies();\r\n cookieStore.set('_session', token, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n maxAge: 60 * 60, // 1 hour\r\n path: '/',\r\n });\r\n }\r\n\r\n export async function verifyTernIDToken(token: string): Promise<{ valid: boolean; uid?: any; error?: any }>{\r\n try {\r\n const res = await adminAuth.verifyIdToken(token);\r\n if (res) {\r\n return { valid: true, uid: res.uid };\r\n } else {\r\n return { valid: false, error: 'Invalid token'};\r\n }\r\n } catch (error) {\r\n return {error: error, valid: false}\r\n }\r\n }\r\n\r\n export async function verifyTernSessionCookie(session: string): Promise<{ valid: boolean; uid?: any; error?: any }>{\r\n try {\r\n const res = await adminAuth.verifySessionCookie(session, true);\r\n if (res) {\r\n return { valid: true, uid: res.uid };\r\n } else {\r\n return { valid: false, error: 'Invalid session'};\r\n }\r\n } catch (error) {\r\n return {error: error, valid: false}\r\n }\r\n }\r\n\r\n\r\n\r\n/*\r\n export async function GET(request: NextRequest) {\r\n const cookieStore = await cookies();\r\n const sessionCookie = cookieStore.get('session')?.value\r\n \r\n if (!sessionCookie) {\r\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\r\n }\r\n \r\n try {\r\n const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie, true)\r\n return NextResponse.json({ isAuthenticated: true, user: decodedClaims }, { status: 200 })\r\n } catch (error) {\r\n console.error('Error verifying session cookie:', error)\r\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\r\n }\r\n }\r\n\r\n*/"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,qBAAwB;AACxB,wBAAiD;AAcjD,eAAsB,oBAAoB,SAAiB;AACzD,MAAI;AACF,UAAM,YAAY,KAAK,KAAK,KAAK,IAAI;AACnC,UAAM,gBAAgB,MAAM,kBAAAA,oBAAU,oBAAoB,SAAS,EAAE,UAAU,CAAC;AAEhF,UAAM,cAAc,UAAM,wBAAQ;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;AArC/C;AAsCE,QAAM,cAAc,UAAM,wBAAQ;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,kBAAAA,oBAAU,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;AA1DnC;AA2DE,QAAM,cAAc,UAAM,wBAAQ;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,kBAAAA,oBAAU,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;AAClD,QAAM,cAAc,UAAM,wBAAQ;AAClC,cAAY,IAAI,YAAY,OAAO;AAAA,IACjC,UAAU;AAAA,IACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,IACjC,UAAU;AAAA,IACV,QAAQ,KAAK;AAAA;AAAA,IACb,MAAM;AAAA,EACR,CAAC;AACH;AAEA,eAAsB,kBAAkB,OAAmE;AACzG,MAAI;AACF,UAAM,MAAM,MAAM,kBAAAA,oBAAU,cAAc,KAAK;AAC/C,QAAI,KAAK;AACP,aAAO,EAAE,OAAO,MAAM,KAAK,IAAI,IAAI;AAAA,IACrC,OAAO;AACL,aAAO,EAAE,OAAO,OAAO,OAAO,gBAAe;AAAA,IAC/C;AAAA,EACF,SAAS,OAAO;AACd,WAAO,EAAC,OAAc,OAAO,MAAK;AAAA,EACpC;AACF;AAEA,eAAsB,wBAAwB,SAAqE;AACjH,MAAI;AACF,UAAM,MAAM,MAAM,kBAAAA,oBAAU,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;","names":["adminAuth"]}
@@ -57,8 +57,22 @@ function TernSecureClientProvider({ children, onUserChanged }) {
57
57
  }
58
58
  }, [auth, onUserChanged]);
59
59
  (0, import_react.useEffect)(() => {
60
+ const unsubscribeMiddleware = (0, import_auth.beforeAuthStateChanged)(auth, async (user) => {
61
+ if (user) {
62
+ try {
63
+ await user.getIdToken(true);
64
+ } catch (error) {
65
+ console.error("Token validation error:", error);
66
+ await auth.signOut();
67
+ return;
68
+ }
69
+ }
70
+ });
60
71
  const unsubscribe = (0, import_auth.onAuthStateChanged)(auth, handleAuthStateChange);
61
- return () => unsubscribe();
72
+ return () => {
73
+ unsubscribeMiddleware();
74
+ unsubscribe();
75
+ };
62
76
  }, [auth, handleAuthStateChange]);
63
77
  if (!authState.isLoaded) {
64
78
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_TernSecureCtx.TernSecureCtx.Provider, { value: authState, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "aria-live": "polite", "aria-busy": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: "Loading authentication state..." }) }) });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/boundary/TernSecureClientProvider.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport React, { useState, useEffect, useMemo, useCallback } from 'react'\r\nimport { ternSecureAuth } from '../utils/client-init'\r\nimport { onAuthStateChanged, User } from \"firebase/auth\"\r\nimport { TernSecureCtx, TernSecureState } from './TernSecureCtx'\r\n\r\ninterface TernSecureClientProviderProps {\r\n children: React.ReactNode;\r\n onUserChanged?: (user: User | null) => Promise<void>;\r\n}\r\n\r\nexport function TernSecureClientProvider({ children, onUserChanged }: TernSecureClientProviderProps) {\r\n const auth = useMemo(() => ternSecureAuth, []);\r\n\r\n const [authState, setAuthState] = useState<TernSecureState>(() => ({\r\n userId: null,\r\n isLoaded: false,\r\n error: null,\r\n }));\r\n\r\n const handleAuthStateChange = useCallback(async (user: User | null) => {\r\n try {\r\n if(!user) {\r\n await auth.signOut();\r\n }\r\n\r\n if (onUserChanged) {\r\n await onUserChanged(user);\r\n }\r\n setAuthState({\r\n isLoaded: true,\r\n userId: user?.uid || null,\r\n error: null\r\n });\r\n } catch (error) {\r\n auth.signOut();\r\n setAuthState({\r\n isLoaded: true,\r\n userId: null,\r\n error: error instanceof Error ? error : new Error('An unknown error occurred')\r\n });\r\n }\r\n }, [auth, onUserChanged]);\r\n\r\n useEffect(() => {\r\n const unsubscribe = onAuthStateChanged(auth, handleAuthStateChange);\r\n \r\n return () => unsubscribe();\r\n }, [auth, handleAuthStateChange]);\r\n\r\n /*const contextValue: TernSecureCtxValue = useMemo(() => ({\r\n ...authState\r\n }), [authState]);*/\r\n\r\n if (!authState.isLoaded) {\r\n return (\r\n <TernSecureCtx.Provider value={authState}>\r\n <div aria-live=\"polite\" aria-busy=\"true\">\r\n <span className=\"sr-only\">Loading authentication state...</span>\r\n </div>\r\n </TernSecureCtx.Provider>\r\n );\r\n }\r\n\r\n return (\r\n <TernSecureCtx.Provider value={authState}>\r\n {children}\r\n </TernSecureCtx.Provider>\r\n );\r\n}\r\n\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA2DU;AAzDV,mBAAiE;AACjE,yBAA+B;AAC/B,kBAAyC;AACzC,2BAA+C;AAOxC,SAAS,yBAAyB,EAAE,UAAU,cAAc,GAAkC;AACnG,QAAM,WAAO,sBAAQ,MAAM,mCAAgB,CAAC,CAAC;AAE7C,QAAM,CAAC,WAAW,YAAY,QAAI,uBAA0B,OAAO;AAAA,IAC/D,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,OAAO;AAAA,EACX,EAAE;AAEF,QAAM,4BAAwB,0BAAY,OAAO,SAAsB;AACrE,QAAI;AACF,UAAG,CAAC,MAAM;AACR,cAAM,KAAK,QAAQ;AAAA,MACrB;AAEA,UAAI,eAAe;AACjB,cAAM,cAAc,IAAI;AAAA,MAC1B;AACA,mBAAa;AAAA,QACX,UAAU;AAAA,QACV,SAAQ,6BAAM,QAAO;AAAA,QACrB,OAAO;AAAA,MACT,CAAC;AAAA,IACH,SAAS,OAAO;AACd,WAAK,QAAQ;AACb,mBAAa;AAAA,QACX,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,2BAA2B;AAAA,MAC/E,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,MAAM,aAAa,CAAC;AAExB,8BAAU,MAAM;AACd,UAAM,kBAAc,gCAAmB,MAAM,qBAAqB;AAElE,WAAO,MAAM,YAAY;AAAA,EAC3B,GAAG,CAAC,MAAM,qBAAqB,CAAC;AAMhC,MAAI,CAAC,UAAU,UAAU;AACvB,WACE,4CAAC,mCAAc,UAAd,EAAuB,OAAO,WAC7B,sDAAC,SAAI,aAAU,UAAS,aAAU,QAChC,sDAAC,UAAK,WAAU,WAAU,6CAA+B,GAC3D,GACF;AAAA,EAEJ;AAEA,SACE,4CAAC,mCAAc,UAAd,EAAuB,OAAO,WAC5B,UACH;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/boundary/TernSecureClientProvider.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport React, { useState, useEffect, useMemo, useCallback } from 'react'\r\nimport { ternSecureAuth } from '../utils/client-init'\r\nimport { onAuthStateChanged, User, beforeAuthStateChanged, ParsedToken } from \"firebase/auth\"\r\nimport { TernSecureCtx, TernSecureState } from './TernSecureCtx'\r\n\r\ninterface TernSecureClientProviderProps {\r\n children: React.ReactNode;\r\n onUserChanged?: (user: User | null) => Promise<void>;\r\n}\r\n\r\n\r\nexport function TernSecureClientProvider({ children, onUserChanged }: TernSecureClientProviderProps) {\r\n const auth = useMemo(() => ternSecureAuth, []);\r\n\r\n const [authState, setAuthState] = useState<TernSecureState>(() => ({\r\n userId: null,\r\n isLoaded: false,\r\n error: null,\r\n }));\r\n\r\n const handleAuthStateChange = useCallback(async (user: User | null) => {\r\n try {\r\n if(!user) {\r\n await auth.signOut();\r\n }\r\n\r\n if (onUserChanged) {\r\n await onUserChanged(user);\r\n }\r\n setAuthState({\r\n isLoaded: true,\r\n userId: user?.uid || null,\r\n error: null\r\n });\r\n } catch (error) {\r\n auth.signOut();\r\n setAuthState({\r\n isLoaded: true,\r\n userId: null,\r\n error: error instanceof Error ? error : new Error('An unknown error occurred')\r\n });\r\n }\r\n }, [auth, onUserChanged]);\r\n\r\n useEffect(() => {\r\n const unsubscribeMiddleware = beforeAuthStateChanged(auth, async (user) => {\r\n if(user) {\r\n try {\r\n await user.getIdToken(true);\r\n } catch (error) {\r\n console.error('Token validation error:', error);\r\n await auth.signOut();\r\n return;\r\n }\r\n }\r\n });\r\n\r\n const unsubscribe = onAuthStateChanged(auth, handleAuthStateChange);\r\n \r\n return () => {\r\n unsubscribeMiddleware();\r\n unsubscribe();\r\n };\r\n }, [auth, handleAuthStateChange]);\r\n\r\n /*const contextValue: TernSecureCtxValue = useMemo(() => ({\r\n ...authState\r\n }), [authState]);*/\r\n\r\n if (!authState.isLoaded) {\r\n return (\r\n <TernSecureCtx.Provider value={authState}>\r\n <div aria-live=\"polite\" aria-busy=\"true\">\r\n <span className=\"sr-only\">Loading authentication state...</span>\r\n </div>\r\n </TernSecureCtx.Provider>\r\n );\r\n }\r\n\r\n return (\r\n <TernSecureCtx.Provider value={authState}>\r\n {children}\r\n </TernSecureCtx.Provider>\r\n );\r\n}\r\n\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA2EU;AAzEV,mBAAiE;AACjE,yBAA+B;AAC/B,kBAA8E;AAC9E,2BAA+C;AAQxC,SAAS,yBAAyB,EAAE,UAAU,cAAc,GAAkC;AACnG,QAAM,WAAO,sBAAQ,MAAM,mCAAgB,CAAC,CAAC;AAE7C,QAAM,CAAC,WAAW,YAAY,QAAI,uBAA0B,OAAO;AAAA,IAC/D,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,OAAO;AAAA,EACX,EAAE;AAEF,QAAM,4BAAwB,0BAAY,OAAO,SAAsB;AACrE,QAAI;AACF,UAAG,CAAC,MAAM;AACR,cAAM,KAAK,QAAQ;AAAA,MACrB;AAEA,UAAI,eAAe;AACjB,cAAM,cAAc,IAAI;AAAA,MAC1B;AACA,mBAAa;AAAA,QACX,UAAU;AAAA,QACV,SAAQ,6BAAM,QAAO;AAAA,QACrB,OAAO;AAAA,MACT,CAAC;AAAA,IACH,SAAS,OAAO;AACd,WAAK,QAAQ;AACb,mBAAa;AAAA,QACX,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,2BAA2B;AAAA,MAC/E,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,MAAM,aAAa,CAAC;AAExB,8BAAU,MAAM;AACd,UAAM,4BAAwB,oCAAuB,MAAM,OAAO,SAAS;AACzE,UAAG,MAAM;AACP,YAAI;AACF,gBAAM,KAAK,WAAW,IAAI;AAAA,QAC5B,SAAS,OAAO;AACd,kBAAQ,MAAM,2BAA2B,KAAK;AAC9C,gBAAM,KAAK,QAAQ;AACnB;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAM,kBAAc,gCAAmB,MAAM,qBAAqB;AAElE,WAAO,MAAM;AACX,4BAAsB;AACtB,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,MAAM,qBAAqB,CAAC;AAMhC,MAAI,CAAC,UAAU,UAAU;AACvB,WACE,4CAAC,mCAAc,UAAd,EAAuB,OAAO,WAC7B,sDAAC,SAAI,aAAU,UAAS,aAAU,QAChC,sDAAC,UAAK,WAAU,WAAU,6CAA+B,GAC3D,GACF;AAAA,EAEJ;AAEA,SACE,4CAAC,mCAAc,UAAd,EAAuB,OAAO,WAC5B,UACH;AAEJ;","names":[]}
@@ -27,13 +27,15 @@ var import_react = require("react");
27
27
  var import_client_init = require("../../utils/client-init");
28
28
  function useUser() {
29
29
  const [user, setUser] = (0, import_react.useState)(null);
30
+ const [loading, setLoading] = (0, import_react.useState)(true);
30
31
  (0, import_react.useEffect)(() => {
31
32
  const unsubscribe = (0, import_auth.onAuthStateChanged)(import_client_init.ternSecureAuth, (authUser) => {
32
33
  setUser(authUser);
34
+ setLoading(false);
33
35
  });
34
36
  return () => unsubscribe();
35
37
  }, []);
36
- return user;
38
+ return { user, loading };
37
39
  }
38
40
  // Annotate the CommonJS export names for ESM import in node:
39
41
  0 && (module.exports = {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/boundary/hooks/useUser.ts"],"sourcesContent":["\"use client\";\r\n\r\nimport { onAuthStateChanged } from \"firebase/auth\";\r\nimport { useEffect, useState } from \"react\";\r\n\r\nimport { ternSecureAuth} from \"../../utils/client-init\";\r\n\r\ninterface UseUserReturn {\r\n user: any | null;\r\n loading: boolean;\r\n }\r\n\r\nexport function useUser(): UseUserReturn {\r\n const [user, setUser] = useState<any| null>(null);\r\n\r\n useEffect(() => {\r\n const unsubscribe = onAuthStateChanged(ternSecureAuth, (authUser) => {\r\n setUser(authUser);\r\n });\r\n\r\n return () => unsubscribe();\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []);\r\n\r\n return user;\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,kBAAmC;AACnC,mBAAoC;AAEpC,yBAA8B;AAOvB,SAAS,UAAyB;AACvC,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAoB,IAAI;AAEhD,8BAAU,MAAM;AACd,UAAM,kBAAc,gCAAmB,mCAAgB,CAAC,aAAa;AACnE,cAAQ,QAAQ;AAAA,IAClB,CAAC;AAED,WAAO,MAAM,YAAY;AAAA,EAE3B,GAAG,CAAC,CAAC;AAEL,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../../../src/boundary/hooks/useUser.ts"],"sourcesContent":["\"use client\";\r\n\r\nimport { onAuthStateChanged } from \"firebase/auth\";\r\nimport { useEffect, useState } from \"react\";\r\n\r\nimport { ternSecureAuth} from \"../../utils/client-init\";\r\n\r\ninterface UseUserReturn {\r\n user: any | null;\r\n loading: boolean;\r\n }\r\n\r\nexport function useUser(): UseUserReturn {\r\n const [user, setUser] = useState<any| null>(null);\r\n const [loading, setLoading] = useState(true);\r\n\r\n useEffect(() => {\r\n const unsubscribe = onAuthStateChanged(ternSecureAuth, (authUser) => {\r\n setUser(authUser);\r\n setLoading(false);\r\n });\r\n\r\n return () => unsubscribe();\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []);\r\n\r\n return {user, loading};\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,kBAAmC;AACnC,mBAAoC;AAEpC,yBAA8B;AAOvB,SAAS,UAAyB;AACvC,QAAM,CAAC,MAAM,OAAO,QAAI,uBAAoB,IAAI;AAChD,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAS,IAAI;AAE3C,8BAAU,MAAM;AACd,UAAM,kBAAc,gCAAmB,mCAAgB,CAAC,aAAa;AACnE,cAAQ,QAAQ;AAChB,iBAAW,KAAK;AAAA,IAClB,CAAC;AAED,WAAO,MAAM,YAAY;AAAA,EAE3B,GAAG,CAAC,CAAC;AAEL,SAAO,EAAC,MAAM,QAAO;AACvB;","names":[]}
@@ -25,7 +25,7 @@ async function getServerSessionCookie() {
25
25
  throw new Error("No session cookie found");
26
26
  }
27
27
  try {
28
- const decondeClaims = await adminAuth.verifySessionCookie(sessionCookie);
28
+ const decondeClaims = await adminAuth.verifySessionCookie(sessionCookie, true);
29
29
  return {
30
30
  token: sessionCookie,
31
31
  userId: decondeClaims.uid
@@ -78,7 +78,7 @@ async function verifyTernIDToken(token) {
78
78
  }
79
79
  async function verifyTernSessionCookie(session) {
80
80
  try {
81
- const res = await adminAuth.verifySessionCookie(session);
81
+ const res = await adminAuth.verifySessionCookie(session, true);
82
82
  if (res) {
83
83
  return { valid: true, uid: res.uid };
84
84
  } else {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/app-router/server/sessionTernSecure.ts"],"sourcesContent":["'use server'\r\n\r\nimport { cookies } from 'next/headers';\r\nimport { adminTernSecureAuth as adminAuth } from '../../utils/admin-init';\r\n\r\n\r\nexport interface User {\r\n uid: string;\r\n email: string;\r\n }\r\n\r\nexport interface Session {\r\n user: User | null;\r\n token: string | null;\r\n error: Error | null;\r\n}\r\n\r\nexport async function createSessionCookie(idToken: string) {\r\n try {\r\n const expiresIn = 60 * 60 * 24 * 5 * 1000;\r\n const sessionCookie = await adminAuth.createSessionCookie(idToken, { expiresIn });\r\n\r\n const cookieStore = await cookies();\r\n cookieStore.set('_session_cookie', sessionCookie, {\r\n maxAge: expiresIn,\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n path: '/',\r\n });\r\n return { success: true, message: 'Session created' };\r\n } catch (error) {\r\n return { success: false, message: 'Failed to create session' };\r\n }\r\n}\r\n\r\n\r\n\r\nexport async function getServerSessionCookie() {\r\n const cookieStore = await cookies();\r\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\r\n\r\n if (!sessionCookie) {\r\n throw new Error('No session cookie found')\r\n }\r\n \r\n try {\r\n const decondeClaims = await adminAuth.verifySessionCookie(sessionCookie)\r\n return {\r\n token: sessionCookie,\r\n userId: decondeClaims.uid\r\n }\r\n } catch (error) {\r\n console.error('Error verifying session:', error)\r\n throw new Error('Invalid Session')\r\n }\r\n}\r\n\r\n\r\nexport async function getIdToken() {\r\n const cookieStore = await cookies();\r\n const token = cookieStore.get('_session_token')?.value;\r\n\r\n if (!token) {\r\n throw new Error('No session cookie found')\r\n }\r\n \r\n try {\r\n const decodedClaims = await adminAuth.verifyIdToken(token)\r\n return {\r\n token: token,\r\n userId: decodedClaims.uid\r\n }\r\n } catch (error) {\r\n console.error('Error verifying session:', error)\r\n throw new Error('Invalid Session')\r\n }\r\n}\r\n\r\nexport async function setServerSession(token: string) {\r\n const cookieStore = await cookies();\r\n cookieStore.set('_session', token, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n maxAge: 60 * 60, // 1 hour\r\n path: '/',\r\n });\r\n }\r\n\r\n export async function verifyTernIDToken(token: string): Promise<{ valid: boolean; uid?: any; error?: any }>{\r\n try {\r\n const res = await adminAuth.verifyIdToken(token);\r\n if (res) {\r\n return { valid: true, uid: res.uid };\r\n } else {\r\n return { valid: false, error: 'Invalid token'};\r\n }\r\n } catch (error) {\r\n return {error: error, valid: false}\r\n }\r\n }\r\n\r\n export async function verifyTernSessionCookie(session: string): Promise<{ valid: boolean; uid?: any; error?: any }>{\r\n try {\r\n const res = await adminAuth.verifySessionCookie(session);\r\n if (res) {\r\n return { valid: true, uid: res.uid };\r\n } else {\r\n return { valid: false, error: 'Invalid session'};\r\n }\r\n } catch (error) {\r\n return {error: error, valid: false}\r\n }\r\n }\r\n\r\n\r\n\r\n/*\r\n export async function GET(request: NextRequest) {\r\n const cookieStore = await cookies();\r\n const sessionCookie = cookieStore.get('session')?.value\r\n \r\n if (!sessionCookie) {\r\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\r\n }\r\n \r\n try {\r\n const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie, true)\r\n return NextResponse.json({ isAuthenticated: true, user: decodedClaims }, { status: 200 })\r\n } catch (error) {\r\n console.error('Error verifying session cookie:', error)\r\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\r\n }\r\n }\r\n\r\n*/"],"mappings":";AAEA,SAAS,eAAe;AACxB,SAAS,uBAAuB,iBAAiB;AAcjD,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;AArC/C;AAsCE,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,aAAa;AACvE,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;AA1DnC;AA2DE,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;AAClD,QAAM,cAAc,MAAM,QAAQ;AAClC,cAAY,IAAI,YAAY,OAAO;AAAA,IACjC,UAAU;AAAA,IACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,IACjC,UAAU;AAAA,IACV,QAAQ,KAAK;AAAA;AAAA,IACb,MAAM;AAAA,EACR,CAAC;AACH;AAEA,eAAsB,kBAAkB,OAAmE;AACzG,MAAI;AACF,UAAM,MAAM,MAAM,UAAU,cAAc,KAAK;AAC/C,QAAI,KAAK;AACP,aAAO,EAAE,OAAO,MAAM,KAAK,IAAI,IAAI;AAAA,IACrC,OAAO;AACL,aAAO,EAAE,OAAO,OAAO,OAAO,gBAAe;AAAA,IAC/C;AAAA,EACF,SAAS,OAAO;AACd,WAAO,EAAC,OAAc,OAAO,MAAK;AAAA,EACpC;AACF;AAEA,eAAsB,wBAAwB,SAAqE;AACjH,MAAI;AACF,UAAM,MAAM,MAAM,UAAU,oBAAoB,OAAO;AACvD,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;","names":[]}
1
+ {"version":3,"sources":["../../../../src/app-router/server/sessionTernSecure.ts"],"sourcesContent":["'use server'\r\n\r\nimport { cookies } from 'next/headers';\r\nimport { adminTernSecureAuth as adminAuth } from '../../utils/admin-init';\r\n\r\n\r\nexport interface User {\r\n uid: string;\r\n email: string;\r\n }\r\n\r\nexport interface Session {\r\n user: User | null;\r\n token: string | null;\r\n error: Error | null;\r\n}\r\n\r\nexport async function createSessionCookie(idToken: string) {\r\n try {\r\n const expiresIn = 60 * 60 * 24 * 5 * 1000;\r\n const sessionCookie = await adminAuth.createSessionCookie(idToken, { expiresIn });\r\n\r\n const cookieStore = await cookies();\r\n cookieStore.set('_session_cookie', sessionCookie, {\r\n maxAge: expiresIn,\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n path: '/',\r\n });\r\n return { success: true, message: 'Session created' };\r\n } catch (error) {\r\n return { success: false, message: 'Failed to create session' };\r\n }\r\n}\r\n\r\n\r\n\r\nexport async function getServerSessionCookie() {\r\n const cookieStore = await cookies();\r\n const sessionCookie = cookieStore.get('_session_cookie')?.value;\r\n\r\n if (!sessionCookie) {\r\n throw new Error('No session cookie found')\r\n }\r\n \r\n try {\r\n const decondeClaims = await adminAuth.verifySessionCookie(sessionCookie, true)\r\n return {\r\n token: sessionCookie,\r\n userId: decondeClaims.uid\r\n }\r\n } catch (error) {\r\n console.error('Error verifying session:', error)\r\n throw new Error('Invalid Session')\r\n }\r\n}\r\n\r\n\r\nexport async function getIdToken() {\r\n const cookieStore = await cookies();\r\n const token = cookieStore.get('_session_token')?.value;\r\n\r\n if (!token) {\r\n throw new Error('No session cookie found')\r\n }\r\n \r\n try {\r\n const decodedClaims = await adminAuth.verifyIdToken(token)\r\n return {\r\n token: token,\r\n userId: decodedClaims.uid\r\n }\r\n } catch (error) {\r\n console.error('Error verifying session:', error)\r\n throw new Error('Invalid Session')\r\n }\r\n}\r\n\r\nexport async function setServerSession(token: string) {\r\n const cookieStore = await cookies();\r\n cookieStore.set('_session', token, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n maxAge: 60 * 60, // 1 hour\r\n path: '/',\r\n });\r\n }\r\n\r\n export async function verifyTernIDToken(token: string): Promise<{ valid: boolean; uid?: any; error?: any }>{\r\n try {\r\n const res = await adminAuth.verifyIdToken(token);\r\n if (res) {\r\n return { valid: true, uid: res.uid };\r\n } else {\r\n return { valid: false, error: 'Invalid token'};\r\n }\r\n } catch (error) {\r\n return {error: error, valid: false}\r\n }\r\n }\r\n\r\n export async function verifyTernSessionCookie(session: string): Promise<{ valid: boolean; uid?: any; error?: any }>{\r\n try {\r\n const res = await adminAuth.verifySessionCookie(session, true);\r\n if (res) {\r\n return { valid: true, uid: res.uid };\r\n } else {\r\n return { valid: false, error: 'Invalid session'};\r\n }\r\n } catch (error) {\r\n return {error: error, valid: false}\r\n }\r\n }\r\n\r\n\r\n\r\n/*\r\n export async function GET(request: NextRequest) {\r\n const cookieStore = await cookies();\r\n const sessionCookie = cookieStore.get('session')?.value\r\n \r\n if (!sessionCookie) {\r\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\r\n }\r\n \r\n try {\r\n const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie, true)\r\n return NextResponse.json({ isAuthenticated: true, user: decodedClaims }, { status: 200 })\r\n } catch (error) {\r\n console.error('Error verifying session cookie:', error)\r\n return NextResponse.json({ isAuthenticated: false }, { status: 401 })\r\n }\r\n }\r\n\r\n*/"],"mappings":";AAEA,SAAS,eAAe;AACxB,SAAS,uBAAuB,iBAAiB;AAcjD,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;AArC/C;AAsCE,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;AA1DnC;AA2DE,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;AAClD,QAAM,cAAc,MAAM,QAAQ;AAClC,cAAY,IAAI,YAAY,OAAO;AAAA,IACjC,UAAU;AAAA,IACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,IACjC,UAAU;AAAA,IACV,QAAQ,KAAK;AAAA;AAAA,IACb,MAAM;AAAA,EACR,CAAC;AACH;AAEA,eAAsB,kBAAkB,OAAmE;AACzG,MAAI;AACF,UAAM,MAAM,MAAM,UAAU,cAAc,KAAK;AAC/C,QAAI,KAAK;AACP,aAAO,EAAE,OAAO,MAAM,KAAK,IAAI,IAAI;AAAA,IACrC,OAAO;AACL,aAAO,EAAE,OAAO,OAAO,OAAO,gBAAe;AAAA,IAC/C;AAAA,EACF,SAAS,OAAO;AACd,WAAO,EAAC,OAAc,OAAO,MAAK;AAAA,EACpC;AACF;AAEA,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;","names":[]}
@@ -2,7 +2,7 @@
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import { useState, useEffect, useMemo, useCallback } from "react";
4
4
  import { ternSecureAuth } from "../utils/client-init";
5
- import { onAuthStateChanged } from "firebase/auth";
5
+ import { onAuthStateChanged, beforeAuthStateChanged } from "firebase/auth";
6
6
  import { TernSecureCtx } from "./TernSecureCtx";
7
7
  function TernSecureClientProvider({ children, onUserChanged }) {
8
8
  const auth = useMemo(() => ternSecureAuth, []);
@@ -34,8 +34,22 @@ function TernSecureClientProvider({ children, onUserChanged }) {
34
34
  }
35
35
  }, [auth, onUserChanged]);
36
36
  useEffect(() => {
37
+ const unsubscribeMiddleware = beforeAuthStateChanged(auth, async (user) => {
38
+ if (user) {
39
+ try {
40
+ await user.getIdToken(true);
41
+ } catch (error) {
42
+ console.error("Token validation error:", error);
43
+ await auth.signOut();
44
+ return;
45
+ }
46
+ }
47
+ });
37
48
  const unsubscribe = onAuthStateChanged(auth, handleAuthStateChange);
38
- return () => unsubscribe();
49
+ return () => {
50
+ unsubscribeMiddleware();
51
+ unsubscribe();
52
+ };
39
53
  }, [auth, handleAuthStateChange]);
40
54
  if (!authState.isLoaded) {
41
55
  return /* @__PURE__ */ jsx(TernSecureCtx.Provider, { value: authState, children: /* @__PURE__ */ jsx("div", { "aria-live": "polite", "aria-busy": "true", children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Loading authentication state..." }) }) });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/boundary/TernSecureClientProvider.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport React, { useState, useEffect, useMemo, useCallback } from 'react'\r\nimport { ternSecureAuth } from '../utils/client-init'\r\nimport { onAuthStateChanged, User } from \"firebase/auth\"\r\nimport { TernSecureCtx, TernSecureState } from './TernSecureCtx'\r\n\r\ninterface TernSecureClientProviderProps {\r\n children: React.ReactNode;\r\n onUserChanged?: (user: User | null) => Promise<void>;\r\n}\r\n\r\nexport function TernSecureClientProvider({ children, onUserChanged }: TernSecureClientProviderProps) {\r\n const auth = useMemo(() => ternSecureAuth, []);\r\n\r\n const [authState, setAuthState] = useState<TernSecureState>(() => ({\r\n userId: null,\r\n isLoaded: false,\r\n error: null,\r\n }));\r\n\r\n const handleAuthStateChange = useCallback(async (user: User | null) => {\r\n try {\r\n if(!user) {\r\n await auth.signOut();\r\n }\r\n\r\n if (onUserChanged) {\r\n await onUserChanged(user);\r\n }\r\n setAuthState({\r\n isLoaded: true,\r\n userId: user?.uid || null,\r\n error: null\r\n });\r\n } catch (error) {\r\n auth.signOut();\r\n setAuthState({\r\n isLoaded: true,\r\n userId: null,\r\n error: error instanceof Error ? error : new Error('An unknown error occurred')\r\n });\r\n }\r\n }, [auth, onUserChanged]);\r\n\r\n useEffect(() => {\r\n const unsubscribe = onAuthStateChanged(auth, handleAuthStateChange);\r\n \r\n return () => unsubscribe();\r\n }, [auth, handleAuthStateChange]);\r\n\r\n /*const contextValue: TernSecureCtxValue = useMemo(() => ({\r\n ...authState\r\n }), [authState]);*/\r\n\r\n if (!authState.isLoaded) {\r\n return (\r\n <TernSecureCtx.Provider value={authState}>\r\n <div aria-live=\"polite\" aria-busy=\"true\">\r\n <span className=\"sr-only\">Loading authentication state...</span>\r\n </div>\r\n </TernSecureCtx.Provider>\r\n );\r\n }\r\n\r\n return (\r\n <TernSecureCtx.Provider value={authState}>\r\n {children}\r\n </TernSecureCtx.Provider>\r\n );\r\n}\r\n\r\n"],"mappings":";AA2DU;AAzDV,SAAgB,UAAU,WAAW,SAAS,mBAAmB;AACjE,SAAS,sBAAsB;AAC/B,SAAS,0BAAgC;AACzC,SAAS,qBAAsC;AAOxC,SAAS,yBAAyB,EAAE,UAAU,cAAc,GAAkC;AACnG,QAAM,OAAO,QAAQ,MAAM,gBAAgB,CAAC,CAAC;AAE7C,QAAM,CAAC,WAAW,YAAY,IAAI,SAA0B,OAAO;AAAA,IAC/D,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,OAAO;AAAA,EACX,EAAE;AAEF,QAAM,wBAAwB,YAAY,OAAO,SAAsB;AACrE,QAAI;AACF,UAAG,CAAC,MAAM;AACR,cAAM,KAAK,QAAQ;AAAA,MACrB;AAEA,UAAI,eAAe;AACjB,cAAM,cAAc,IAAI;AAAA,MAC1B;AACA,mBAAa;AAAA,QACX,UAAU;AAAA,QACV,SAAQ,6BAAM,QAAO;AAAA,QACrB,OAAO;AAAA,MACT,CAAC;AAAA,IACH,SAAS,OAAO;AACd,WAAK,QAAQ;AACb,mBAAa;AAAA,QACX,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,2BAA2B;AAAA,MAC/E,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,MAAM,aAAa,CAAC;AAExB,YAAU,MAAM;AACd,UAAM,cAAc,mBAAmB,MAAM,qBAAqB;AAElE,WAAO,MAAM,YAAY;AAAA,EAC3B,GAAG,CAAC,MAAM,qBAAqB,CAAC;AAMhC,MAAI,CAAC,UAAU,UAAU;AACvB,WACE,oBAAC,cAAc,UAAd,EAAuB,OAAO,WAC7B,8BAAC,SAAI,aAAU,UAAS,aAAU,QAChC,8BAAC,UAAK,WAAU,WAAU,6CAA+B,GAC3D,GACF;AAAA,EAEJ;AAEA,SACE,oBAAC,cAAc,UAAd,EAAuB,OAAO,WAC5B,UACH;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/boundary/TernSecureClientProvider.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport React, { useState, useEffect, useMemo, useCallback } from 'react'\r\nimport { ternSecureAuth } from '../utils/client-init'\r\nimport { onAuthStateChanged, User, beforeAuthStateChanged, ParsedToken } from \"firebase/auth\"\r\nimport { TernSecureCtx, TernSecureState } from './TernSecureCtx'\r\n\r\ninterface TernSecureClientProviderProps {\r\n children: React.ReactNode;\r\n onUserChanged?: (user: User | null) => Promise<void>;\r\n}\r\n\r\n\r\nexport function TernSecureClientProvider({ children, onUserChanged }: TernSecureClientProviderProps) {\r\n const auth = useMemo(() => ternSecureAuth, []);\r\n\r\n const [authState, setAuthState] = useState<TernSecureState>(() => ({\r\n userId: null,\r\n isLoaded: false,\r\n error: null,\r\n }));\r\n\r\n const handleAuthStateChange = useCallback(async (user: User | null) => {\r\n try {\r\n if(!user) {\r\n await auth.signOut();\r\n }\r\n\r\n if (onUserChanged) {\r\n await onUserChanged(user);\r\n }\r\n setAuthState({\r\n isLoaded: true,\r\n userId: user?.uid || null,\r\n error: null\r\n });\r\n } catch (error) {\r\n auth.signOut();\r\n setAuthState({\r\n isLoaded: true,\r\n userId: null,\r\n error: error instanceof Error ? error : new Error('An unknown error occurred')\r\n });\r\n }\r\n }, [auth, onUserChanged]);\r\n\r\n useEffect(() => {\r\n const unsubscribeMiddleware = beforeAuthStateChanged(auth, async (user) => {\r\n if(user) {\r\n try {\r\n await user.getIdToken(true);\r\n } catch (error) {\r\n console.error('Token validation error:', error);\r\n await auth.signOut();\r\n return;\r\n }\r\n }\r\n });\r\n\r\n const unsubscribe = onAuthStateChanged(auth, handleAuthStateChange);\r\n \r\n return () => {\r\n unsubscribeMiddleware();\r\n unsubscribe();\r\n };\r\n }, [auth, handleAuthStateChange]);\r\n\r\n /*const contextValue: TernSecureCtxValue = useMemo(() => ({\r\n ...authState\r\n }), [authState]);*/\r\n\r\n if (!authState.isLoaded) {\r\n return (\r\n <TernSecureCtx.Provider value={authState}>\r\n <div aria-live=\"polite\" aria-busy=\"true\">\r\n <span className=\"sr-only\">Loading authentication state...</span>\r\n </div>\r\n </TernSecureCtx.Provider>\r\n );\r\n }\r\n\r\n return (\r\n <TernSecureCtx.Provider value={authState}>\r\n {children}\r\n </TernSecureCtx.Provider>\r\n );\r\n}\r\n\r\n"],"mappings":";AA2EU;AAzEV,SAAgB,UAAU,WAAW,SAAS,mBAAmB;AACjE,SAAS,sBAAsB;AAC/B,SAAS,oBAA0B,8BAA2C;AAC9E,SAAS,qBAAsC;AAQxC,SAAS,yBAAyB,EAAE,UAAU,cAAc,GAAkC;AACnG,QAAM,OAAO,QAAQ,MAAM,gBAAgB,CAAC,CAAC;AAE7C,QAAM,CAAC,WAAW,YAAY,IAAI,SAA0B,OAAO;AAAA,IAC/D,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,OAAO;AAAA,EACX,EAAE;AAEF,QAAM,wBAAwB,YAAY,OAAO,SAAsB;AACrE,QAAI;AACF,UAAG,CAAC,MAAM;AACR,cAAM,KAAK,QAAQ;AAAA,MACrB;AAEA,UAAI,eAAe;AACjB,cAAM,cAAc,IAAI;AAAA,MAC1B;AACA,mBAAa;AAAA,QACX,UAAU;AAAA,QACV,SAAQ,6BAAM,QAAO;AAAA,QACrB,OAAO;AAAA,MACT,CAAC;AAAA,IACH,SAAS,OAAO;AACd,WAAK,QAAQ;AACb,mBAAa;AAAA,QACX,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,2BAA2B;AAAA,MAC/E,CAAC;AAAA,IACH;AAAA,EACF,GAAG,CAAC,MAAM,aAAa,CAAC;AAExB,YAAU,MAAM;AACd,UAAM,wBAAwB,uBAAuB,MAAM,OAAO,SAAS;AACzE,UAAG,MAAM;AACP,YAAI;AACF,gBAAM,KAAK,WAAW,IAAI;AAAA,QAC5B,SAAS,OAAO;AACd,kBAAQ,MAAM,2BAA2B,KAAK;AAC9C,gBAAM,KAAK,QAAQ;AACnB;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAM,cAAc,mBAAmB,MAAM,qBAAqB;AAElE,WAAO,MAAM;AACX,4BAAsB;AACtB,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,MAAM,qBAAqB,CAAC;AAMhC,MAAI,CAAC,UAAU,UAAU;AACvB,WACE,oBAAC,cAAc,UAAd,EAAuB,OAAO,WAC7B,8BAAC,SAAI,aAAU,UAAS,aAAU,QAChC,8BAAC,UAAK,WAAU,WAAU,6CAA+B,GAC3D,GACF;AAAA,EAEJ;AAEA,SACE,oBAAC,cAAc,UAAd,EAAuB,OAAO,WAC5B,UACH;AAEJ;","names":[]}
@@ -4,13 +4,15 @@ import { useEffect, useState } from "react";
4
4
  import { ternSecureAuth } from "../../utils/client-init";
5
5
  function useUser() {
6
6
  const [user, setUser] = useState(null);
7
+ const [loading, setLoading] = useState(true);
7
8
  useEffect(() => {
8
9
  const unsubscribe = onAuthStateChanged(ternSecureAuth, (authUser) => {
9
10
  setUser(authUser);
11
+ setLoading(false);
10
12
  });
11
13
  return () => unsubscribe();
12
14
  }, []);
13
- return user;
15
+ return { user, loading };
14
16
  }
15
17
  export {
16
18
  useUser
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/boundary/hooks/useUser.ts"],"sourcesContent":["\"use client\";\r\n\r\nimport { onAuthStateChanged } from \"firebase/auth\";\r\nimport { useEffect, useState } from \"react\";\r\n\r\nimport { ternSecureAuth} from \"../../utils/client-init\";\r\n\r\ninterface UseUserReturn {\r\n user: any | null;\r\n loading: boolean;\r\n }\r\n\r\nexport function useUser(): UseUserReturn {\r\n const [user, setUser] = useState<any| null>(null);\r\n\r\n useEffect(() => {\r\n const unsubscribe = onAuthStateChanged(ternSecureAuth, (authUser) => {\r\n setUser(authUser);\r\n });\r\n\r\n return () => unsubscribe();\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []);\r\n\r\n return user;\r\n}\r\n"],"mappings":";AAEA,SAAS,0BAA0B;AACnC,SAAS,WAAW,gBAAgB;AAEpC,SAAS,sBAAqB;AAOvB,SAAS,UAAyB;AACvC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAoB,IAAI;AAEhD,YAAU,MAAM;AACd,UAAM,cAAc,mBAAmB,gBAAgB,CAAC,aAAa;AACnE,cAAQ,QAAQ;AAAA,IAClB,CAAC;AAED,WAAO,MAAM,YAAY;AAAA,EAE3B,GAAG,CAAC,CAAC;AAEL,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../../../src/boundary/hooks/useUser.ts"],"sourcesContent":["\"use client\";\r\n\r\nimport { onAuthStateChanged } from \"firebase/auth\";\r\nimport { useEffect, useState } from \"react\";\r\n\r\nimport { ternSecureAuth} from \"../../utils/client-init\";\r\n\r\ninterface UseUserReturn {\r\n user: any | null;\r\n loading: boolean;\r\n }\r\n\r\nexport function useUser(): UseUserReturn {\r\n const [user, setUser] = useState<any| null>(null);\r\n const [loading, setLoading] = useState(true);\r\n\r\n useEffect(() => {\r\n const unsubscribe = onAuthStateChanged(ternSecureAuth, (authUser) => {\r\n setUser(authUser);\r\n setLoading(false);\r\n });\r\n\r\n return () => unsubscribe();\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []);\r\n\r\n return {user, loading};\r\n}\r\n"],"mappings":";AAEA,SAAS,0BAA0B;AACnC,SAAS,WAAW,gBAAgB;AAEpC,SAAS,sBAAqB;AAOvB,SAAS,UAAyB;AACvC,QAAM,CAAC,MAAM,OAAO,IAAI,SAAoB,IAAI;AAChD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAE3C,YAAU,MAAM;AACd,UAAM,cAAc,mBAAmB,gBAAgB,CAAC,aAAa;AACnE,cAAQ,QAAQ;AAChB,iBAAW,KAAK;AAAA,IAClB,CAAC;AAED,WAAO,MAAM,YAAY;AAAA,EAE3B,GAAG,CAAC,CAAC;AAEL,SAAO,EAAC,MAAM,QAAO;AACvB;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"TernSecureClientProvider.d.ts","sourceRoot":"","sources":["../../../src/boundary/TernSecureClientProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAoD,MAAM,OAAO,CAAA;AAExE,OAAO,EAAsB,IAAI,EAAE,MAAM,eAAe,CAAA;AAGxD,UAAU,6BAA6B;IACrC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtD;AAED,wBAAgB,wBAAwB,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,6BAA6B,2CA0DlG"}
1
+ {"version":3,"file":"TernSecureClientProvider.d.ts","sourceRoot":"","sources":["../../../src/boundary/TernSecureClientProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAoD,MAAM,OAAO,CAAA;AAExE,OAAO,EAAsB,IAAI,EAAuC,MAAM,eAAe,CAAA;AAG7F,UAAU,6BAA6B;IACrC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtD;AAGD,wBAAgB,wBAAwB,CAAC,EAAE,QAAQ,EAAE,aAAa,EAAE,EAAE,6BAA6B,2CAyElG"}
@@ -1 +1 @@
1
- {"version":3,"file":"useUser.d.ts","sourceRoot":"","sources":["../../../../src/boundary/hooks/useUser.ts"],"names":[],"mappings":"AAOA,UAAU,aAAa;IACnB,IAAI,EAAE,GAAG,GAAG,IAAI,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB;AAEH,wBAAgB,OAAO,IAAI,aAAa,CAavC"}
1
+ {"version":3,"file":"useUser.d.ts","sourceRoot":"","sources":["../../../../src/boundary/hooks/useUser.ts"],"names":[],"mappings":"AAOA,UAAU,aAAa;IACnB,IAAI,EAAE,GAAG,GAAG,IAAI,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;CAClB;AAEH,wBAAgB,OAAO,IAAI,aAAa,CAevC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tern-secure/nextjs",
3
- "version": "3.2.26",
3
+ "version": "3.2.28",
4
4
  "packageManager": "npm@10.9.0",
5
5
  "publishConfig": {
6
6
  "access": "public"