@tern-secure/backend 1.2.0-canary.v20250919134427 → 1.2.0-canary.v20250926170202

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 (56) hide show
  1. package/dist/admin/index.js +207 -180
  2. package/dist/admin/index.js.map +1 -1
  3. package/dist/admin/index.mjs +152 -105
  4. package/dist/admin/index.mjs.map +1 -1
  5. package/dist/admin/nextSessionTernSecure.d.ts.map +1 -1
  6. package/dist/admin/sessionTernSecure.d.ts +24 -5
  7. package/dist/admin/sessionTernSecure.d.ts.map +1 -1
  8. package/dist/{chunk-ZIO4EKS5.mjs → chunk-ZMDLKXUP.mjs} +6 -29
  9. package/dist/chunk-ZMDLKXUP.mjs.map +1 -0
  10. package/dist/constants.d.ts +4 -5
  11. package/dist/constants.d.ts.map +1 -1
  12. package/dist/fireRestApi/createFireApi.d.ts +12 -0
  13. package/dist/fireRestApi/createFireApi.d.ts.map +1 -0
  14. package/dist/fireRestApi/endpointUrl.d.ts +6 -0
  15. package/dist/fireRestApi/endpointUrl.d.ts.map +1 -0
  16. package/dist/fireRestApi/endpoints/AbstractApi.d.ts +7 -0
  17. package/dist/fireRestApi/endpoints/AbstractApi.d.ts.map +1 -0
  18. package/dist/fireRestApi/endpoints/EmailApi.d.ts +14 -0
  19. package/dist/fireRestApi/endpoints/EmailApi.d.ts.map +1 -0
  20. package/dist/fireRestApi/endpoints/PasswordApi.d.ts +20 -0
  21. package/dist/fireRestApi/endpoints/PasswordApi.d.ts.map +1 -0
  22. package/dist/fireRestApi/endpoints/SignInTokenApi.d.ts +11 -0
  23. package/dist/fireRestApi/endpoints/SignInTokenApi.d.ts.map +1 -0
  24. package/dist/fireRestApi/endpoints/SignUpApi.d.ts +11 -0
  25. package/dist/fireRestApi/endpoints/SignUpApi.d.ts.map +1 -0
  26. package/dist/fireRestApi/endpoints/TokenApi.d.ts +15 -0
  27. package/dist/fireRestApi/endpoints/TokenApi.d.ts.map +1 -0
  28. package/dist/fireRestApi/endpoints/index.d.ts +6 -0
  29. package/dist/fireRestApi/endpoints/index.d.ts.map +1 -0
  30. package/dist/fireRestApi/index.d.ts +2 -0
  31. package/dist/fireRestApi/index.d.ts.map +1 -0
  32. package/dist/fireRestApi/request.d.ts +37 -0
  33. package/dist/fireRestApi/request.d.ts.map +1 -0
  34. package/dist/fireRestApi/resources/JSON.d.ts +44 -0
  35. package/dist/fireRestApi/resources/JSON.d.ts.map +1 -0
  36. package/dist/fireRestApi/resources/Token.d.ts +7 -0
  37. package/dist/fireRestApi/resources/Token.d.ts.map +1 -0
  38. package/dist/index.js +178 -66
  39. package/dist/index.js.map +1 -1
  40. package/dist/index.mjs +161 -38
  41. package/dist/index.mjs.map +1 -1
  42. package/dist/instance/backendFireInstance.d.ts +4 -4
  43. package/dist/instance/backendFireInstance.d.ts.map +1 -1
  44. package/dist/instance/backendInstanceEdge.d.ts +2 -2
  45. package/dist/instance/backendInstanceEdge.d.ts.map +1 -1
  46. package/dist/tokens/authstate.d.ts +1 -1
  47. package/dist/tokens/authstate.d.ts.map +1 -1
  48. package/dist/tokens/request.d.ts +3 -3
  49. package/dist/tokens/request.d.ts.map +1 -1
  50. package/dist/tokens/requestFire.d.ts.map +1 -1
  51. package/dist/tokens/types.d.ts +4 -2
  52. package/dist/tokens/types.d.ts.map +1 -1
  53. package/package.json +3 -3
  54. package/dist/admin/gemini.sessionTernSecure.d.ts +0 -8
  55. package/dist/admin/gemini.sessionTernSecure.d.ts.map +0 -1
  56. package/dist/chunk-ZIO4EKS5.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/admin/index.ts","../../src/admin/sessionTernSecure.ts","../../src/tokens/sessionConfig.ts","../../src/utils/admin-init.ts","../../src/utils/config.ts","../../src/admin/tenant.ts","../../src/admin/nextSessionTernSecure.ts","../../src/tokens/ternSecureRequest.ts","../../src/constants.ts","../../src/tokens/ternUrl.ts","../../src/instance/backendInstance.ts"],"sourcesContent":["export { \n createSessionCookie, \n clearSessionCookie\n} from './sessionTernSecure'\nexport { \n adminTernSecureAuth, \n adminTernSecureDb, \n TernSecureTenantManager \n} from '../utils/admin-init'\nexport { initializeAdminConfig } from '../utils/config'\nexport { createTenant, createTenantUser } from './tenant'\nexport { \n CreateNextSessionCookie,\n GetNextServerSessionCookie,\n GetNextIdToken,\n SetNextServerSession,\n SetNextServerToken,\n VerifyNextTernIdToken,\n VerifyNextTernSessionCookie,\n ClearNextSessionCookie\n} from './nextSessionTernSecure'\n\nexport type { SignInAuthObject, RequestState } from '../instance/backendInstance'\nexport { createBackendInstance, authenticateRequest, signedIn } from '../instance/backendInstance'","\"use server\";\r\n\r\nimport { handleFirebaseAuthError } from \"@tern-secure/shared/errors\";\r\nimport type {\r\n CookieStore,\r\n SessionParams,\r\n SessionResult,\r\n} from \"@tern-secure/types\";\r\n\r\nimport { getCookieOptions, getSessionConfig } from \"../tokens/sessionConfig\";\r\nimport type { RequestOptions } from \"../tokens/types\";\r\nimport { getAuthForTenant } from \"../utils/admin-init\";\r\n\r\nconst SESSION_CONSTANTS = {\r\n COOKIE_NAME: \"_session_cookie\",\r\n //DEFAULT_EXPIRES_IN_MS: 60 * 60 * 24 * 5 * 1000, // 5 days\r\n //DEFAULT_EXPIRES_IN_SECONDS: 60 * 60 * 24 * 5, // 5days\r\n DEFAULT_EXPIRES_IN_MS: 5 * 60 * 1000, // 5 minutes\r\n DEFAULT_EXPIRES_IN_SECONDS: 5 * 60,\r\n REVOKE_REFRESH_TOKENS_ON_SIGNOUT: true,\r\n} as const;\r\n\r\nconst COOKIE_OPTIONS = {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === \"production\",\r\n sameSite: \"strict\" as const,\r\n path: \"/\",\r\n} as const;\r\n\r\n\r\nexport async function createSessionCookie(\r\n params: SessionParams | string,\r\n cookieStore: CookieStore,\r\n options?: RequestOptions\r\n): Promise<SessionResult> {\r\n try {\r\n const tenantAuth = getAuthForTenant(options?.tenantId);\r\n\r\n const sessionConfig = getSessionConfig(options);\r\n const cookieOptions = getCookieOptions(options);\r\n \r\n let decodedToken;\r\n let sessionCookie;\r\n\r\n const idToken = typeof params === \"string\" ? params : params.idToken;\r\n\r\n if (!idToken) {\r\n const error = new Error(\"ID token is required for session creation\");\r\n console.error(\"[createSessionCookie] Missing ID token:\", error);\r\n return {\r\n success: false,\r\n message: \"ID token is required\",\r\n error: \"INVALID_TOKEN\",\r\n cookieSet: false,\r\n };\r\n }\r\n\r\n try {\r\n console.log(\"Verifying ID token for tenant:\", options?.tenantId);\r\n decodedToken = await tenantAuth.verifyIdToken(idToken);\r\n } catch (verifyError) {\r\n console.error(\r\n \"[createSessionCookie] ID token verification failed:\",\r\n verifyError\r\n );\r\n const authError = handleFirebaseAuthError(verifyError);\r\n return {\r\n success: false,\r\n message: authError.message,\r\n error: authError.code,\r\n cookieSet: false,\r\n };\r\n }\r\n\r\n if (!decodedToken) {\r\n const error = new Error(\"Invalid ID token - verification returned null\");\r\n console.error(\r\n \"[createSessionCookie] Token verification returned null:\",\r\n error\r\n );\r\n return {\r\n success: false,\r\n message: \"Invalid ID token\",\r\n error: \"INVALID_TOKEN\",\r\n cookieSet: false,\r\n };\r\n }\r\n\r\n try {\r\n sessionCookie = await tenantAuth.createSessionCookie(idToken, {\r\n expiresIn: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_MS,\r\n });\r\n } catch (sessionError) {\r\n console.error(\r\n \"[createSessionCookie] Firebase session cookie creation failed:\",\r\n sessionError\r\n );\r\n const authError = handleFirebaseAuthError(sessionError);\r\n return {\r\n success: false,\r\n message: authError.message,\r\n error: authError.code,\r\n cookieSet: false,\r\n };\r\n }\r\n\r\n // Set the cookie and verify it was set\r\n let cookieSetSuccessfully = false;\r\n try {\r\n //const cookieStore = await cookies();\r\n cookieStore.set(SESSION_CONSTANTS.COOKIE_NAME, sessionCookie, {\r\n maxAge: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_SECONDS,\r\n ...COOKIE_OPTIONS,\r\n });\r\n\r\n // Verify the cookie was actually set\r\n const verifySetCookie = await cookieStore.get(\r\n SESSION_CONSTANTS.COOKIE_NAME\r\n );\r\n cookieSetSuccessfully = !!verifySetCookie?.value;\r\n\r\n if (!cookieSetSuccessfully) {\r\n const error = new Error(\"Session cookie was not set successfully\");\r\n console.error(\r\n \"[createSessionCookie] Cookie verification failed:\",\r\n error\r\n );\r\n throw error;\r\n }\r\n } catch (cookieError) {\r\n console.error(\r\n \"[createSessionCookie] Failed to set session cookie:\",\r\n cookieError\r\n );\r\n return {\r\n success: false,\r\n message: \"Failed to set session cookie\",\r\n error: \"COOKIE_SET_FAILED\",\r\n cookieSet: false,\r\n };\r\n }\r\n\r\n console.log(\r\n `[createSessionCookie] Session cookie created successfully for user: ${decodedToken.uid}`\r\n );\r\n return {\r\n success: true,\r\n message: \"Session created successfully\",\r\n expiresIn: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_SECONDS,\r\n cookieSet: cookieSetSuccessfully,\r\n };\r\n } catch (error) {\r\n console.error(\"[createSessionCookie] Unexpected error:\", error);\r\n const authError = handleFirebaseAuthError(error);\r\n return {\r\n success: false,\r\n message: authError.message || \"Failed to create session\",\r\n error: authError.code || \"INTERNAL_ERROR\",\r\n cookieSet: false,\r\n };\r\n }\r\n}\r\n\r\nexport async function clearSessionCookie(\r\n cookieStore: CookieStore,\r\n options?: RequestOptions\r\n): Promise<SessionResult> {\r\n try {\r\n const adminAuth = getAuthForTenant(options?.tenantId);\r\n const sessionCookie = await cookieStore.get(SESSION_CONSTANTS.COOKIE_NAME);\r\n\r\n await cookieStore.delete(SESSION_CONSTANTS.COOKIE_NAME);\r\n await cookieStore.delete(\"_session_token\");\r\n await cookieStore.delete(\"_session\");\r\n\r\n if (\r\n SESSION_CONSTANTS.REVOKE_REFRESH_TOKENS_ON_SIGNOUT &&\r\n sessionCookie?.value\r\n ) {\r\n try {\r\n const decodedClaims = await adminAuth.verifySessionCookie(\r\n sessionCookie.value\r\n );\r\n await adminAuth.revokeRefreshTokens(decodedClaims.sub);\r\n console.log(\r\n `[clearSessionCookie] Successfully revoked tokens for user: ${decodedClaims.sub}`\r\n );\r\n } catch (revokeError) {\r\n console.error(\r\n \"[clearSessionCookie] Failed to revoke refresh tokens:\",\r\n revokeError\r\n );\r\n }\r\n }\r\n\r\n console.log(\"[clearSessionCookie] Session cookies cleared successfully\");\r\n return {\r\n success: true,\r\n message: \"Session cleared successfully\",\r\n cookieSet: false,\r\n };\r\n } catch (error) {\r\n console.error(\"[clearSessionCookie] Unexpected error:\", error);\r\n const authError = handleFirebaseAuthError(error);\r\n return {\r\n success: false,\r\n message: authError.message || \"Failed to clear session\",\r\n error: authError.code || \"INTERNAL_ERROR\",\r\n cookieSet: false,\r\n };\r\n }\r\n}\r\n\r\nexport async function createCustomToken(uid: string, options?: RequestOptions): Promise<string | null> {\r\n const adminAuth = getAuthForTenant(options?.tenantId);\r\n try {\r\n const customToken = await adminAuth.createCustomToken(uid);\r\n return customToken;\r\n } catch (error) {\r\n console.error(\"[createCustomToken] Error creating custom token:\", error);\r\n return null;\r\n }\r\n}\r\n","import type { RequestOptions } from \"./types\";\n\nexport const getSessionConfig = (options?: RequestOptions) => {\n const cookieConfig = options?.cookies?.session_cookie;\n \n return {\n COOKIE_NAME: cookieConfig?.name,\n DEFAULT_EXPIRES_IN_MS: cookieConfig?.attributes?.maxAge,\n DEFAULT_EXPIRES_IN_SECONDS: Math.floor((cookieConfig?.attributes?.maxAge || 0) / 1000),\n REVOKE_REFRESH_TOKENS_ON_SIGNOUT: cookieConfig?.revokeRefreshTokensOnSignOut,\n };\n};\n\n\nexport const getCookieOptions = (options?: RequestOptions) => {\n const cookieConfig = options?.cookies?.session_cookie;\n \n return {\n httpOnly: cookieConfig?.attributes?.httpOnly,\n secure: cookieConfig?.attributes?.secure,\n sameSite: cookieConfig?.attributes?.sameSite,\n path: cookieConfig?.attributes?.path,\n };\n};","import admin from 'firebase-admin';\r\n\r\nimport { initializeAdminConfig } from './config';\r\n\r\nif (!admin.apps.length) {\r\n try {\r\n const config = initializeAdminConfig();\r\n admin.initializeApp({\r\n credential: admin.credential.cert({\r\n ...config,\r\n privateKey: config.privateKey.replace(/\\\\n/g, '\\n'),\r\n }),\r\n });\r\n } catch (error) {\r\n console.error('Firebase admin initialization error', error);\r\n }\r\n}\r\n\r\nexport const adminTernSecureAuth: admin.auth.Auth = admin.auth();\r\nexport const adminTernSecureDb: admin.firestore.Firestore = admin.firestore();\r\nexport const TernSecureTenantManager: admin.auth.TenantManager = admin.auth().tenantManager();\r\n\r\n/**\r\n * Gets the appropriate Firebase Auth instance.\r\n * If a tenantId is provided, it returns the Auth instance for that tenant.\r\n * Otherwise, it returns the default project-level Auth instance.\r\n * @param tenantId - The optional tenant ID.\r\n * @returns An admin.auth.Auth instance.\r\n */\r\nexport function getAuthForTenant(tenantId?: string): admin.auth.Auth {\r\n if (tenantId) {\r\n return TernSecureTenantManager.authForTenant(tenantId) as unknown as admin.auth.Auth;\r\n }\r\n return admin.auth();\r\n}","import type { \r\n AdminConfigValidationResult, \r\n ConfigValidationResult, \r\n TernSecureAdminConfig, \r\n TernSecureConfig} from '@tern-secure/types'\r\n\r\n/**\r\n * Loads Firebase configuration from environment variables\r\n * @returns {TernSecureConfig} Firebase configuration object\r\n */\r\nexport const loadFireConfig = (): TernSecureConfig => ({\r\n apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY || '',\r\n authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN || '',\r\n projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID || '',\r\n storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET || '',\r\n messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID || '',\r\n appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID || '',\r\n measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID || undefined,\r\n})\r\n\r\n/**\r\n * Validates Firebase configuration\r\n * @param {TernSecureConfig} config - Firebase configuration object\r\n * @throws {Error} If required configuration values are missing\r\n * @returns {TernSecureConfig} Validated configuration object\r\n */\r\nexport const validateConfig = (config: TernSecureConfig): ConfigValidationResult => {\r\n const requiredFields: (keyof TernSecureConfig)[] = [\r\n 'apiKey',\r\n 'authDomain',\r\n 'projectId',\r\n 'storageBucket',\r\n 'messagingSenderId',\r\n 'appId'\r\n ]\r\n\r\n const errors: string[] = []\r\n \r\n requiredFields.forEach(field => {\r\n if (!config[field]) {\r\n errors.push(`Missing required field: NEXT_PUBLIC_FIREBASE_${String(field).toUpperCase()}`)\r\n }\r\n })\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n config\r\n }\r\n}\r\n\r\n/**\r\n * Initializes configuration with validation\r\n * @throws {Error} If configuration is invalid\r\n */\r\nexport const initializeConfig = (): TernSecureConfig => {\r\n const config = loadFireConfig()\r\n const validationResult = validateConfig(config)\r\n\r\n if (!validationResult.isValid) {\r\n throw new Error(\r\n `Firebase configuration validation failed:\\n${validationResult.errors.join('\\n')}`\r\n )\r\n }\r\n\r\n return config\r\n}\r\n\r\n/**\r\n * Loads Firebase Admin configuration from environment variables\r\n * @returns {AdminConfig} Firebase Admin configuration object\r\n */\r\nexport const loadAdminConfig = (): TernSecureAdminConfig => ({\r\n projectId: process.env.FIREBASE_PROJECT_ID || '',\r\n clientEmail: process.env.FIREBASE_CLIENT_EMAIL || '',\r\n privateKey: process.env.FIREBASE_PRIVATE_KEY || '',\r\n})\r\n\r\n/**\r\n * Validates Firebase Admin configuration\r\n * @param {AdminConfig} config - Firebase Admin configuration object\r\n * @returns {ConfigValidationResult} Validation result\r\n */\r\nexport const validateAdminConfig = (config: TernSecureAdminConfig): AdminConfigValidationResult => {\r\n const requiredFields: (keyof TernSecureAdminConfig)[] = [\r\n 'projectId',\r\n 'clientEmail',\r\n 'privateKey'\r\n ]\r\n\r\n const errors: string[] = []\r\n \r\n requiredFields.forEach(field => {\r\n if (!config[field]) {\r\n errors.push(`Missing required field: FIREBASE_${String(field).toUpperCase()}`)\r\n }\r\n })\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n config\r\n }\r\n}\r\n\r\n/**\r\n * Initializes admin configuration with validation\r\n * @throws {Error} If configuration is invalid\r\n */\r\nexport const initializeAdminConfig = (): TernSecureAdminConfig => {\r\n const config = loadAdminConfig()\r\n const validationResult = validateAdminConfig(config)\r\n\r\n if (!validationResult.isValid) {\r\n throw new Error(\r\n `Firebase Admin configuration validation failed:\\n${validationResult.errors.join('\\n')}`\r\n )\r\n }\r\n\r\n return config\r\n}","import type { SignInResponse } from '@tern-secure/types';\r\n\r\nimport { TernSecureTenantManager } from \"../utils/admin-init\";\r\n\r\n\r\nexport async function createTenant(\r\n displayName: string,\r\n emailSignInConfig: {\r\n enabled: boolean;\r\n passwordRequired: boolean;\r\n },\r\n multiFactorConfig?: {\r\n state: 'ENABLED' | 'DISABLED';\r\n factorIds: \"phone\"[];\r\n testPhoneNumbers?: {\r\n [phoneNumber: string]: string;\r\n }\r\n }\r\n) {\r\n try {\r\n const tenantConfig = {\r\n displayName,\r\n emailSignInConfig,\r\n ...(multiFactorConfig && { multiFactorConfig })\r\n };\r\n\r\n const tenant = await TernSecureTenantManager.createTenant(tenantConfig);\r\n \r\n return {\r\n success: true,\r\n tenantId: tenant.tenantId,\r\n displayName: tenant.displayName,\r\n };\r\n } catch (error) {\r\n console.error('Error creating tenant:', error);\r\n throw new Error('Failed to create tenant');\r\n }\r\n}\r\n\r\nexport async function createTenantUser(\r\n email: string,\r\n password: string,\r\n tenantId: string\r\n): Promise<SignInResponse> {\r\n try {\r\n const tenantAuth = TernSecureTenantManager.authForTenant(tenantId);\r\n \r\n const userRecord = await tenantAuth.createUser({\r\n email,\r\n password,\r\n emailVerified: false,\r\n disabled: false\r\n });\r\n\r\n return {\r\n success: true,\r\n message: 'Tenant user created successfully',\r\n user: userRecord.uid,\r\n };\r\n } catch (error) {\r\n console.error('Error creating tenant user:', error);\r\n throw new Error('Failed to create tenant user');\r\n }\r\n}\r\n","\"use server\";\n\nimport { handleFirebaseAuthError } from \"@tern-secure/shared/errors\";\nimport type { TernVerificationResult } from \"@tern-secure/types\";\nimport { cookies } from \"next/headers\";\n\nimport { adminTernSecureAuth as adminAuth, getAuthForTenant } from \"../utils/admin-init\";\n\n\nconst SESSION_CONSTANTS = {\n COOKIE_NAME: \"_session_cookie\",\n DEFAULT_EXPIRES_IN_MS: 60 * 60 * 24 * 5 * 1000, // 5 days\n DEFAULT_EXPIRES_IN_SECONDS: 60 * 60 * 24 * 5,\n REVOKE_REFRESH_TOKENS_ON_SIGNOUT: true,\n} as const;\n\nexport async function CreateNextSessionCookie(idToken: string) {\n try {\n const expiresIn = 60 * 60 * 24 * 5 * 1000;\n const sessionCookie = await adminAuth.createSessionCookie(idToken, {\n expiresIn,\n });\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\nexport async function GetNextServerSessionCookie() {\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(\n sessionCookie,\n true\n );\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\nexport async function GetNextIdToken() {\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 SetNextServerSession(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\nexport async function SetNextServerToken(token: string) {\n try {\n const cookieStore = await cookies();\n cookieStore.set(\"_tern\", 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\nexport async function VerifyNextTernIdToken(\n token: string\n): Promise<TernVerificationResult> {\n try {\n const decodedToken = await adminAuth.verifyIdToken(token);\n return {\n ...decodedToken,\n valid: true,\n };\n } catch (error) {\n console.error(\"[VerifyNextTernIdToken] Error verifying session:\", error);\n const authError = handleFirebaseAuthError(error);\n return {\n valid: false,\n error: authError,\n };\n }\n}\n\nexport async function VerifyNextTernSessionCookie(\n session: string\n): Promise<TernVerificationResult> {\n try {\n const res = await adminAuth.verifySessionCookie(session);\n console.warn(\n \"[VerifyNextTernSessionCookie] uid in Decoded Token:\",\n res.uid\n );\n return {\n valid: true,\n ...res,\n };\n } catch (error) {\n console.error(\n \"[VerifyNextTernSessionCookie] Error verifying session:\",\n error\n );\n const authError = handleFirebaseAuthError(error);\n return {\n valid: false,\n error: authError,\n };\n }\n}\n\nexport async function ClearNextSessionCookie(tenantId?: string) {\n try {\n console.log(\"[clearSessionCookie] Clearing session for tenant:\", tenantId);\n const tenantAuth = getAuthForTenant(tenantId);\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get(SESSION_CONSTANTS.COOKIE_NAME);\n\n cookieStore.delete(SESSION_CONSTANTS.COOKIE_NAME);\n cookieStore.delete(\"_session_token\");\n cookieStore.delete(\"_session\");\n\n if (\n SESSION_CONSTANTS.REVOKE_REFRESH_TOKENS_ON_SIGNOUT &&\n sessionCookie?.value\n ) {\n try {\n const decodedClaims = await tenantAuth.verifySessionCookie(\n sessionCookie.value\n );\n await tenantAuth.revokeRefreshTokens(decodedClaims.sub);\n console.log(\n `[clearSessionCookie] Successfully revoked tokens for user: ${decodedClaims.sub}`\n );\n } catch (revokeError) {\n console.error(\n \"[ClearNextSessionCookie] Failed to revoke refresh tokens:\",\n revokeError\n );\n }\n }\n return { success: true, message: \"Session cleared successfully\" };\n } catch (error) {\n console.error(\"Error clearing session:\", error);\n return { success: false, message: \"Failed to clear session cookies\" };\n }\n}\n","import { parse } from \"cookie\";\n\nimport { constants } from \"../constants\";\nimport type { TernUrl } from \"./ternUrl\";\nimport { createTernUrl } from \"./ternUrl\";\n\nclass TernSecureRequest extends Request {\n readonly ternUrl: TernUrl;\n readonly cookies: Map<string, string | undefined>;\n\n public constructor(\n input: TernSecureRequest | Request | RequestInfo,\n init?: RequestInit\n ) {\n const url =\n typeof input !== \"string\" && \"url\" in input ? input.url : String(input);\n super(url, init || typeof input === \"string\" ? undefined : input);\n this.ternUrl = this.deriveUrlFromHeaders(this);\n this.cookies = this.parseCookies(this);\n }\n\n public toJSON() {\n return {\n url: this.ternUrl.href,\n method: this.method,\n headers: JSON.stringify(Object.fromEntries(this.headers)),\n ternUrl: this.ternUrl.toString(),\n cookies: JSON.stringify(Object.fromEntries(this.cookies)),\n };\n }\n\n private deriveUrlFromHeaders(req: Request) {\n const initialUrl = new URL(req.url);\n const forwardedProto = req.headers.get(constants.Headers.ForwardedProto);\n const forwardedHost = req.headers.get(constants.Headers.ForwardedHost);\n const host = req.headers.get(constants.Headers.Host);\n const protocol = initialUrl.protocol;\n\n const resolvedHost = this.getFirstValueFromHeader(forwardedHost) ?? host;\n const resolvedProtocol =\n this.getFirstValueFromHeader(forwardedProto) ??\n protocol?.replace(/[:/]/, \"\");\n const origin =\n resolvedHost && resolvedProtocol\n ? `${resolvedProtocol}://${resolvedHost}`\n : initialUrl.origin;\n\n if (origin === initialUrl.origin) {\n return createTernUrl(initialUrl);\n }\n\n return createTernUrl(initialUrl.pathname + initialUrl.search, origin);\n }\n\n private getFirstValueFromHeader(value?: string | null) {\n return value?.split(\",\")[0];\n }\n\n private parseCookies(req: Request) {\n const cookiesRecord = parse(\n this.decodeCookieValue(req.headers.get(\"cookie\") || \"\")\n );\n return new Map(Object.entries(cookiesRecord));\n }\n\n private decodeCookieValue(str: string) {\n return str ? str.replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent) : str;\n }\n}\n\nexport const createTernSecureRequest = (\n ...args: ConstructorParameters<typeof TernSecureRequest>\n): TernSecureRequest => {\n return args[0] instanceof TernSecureRequest\n ? args[0]\n : new TernSecureRequest(...args);\n};\n\nexport type { TernSecureRequest };\n","export const GOOGLE_PUBLIC_KEYS_URL =\n 'https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com';\nexport const SESSION_COOKIE_PUBLIC_KEYS_URL =\n 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys';\nexport const MAX_CACHE_LAST_UPDATED_AT_SECONDS = 5 * 60;\nexport const DEFAULT_CACHE_DURATION = 3600 * 1000; // 1 hour in milliseconds\nexport const CACHE_CONTROL_REGEX = /max-age=(\\d+)/;\n\nconst Attributes = {\n AuthToken: '__ternsecureAuthToken',\n AuthSignature: '__ternsecureAuthSignature',\n AuthStatus: '__ternsecureAuthStatus',\n AuthReason: '__ternsecureAuthReason',\n AuthMessage: '__ternsecureAuthMessage',\n TernSecureUrl: '__ternsecureUrl',\n} as const;\n\nconst Cookies = {\n Session: '__session',\n IdToken: '_tern',\n CsrfToken: '_session_terncf',\n SessionCookie: '_session_cookie',\n SessionToken: '_session_token',\n Refresh: '__refresh',\n Handshake: '__ternsecure_handshake',\n DevBrowser: '__ternsecure_db_jwt',\n RedirectCount: '__ternsecure_redirect_count',\n HandshakeNonce: '__ternsecure_handshake_nonce',\n} as const;\n\nconst Headers = {\n Accept: 'accept',\n AuthMessage: 'x-ternsecure-auth-message',\n Authorization: 'authorization',\n AuthReason: 'x-ternsecure-auth-reason',\n AuthSignature: 'x-ternsecure-auth-signature',\n AuthStatus: 'x-ternsecure-auth-status',\n AuthToken: 'x-ternsecure-auth-token',\n CacheControl: 'cache-control',\n TernSecureRedirectTo: 'x-ternsecure-redirect-to',\n TernSecureRequestData: 'x-ternsecure-request-data',\n TernSecureUrl: 'x-ternsecure-url',\n CloudFrontForwardedProto: 'cloudfront-forwarded-proto',\n ContentType: 'content-type',\n ContentSecurityPolicy: 'content-security-policy',\n ContentSecurityPolicyReportOnly: 'content-security-policy-report-only',\n EnableDebug: 'x-ternsecure-debug',\n ForwardedHost: 'x-forwarded-host',\n ForwardedPort: 'x-forwarded-port',\n ForwardedProto: 'x-forwarded-proto',\n Host: 'host',\n Location: 'location',\n Nonce: 'x-nonce',\n Origin: 'origin',\n Referrer: 'referer',\n SecFetchDest: 'sec-fetch-dest',\n UserAgent: 'user-agent',\n ReportingEndpoints: 'reporting-endpoints',\n} as const;\n\nconst ContentTypes = {\n Json: 'application/json',\n} as const;\n\n/**\n * @internal\n */\nexport const constants = {\n Attributes,\n Cookies,\n Headers,\n ContentTypes,\n} as const;\n\nexport type Constants = typeof constants;\n","class TernUrl extends URL {\n public isCrossOrigin(other: URL | string) {\n return this.origin !== new URL(other.toString()).origin;\n }\n}\n\nexport type WithTernUrl<T> = T & {\n /**\n * When a NextJs app is hosted on a platform different from Vercel\n * or inside a container (Netlify, Fly.io, AWS Amplify, docker etc),\n * req.url is always set to `localhost:3000` instead of the actual host of the app.\n *\n */\n ternUrl: TernUrl;\n};\n\nexport const createTernUrl = (\n ...args: ConstructorParameters<typeof TernUrl>\n): TernUrl => {\n return new TernUrl(...args);\n};\n\nexport type { TernUrl };\n","import type { CheckCustomClaims, DecodedIdToken,SharedSignInAuthObjectProperties } from \"@tern-secure/types\";\n\nimport { VerifyNextTernSessionCookie } from \"../admin/nextSessionTernSecure\";\nimport type { TernSecureRequest} from \"../tokens/ternSecureRequest\";\nimport { createTernSecureRequest } from \"../tokens/ternSecureRequest\";\n\nexport type SignInAuthObject = SharedSignInAuthObjectProperties & {\n has: CheckCustomClaims\n}\n\nexport type SignInState = {\n auth: () => SignInAuthObject\n token: string\n headers: Headers\n}\n\nexport type RequestState = SignInState\n\nexport interface BackendInstance {\n ternSecureRequest: TernSecureRequest;\n requestState: RequestState;\n}\n\nexport const createBackendInstance = async (request: Request): Promise<BackendInstance> => {\n const ternSecureRequest = createTernSecureRequest(request);\n const requestState = await authenticateRequest(request);\n \n return {\n ternSecureRequest,\n requestState,\n };\n};\n\nexport async function authenticateRequest(request: Request): Promise<RequestState> {\n const sessionCookie = request.headers.get('cookie');\n const sessionToken = sessionCookie?.split(';')\n .find(c => c.trim().startsWith('_session_cookie='))\n ?.split('=')[1];\n \n if (!sessionToken) {\n throw new Error(\"No session token found\");\n }\n\n const verificationResult = await VerifyNextTernSessionCookie(sessionToken);\n\n if (!verificationResult.valid) {\n throw new Error(\"Invalid session token\");\n }\n\n return signedIn(\n verificationResult as DecodedIdToken,\n new Headers(request.headers),\n sessionToken\n );\n}\n\nexport function signInAuthObject(\n session: DecodedIdToken,\n): SignInAuthObject {\n return {\n session,\n userId: session.uid,\n has: {} as CheckCustomClaims,\n };\n}\n\nexport function signedIn(\n session: DecodedIdToken,\n headers: Headers = new Headers(),\n token: string\n): SignInState {\n const authObject = signInAuthObject(session);\n return {\n auth: () => authObject,\n token,\n headers,\n };\n}\n"],"mappings":"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","names":["admin","import_errors","SESSION_CONSTANTS","Headers"]}
1
+ {"version":3,"sources":["../../src/admin/index.ts","../../src/admin/sessionTernSecure.ts","../../src/constants.ts","../../src/utils/admin-init.ts","../../src/utils/config.ts","../../src/admin/tenant.ts","../../src/admin/nextSessionTernSecure.ts","../../src/tokens/ternSecureRequest.ts","../../src/tokens/ternUrl.ts","../../src/instance/backendInstance.ts"],"sourcesContent":["export { \n createSessionCookie, \n clearSessionCookie\n} from './sessionTernSecure'\nexport { \n adminTernSecureAuth, \n adminTernSecureDb, \n TernSecureTenantManager \n} from '../utils/admin-init'\nexport { initializeAdminConfig } from '../utils/config'\nexport { createTenant, createTenantUser } from './tenant'\nexport { \n CreateNextSessionCookie,\n GetNextServerSessionCookie,\n GetNextIdToken,\n SetNextServerSession,\n SetNextServerToken,\n VerifyNextTernIdToken,\n VerifyNextTernSessionCookie,\n ClearNextSessionCookie\n} from './nextSessionTernSecure'\n\nexport type { SignInAuthObject, RequestState } from '../instance/backendInstance'\nexport { createBackendInstance, authenticateRequest, signedIn } from '../instance/backendInstance'","'use server';\r\nimport { handleFirebaseAuthError } from '@tern-secure/shared/errors';\r\nimport type {\r\n CookieStore,\r\n SessionParams,\r\n SessionResult,\r\n TernSecureHandlerOptions,\r\n} from '@tern-secure/types';\r\n\r\nimport { constants } from '../constants';\r\nimport { getAuthForTenant } from '../utils/admin-init';\r\n\r\nconst SESSION_CONSTANTS = {\r\n COOKIE_NAME: '_session_cookie',\r\n //DEFAULT_EXPIRES_IN_MS: 60 * 60 * 24 * 5 * 1000, // 5 days\r\n //DEFAULT_EXPIRES_IN_SECONDS: 60 * 60 * 24 * 5, // 5days\r\n DEFAULT_EXPIRES_IN_MS: 5 * 60 * 1000, // 5 minutes\r\n DEFAULT_EXPIRES_IN_SECONDS: 5 * 60,\r\n REVOKE_REFRESH_TOKENS_ON_SIGNOUT: true,\r\n} as const;\r\n\r\nconst COOKIE_OPTIONS = {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict' as const,\r\n path: '/',\r\n} as const;\r\n\r\nexport async function createSessionCookie_old(\r\n params: SessionParams | string,\r\n cookieStore: CookieStore,\r\n options?: TernSecureHandlerOptions,\r\n): Promise<SessionResult> {\r\n try {\r\n const tenantAuth = getAuthForTenant(options?.tenantId || '');\r\n\r\n let decodedToken;\r\n let sessionCookie;\r\n\r\n const idToken = typeof params === 'string' ? params : params.idToken;\r\n\r\n if (!idToken) {\r\n return {\r\n success: false,\r\n message: 'ID token is required',\r\n error: 'INVALID_TOKEN',\r\n };\r\n }\r\n\r\n try {\r\n decodedToken = await tenantAuth.verifyIdToken(idToken);\r\n } catch (verifyError) {\r\n const authError = handleFirebaseAuthError(verifyError);\r\n return {\r\n success: false,\r\n message: authError.message,\r\n error: authError.code,\r\n };\r\n }\r\n\r\n if (!decodedToken) {\r\n return {\r\n success: false,\r\n message: 'Invalid ID token',\r\n error: 'INVALID_TOKEN',\r\n };\r\n }\r\n\r\n try {\r\n sessionCookie = await tenantAuth.createSessionCookie(idToken, {\r\n expiresIn: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_MS,\r\n });\r\n } catch (sessionError) {\r\n console.error('[createSessionCookie] Firebase session cookie creation failed:', sessionError);\r\n const authError = handleFirebaseAuthError(sessionError);\r\n return {\r\n success: false,\r\n message: authError.message,\r\n error: authError.code,\r\n };\r\n }\r\n\r\n try {\r\n await cookieStore.set(constants.Cookies.IdToken, idToken, {\r\n maxAge: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_SECONDS,\r\n ...COOKIE_OPTIONS,\r\n });\r\n await cookieStore.set(SESSION_CONSTANTS.COOKIE_NAME, sessionCookie, {\r\n maxAge: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_SECONDS,\r\n ...COOKIE_OPTIONS,\r\n });\r\n } catch (cookieError) {\r\n console.error('[createSessionCookie] Failed to set session cookie:', cookieError);\r\n return {\r\n success: false,\r\n message: 'Failed to set session cookie',\r\n error: 'COOKIE_SET_FAILED',\r\n };\r\n }\r\n\r\n return {\r\n success: true,\r\n message: 'Session created successfully',\r\n expiresIn: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_SECONDS,\r\n };\r\n } catch (error) {\r\n console.error('[createSessionCookie] Unexpected error:', error);\r\n const authError = handleFirebaseAuthError(error);\r\n return {\r\n success: false,\r\n message: authError.message || 'Failed to create session',\r\n error: authError.code || 'INTERNAL_ERROR',\r\n };\r\n }\r\n}\r\n\r\nexport async function clearSessionCookie_old(\r\n cookieStore: CookieStore,\r\n options?: TernSecureHandlerOptions,\r\n): Promise<SessionResult> {\r\n try {\r\n const adminAuth = getAuthForTenant(options?.tenantId || '');\r\n const sessionCookie = await cookieStore.get(SESSION_CONSTANTS.COOKIE_NAME);\r\n\r\n await cookieStore.delete(SESSION_CONSTANTS.COOKIE_NAME);\r\n await cookieStore.delete(constants.Cookies.IdToken);\r\n await cookieStore.delete(constants.Cookies.Refresh);\r\n await cookieStore.delete(constants.Cookies.Custom);\r\n await cookieStore.delete(constants.Cookies.Session);\r\n\r\n if (SESSION_CONSTANTS.REVOKE_REFRESH_TOKENS_ON_SIGNOUT && sessionCookie?.value) {\r\n try {\r\n const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie.value);\r\n await adminAuth.revokeRefreshTokens(decodedClaims.sub);\r\n } catch (revokeError) {\r\n console.error('[clearSessionCookie] Failed to revoke refresh tokens:', revokeError);\r\n }\r\n }\r\n return {\r\n success: true,\r\n message: 'Session cleared successfully',\r\n };\r\n } catch (error) {\r\n const authError = handleFirebaseAuthError(error);\r\n return {\r\n success: false,\r\n message: authError.message || 'Failed to clear session',\r\n error: authError.code || 'INTERNAL_ERROR',\r\n };\r\n }\r\n}\r\n\r\nexport async function createCustomToken_old(\r\n uid: string,\r\n options?: TernSecureHandlerOptions,\r\n): Promise<string | null> {\r\n const adminAuth = getAuthForTenant(options?.tenantId || '');\r\n try {\r\n const customToken = await adminAuth.createCustomToken(uid);\r\n return customToken;\r\n } catch (error) {\r\n console.error('[createCustomToken] Error creating custom token:', error);\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Generates cookie name with optional prefix\r\n */\r\n\r\nconst DEFAULT_COOKIE_CONFIG = {\r\n DEFAULT_EXPIRES_IN_MS: 5 * 60 * 1000, // 5 minutes\r\n DEFAULT_EXPIRES_IN_SECONDS: 5 * 60,\r\n REVOKE_REFRESH_TOKENS_ON_SIGNOUT: true,\r\n} as const;\r\n\r\nconst DEFAULT_COOKIE_OPTIONS = {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict' as const,\r\n path: '/',\r\n} as const;\r\n\r\n/**\r\n * Generates cookie name with optional prefix\r\n */\r\nconst getCookieName = (baseName: string, prefix?: string): string => {\r\n return prefix ? `${prefix}${baseName}` : baseName;\r\n};\r\n\r\n/**\r\n * Creates standard cookie options with optional overrides\r\n */\r\nconst createCookieOptions = (\r\n maxAge: number,\r\n overrides?: {\r\n httpOnly?: boolean;\r\n secure?: boolean;\r\n sameSite?: 'strict' | 'lax' | 'none';\r\n path?: string;\r\n },\r\n) => {\r\n return {\r\n maxAge,\r\n httpOnly: overrides?.httpOnly ?? DEFAULT_COOKIE_OPTIONS.httpOnly,\r\n secure: overrides?.secure ?? DEFAULT_COOKIE_OPTIONS.secure,\r\n sameSite: overrides?.sameSite ?? DEFAULT_COOKIE_OPTIONS.sameSite,\r\n path: overrides?.path ?? DEFAULT_COOKIE_OPTIONS.path,\r\n };\r\n};\r\n\r\n/**\r\n * Determines the appropriate cookie prefix based on environment and options\r\n */\r\nconst getCookiePrefix = (): string => {\r\n const isProduction = process.env.NODE_ENV === 'production';\r\n return isProduction ? '__HOST-' : '__dev_';\r\n};\r\n\r\n/**\r\n * Creates cookies for user session management\r\n * @param params - Session parameters containing idToken and optional refreshToken\r\n * @param cookieStore - Cookie store interface for managing cookies\r\n * @param options - TernSecure handler options containing cookie configurations\r\n */\r\nexport async function createSessionCookie(\r\n params: SessionParams | string,\r\n cookieStore: CookieStore,\r\n options?: TernSecureHandlerOptions,\r\n): Promise<SessionResult> {\r\n try {\r\n const tenantAuth = getAuthForTenant(options?.tenantId || '');\r\n\r\n const idToken = typeof params === 'string' ? params : params.idToken;\r\n const refreshToken = typeof params === 'string' ? undefined : (params as any).refreshToken;\r\n\r\n if (!idToken) {\r\n return {\r\n success: false,\r\n message: 'ID token is required',\r\n error: 'INVALID_TOKEN',\r\n };\r\n }\r\n\r\n // Verify the ID token\r\n let decodedToken;\r\n try {\r\n decodedToken = await tenantAuth.verifyIdToken(idToken);\r\n } catch (verifyError) {\r\n const authError = handleFirebaseAuthError(verifyError);\r\n return {\r\n success: false,\r\n message: authError.message,\r\n error: authError.code,\r\n };\r\n }\r\n\r\n const cookiePromises: Promise<void>[] = [];\r\n const cookiePrefix = getCookiePrefix();\r\n\r\n // Always set idToken cookie by default\r\n const idTokenCookieName = getCookieName(\r\n constants.Cookies.IdToken,\r\n cookiePrefix,\r\n );\r\n cookiePromises.push(\r\n cookieStore.set(\r\n idTokenCookieName,\r\n idToken,\r\n createCookieOptions(DEFAULT_COOKIE_CONFIG.DEFAULT_EXPIRES_IN_SECONDS),\r\n ),\r\n );\r\n\r\n // Always set refreshToken cookie by default if provided\r\n if (refreshToken) {\r\n const refreshTokenCookieName = getCookieName(\r\n constants.Cookies.Refresh,\r\n cookiePrefix,\r\n );\r\n cookiePromises.push(\r\n cookieStore.set(\r\n refreshTokenCookieName,\r\n refreshToken,\r\n createCookieOptions(DEFAULT_COOKIE_CONFIG.DEFAULT_EXPIRES_IN_SECONDS),\r\n ),\r\n );\r\n }\r\n\r\n // Create and set session cookie only if session config is provided\r\n if (options?.cookies?.session) {\r\n const sessionOptions = options.cookies.session;\r\n const sessionCookieName = getCookieName(constants.Cookies.Session); //removed prefix for test\r\n const expiresIn = sessionOptions.maxAge\r\n ? sessionOptions.maxAge * 1000\r\n : DEFAULT_COOKIE_CONFIG.DEFAULT_EXPIRES_IN_MS;\r\n\r\n try {\r\n const sessionCookie = await tenantAuth.createSessionCookie(idToken, { expiresIn });\r\n cookiePromises.push(\r\n cookieStore.set(\r\n sessionCookieName,\r\n sessionCookie,\r\n createCookieOptions(\r\n sessionOptions.maxAge || DEFAULT_COOKIE_CONFIG.DEFAULT_EXPIRES_IN_SECONDS,\r\n {\r\n httpOnly: sessionOptions.httpOnly,\r\n sameSite: sessionOptions.sameSite,\r\n path: sessionOptions.path,\r\n },\r\n ),\r\n ),\r\n );\r\n } catch (sessionError) {\r\n console.error(\r\n '[createSessionCookie] Firebase session cookie creation failed:',\r\n sessionError,\r\n );\r\n const authError = handleFirebaseAuthError(sessionError);\r\n return {\r\n success: false,\r\n message: authError.message,\r\n error: authError.code,\r\n };\r\n }\r\n }\r\n\r\n // Create and set custom token cookie only if enableCustomToken is true\r\n if (options?.enableCustomToken && decodedToken?.uid) {\r\n const customTokenCookieName = getCookieName(\r\n constants.Cookies.Custom,\r\n cookiePrefix,\r\n );\r\n const customToken = await createCustomToken(decodedToken.uid, options);\r\n if (customToken) {\r\n cookiePromises.push(\r\n cookieStore.set(\r\n customTokenCookieName,\r\n customToken,\r\n createCookieOptions(DEFAULT_COOKIE_CONFIG.DEFAULT_EXPIRES_IN_SECONDS),\r\n ),\r\n );\r\n }\r\n }\r\n\r\n await Promise.all(cookiePromises);\r\n\r\n return {\r\n success: true,\r\n message: 'Session created successfully',\r\n expiresIn: DEFAULT_COOKIE_CONFIG.DEFAULT_EXPIRES_IN_SECONDS,\r\n };\r\n } catch (error) {\r\n console.error('[createSessionCookie] Unexpected error:', error);\r\n const authError = handleFirebaseAuthError(error);\r\n return {\r\n success: false,\r\n message: authError.message || 'Failed to create session',\r\n error: authError.code || 'INTERNAL_ERROR',\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Clears user session cookies\r\n * @param cookieStore - Cookie store interface for managing cookies\r\n * @param options - TernSecure handler options containing cookie configurations\r\n */\r\nexport async function clearSessionCookie(\r\n cookieStore: CookieStore,\r\n options?: TernSecureHandlerOptions,\r\n): Promise<SessionResult> {\r\n try {\r\n const adminAuth = getAuthForTenant(options?.tenantId || '');\r\n const cookiePrefix = getCookiePrefix();\r\n\r\n // Get the session cookie name for revocation purposes\r\n const sessionCookieName = getCookieName(\r\n constants.Cookies.Session,\r\n cookiePrefix,\r\n );\r\n const sessionCookie = await cookieStore.get(sessionCookieName);\r\n\r\n const deletionPromises: Promise<void>[] = [];\r\n\r\n // Delete all cookie types\r\n // Session cookie (only if it was configured)\r\n if (options?.cookies?.session) {\r\n deletionPromises.push(cookieStore.delete(sessionCookieName));\r\n }\r\n\r\n // Always delete default cookies\r\n const idTokenCookieName = getCookieName(\r\n constants.Cookies.IdToken,\r\n cookiePrefix,\r\n );\r\n deletionPromises.push(cookieStore.delete(idTokenCookieName));\r\n\r\n const refreshTokenCookieName = getCookieName(\r\n constants.Cookies.Refresh,\r\n cookiePrefix,\r\n );\r\n deletionPromises.push(cookieStore.delete(refreshTokenCookieName));\r\n\r\n const customTokenCookieName = getCookieName(\r\n constants.Cookies.Custom,\r\n cookiePrefix,\r\n );\r\n deletionPromises.push(cookieStore.delete(customTokenCookieName));\r\n\r\n // Also delete legacy cookie names for backward compatibility\r\n deletionPromises.push(cookieStore.delete(constants.Cookies.Session));\r\n\r\n await Promise.all(deletionPromises);\r\n\r\n // Revoke refresh tokens if session cookie exists and revocation is enabled\r\n if (DEFAULT_COOKIE_CONFIG.REVOKE_REFRESH_TOKENS_ON_SIGNOUT && sessionCookie?.value) {\r\n try {\r\n const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie.value);\r\n await adminAuth.revokeRefreshTokens(decodedClaims.sub);\r\n } catch (revokeError) {\r\n console.error('[clearSessionCookie] Failed to revoke refresh tokens:', revokeError);\r\n }\r\n }\r\n\r\n return {\r\n success: true,\r\n message: 'Session cleared successfully',\r\n };\r\n } catch (error) {\r\n const authError = handleFirebaseAuthError(error);\r\n return {\r\n success: false,\r\n message: authError.message || 'Failed to clear session',\r\n error: authError.code || 'INTERNAL_ERROR',\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Creates a custom token for a user\r\n * @param uid - User ID to create the custom token for\r\n * @param options - TernSecure handler options\r\n * @returns Promise resolving to the custom token string or null if creation fails\r\n */\r\nexport async function createCustomToken(\r\n uid: string,\r\n options?: TernSecureHandlerOptions,\r\n): Promise<string | null> {\r\n const adminAuth = getAuthForTenant(options?.tenantId || '');\r\n try {\r\n const customToken = await adminAuth.createCustomToken(uid);\r\n return customToken;\r\n } catch (error) {\r\n console.error('[createCustomToken] Error creating custom token:', error);\r\n return null;\r\n }\r\n}\r\n","export const GOOGLE_PUBLIC_KEYS_URL =\n 'https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com';\nexport const SESSION_COOKIE_PUBLIC_KEYS_URL =\n 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys';\n\nexport const MAX_CACHE_LAST_UPDATED_AT_SECONDS = 5 * 60;\nexport const DEFAULT_CACHE_DURATION = 3600 * 1000; // 1 hour in milliseconds\nexport const CACHE_CONTROL_REGEX = /max-age=(\\d+)/;\n\nconst Attributes = {\n AuthToken: '__ternsecureAuthToken',\n AuthSignature: '__ternsecureAuthSignature',\n AuthStatus: '__ternsecureAuthStatus',\n AuthReason: '__ternsecureAuthReason',\n AuthMessage: '__ternsecureAuthMessage',\n TernSecureUrl: '__ternsecureUrl',\n} as const;\n\nconst Cookies = {\n Session: '__session',\n CsrfToken: '__session_terncf',\n IdToken: 'FIREBASE_[DEFAULT]',\n Refresh: 'FIREBASEID_[DEFAULT]',\n Custom: '__custom',\n Handshake: '__ternsecure_handshake',\n DevBrowser: '__ternsecure_db_jwt',\n RedirectCount: '__ternsecure_redirect_count',\n HandshakeNonce: '__ternsecure_handshake_nonce',\n} as const;\n\nconst Headers = {\n Accept: 'accept',\n AuthMessage: 'x-ternsecure-auth-message',\n Authorization: 'authorization',\n AuthReason: 'x-ternsecure-auth-reason',\n AuthSignature: 'x-ternsecure-auth-signature',\n AuthStatus: 'x-ternsecure-auth-status',\n AuthToken: 'x-ternsecure-auth-token',\n CacheControl: 'cache-control',\n TernSecureRedirectTo: 'x-ternsecure-redirect-to',\n TernSecureRequestData: 'x-ternsecure-request-data',\n TernSecureUrl: 'x-ternsecure-url',\n CloudFrontForwardedProto: 'cloudfront-forwarded-proto',\n ContentType: 'content-type',\n ContentSecurityPolicy: 'content-security-policy',\n ContentSecurityPolicyReportOnly: 'content-security-policy-report-only',\n EnableDebug: 'x-ternsecure-debug',\n ForwardedHost: 'x-forwarded-host',\n ForwardedPort: 'x-forwarded-port',\n ForwardedProto: 'x-forwarded-proto',\n Host: 'host',\n Location: 'location',\n Nonce: 'x-nonce',\n Origin: 'origin',\n Referrer: 'referer',\n SecFetchDest: 'sec-fetch-dest',\n UserAgent: 'user-agent',\n ReportingEndpoints: 'reporting-endpoints',\n} as const;\n\nconst ContentTypes = {\n Json: 'application/json',\n} as const;\n\n/**\n * @internal\n */\nexport const constants = {\n Attributes,\n Cookies,\n Headers,\n ContentTypes,\n} as const;\n\nexport type Constants = typeof constants;\n","import admin from 'firebase-admin';\r\n\r\nimport { initializeAdminConfig } from './config';\r\n\r\nif (!admin.apps.length) {\r\n try {\r\n const config = initializeAdminConfig();\r\n admin.initializeApp({\r\n credential: admin.credential.cert({\r\n ...config,\r\n privateKey: config.privateKey.replace(/\\\\n/g, '\\n'),\r\n }),\r\n });\r\n } catch (error) {\r\n console.error('Firebase admin initialization error', error);\r\n }\r\n}\r\n\r\nexport const adminTernSecureAuth: admin.auth.Auth = admin.auth();\r\nexport const adminTernSecureDb: admin.firestore.Firestore = admin.firestore();\r\nexport const TernSecureTenantManager: admin.auth.TenantManager = admin.auth().tenantManager();\r\n\r\n/**\r\n * Gets the appropriate Firebase Auth instance.\r\n * If a tenantId is provided, it returns the Auth instance for that tenant.\r\n * Otherwise, it returns the default project-level Auth instance.\r\n * @param tenantId - The optional tenant ID.\r\n * @returns An admin.auth.Auth instance.\r\n */\r\nexport function getAuthForTenant(tenantId?: string): admin.auth.Auth {\r\n if (tenantId) {\r\n return TernSecureTenantManager.authForTenant(tenantId) as unknown as admin.auth.Auth;\r\n }\r\n return admin.auth();\r\n}","import type { \r\n AdminConfigValidationResult, \r\n ConfigValidationResult, \r\n TernSecureAdminConfig, \r\n TernSecureConfig} from '@tern-secure/types'\r\n\r\n/**\r\n * Loads Firebase configuration from environment variables\r\n * @returns {TernSecureConfig} Firebase configuration object\r\n */\r\nexport const loadFireConfig = (): TernSecureConfig => ({\r\n apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY || '',\r\n authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN || '',\r\n projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID || '',\r\n storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET || '',\r\n messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID || '',\r\n appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID || '',\r\n measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID || undefined,\r\n})\r\n\r\n/**\r\n * Validates Firebase configuration\r\n * @param {TernSecureConfig} config - Firebase configuration object\r\n * @throws {Error} If required configuration values are missing\r\n * @returns {TernSecureConfig} Validated configuration object\r\n */\r\nexport const validateConfig = (config: TernSecureConfig): ConfigValidationResult => {\r\n const requiredFields: (keyof TernSecureConfig)[] = [\r\n 'apiKey',\r\n 'authDomain',\r\n 'projectId',\r\n 'storageBucket',\r\n 'messagingSenderId',\r\n 'appId'\r\n ]\r\n\r\n const errors: string[] = []\r\n \r\n requiredFields.forEach(field => {\r\n if (!config[field]) {\r\n errors.push(`Missing required field: NEXT_PUBLIC_FIREBASE_${String(field).toUpperCase()}`)\r\n }\r\n })\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n config\r\n }\r\n}\r\n\r\n/**\r\n * Initializes configuration with validation\r\n * @throws {Error} If configuration is invalid\r\n */\r\nexport const initializeConfig = (): TernSecureConfig => {\r\n const config = loadFireConfig()\r\n const validationResult = validateConfig(config)\r\n\r\n if (!validationResult.isValid) {\r\n throw new Error(\r\n `Firebase configuration validation failed:\\n${validationResult.errors.join('\\n')}`\r\n )\r\n }\r\n\r\n return config\r\n}\r\n\r\n/**\r\n * Loads Firebase Admin configuration from environment variables\r\n * @returns {AdminConfig} Firebase Admin configuration object\r\n */\r\nexport const loadAdminConfig = (): TernSecureAdminConfig => ({\r\n projectId: process.env.FIREBASE_PROJECT_ID || '',\r\n clientEmail: process.env.FIREBASE_CLIENT_EMAIL || '',\r\n privateKey: process.env.FIREBASE_PRIVATE_KEY || '',\r\n})\r\n\r\n/**\r\n * Validates Firebase Admin configuration\r\n * @param {AdminConfig} config - Firebase Admin configuration object\r\n * @returns {ConfigValidationResult} Validation result\r\n */\r\nexport const validateAdminConfig = (config: TernSecureAdminConfig): AdminConfigValidationResult => {\r\n const requiredFields: (keyof TernSecureAdminConfig)[] = [\r\n 'projectId',\r\n 'clientEmail',\r\n 'privateKey'\r\n ]\r\n\r\n const errors: string[] = []\r\n \r\n requiredFields.forEach(field => {\r\n if (!config[field]) {\r\n errors.push(`Missing required field: FIREBASE_${String(field).toUpperCase()}`)\r\n }\r\n })\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n config\r\n }\r\n}\r\n\r\n/**\r\n * Initializes admin configuration with validation\r\n * @throws {Error} If configuration is invalid\r\n */\r\nexport const initializeAdminConfig = (): TernSecureAdminConfig => {\r\n const config = loadAdminConfig()\r\n const validationResult = validateAdminConfig(config)\r\n\r\n if (!validationResult.isValid) {\r\n throw new Error(\r\n `Firebase Admin configuration validation failed:\\n${validationResult.errors.join('\\n')}`\r\n )\r\n }\r\n\r\n return config\r\n}","import type { SignInResponse } from '@tern-secure/types';\r\n\r\nimport { TernSecureTenantManager } from \"../utils/admin-init\";\r\n\r\n\r\nexport async function createTenant(\r\n displayName: string,\r\n emailSignInConfig: {\r\n enabled: boolean;\r\n passwordRequired: boolean;\r\n },\r\n multiFactorConfig?: {\r\n state: 'ENABLED' | 'DISABLED';\r\n factorIds: \"phone\"[];\r\n testPhoneNumbers?: {\r\n [phoneNumber: string]: string;\r\n }\r\n }\r\n) {\r\n try {\r\n const tenantConfig = {\r\n displayName,\r\n emailSignInConfig,\r\n ...(multiFactorConfig && { multiFactorConfig })\r\n };\r\n\r\n const tenant = await TernSecureTenantManager.createTenant(tenantConfig);\r\n \r\n return {\r\n success: true,\r\n tenantId: tenant.tenantId,\r\n displayName: tenant.displayName,\r\n };\r\n } catch (error) {\r\n console.error('Error creating tenant:', error);\r\n throw new Error('Failed to create tenant');\r\n }\r\n}\r\n\r\nexport async function createTenantUser(\r\n email: string,\r\n password: string,\r\n tenantId: string\r\n): Promise<SignInResponse> {\r\n try {\r\n const tenantAuth = TernSecureTenantManager.authForTenant(tenantId);\r\n \r\n const userRecord = await tenantAuth.createUser({\r\n email,\r\n password,\r\n emailVerified: false,\r\n disabled: false\r\n });\r\n\r\n return {\r\n success: true,\r\n message: 'Tenant user created successfully',\r\n user: userRecord.uid,\r\n };\r\n } catch (error) {\r\n console.error('Error creating tenant user:', error);\r\n throw new Error('Failed to create tenant user');\r\n }\r\n}\r\n","\"use server\";\n\nimport { handleFirebaseAuthError } from \"@tern-secure/shared/errors\";\nimport type { TernVerificationResult } from \"@tern-secure/types\";\nimport { cookies } from \"next/headers\";\n\nimport { constants } from '../constants';\nimport { adminTernSecureAuth as adminAuth, getAuthForTenant } from \"../utils/admin-init\";\n\n\nconst SESSION_CONSTANTS = {\n COOKIE_NAME: constants.Cookies.Session,\n DEFAULT_EXPIRES_IN_MS: 60 * 60 * 24 * 5 * 1000, // 5 days\n DEFAULT_EXPIRES_IN_SECONDS: 60 * 60 * 24 * 5,\n REVOKE_REFRESH_TOKENS_ON_SIGNOUT: true,\n} as const;\n\nexport async function CreateNextSessionCookie(idToken: string) {\n try {\n const expiresIn = 60 * 60 * 24 * 5 * 1000;\n const sessionCookie = await adminAuth.createSessionCookie(idToken, {\n expiresIn,\n });\n\n const cookieStore = await cookies();\n cookieStore.set(constants.Cookies.Session, 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\nexport async function GetNextServerSessionCookie() {\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(\n sessionCookie,\n true\n );\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\nexport async function GetNextIdToken() {\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 SetNextServerSession(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\nexport async function SetNextServerToken(token: string) {\n try {\n const cookieStore = await cookies();\n cookieStore.set(\"_tern\", 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\nexport async function VerifyNextTernIdToken(\n token: string\n): Promise<TernVerificationResult> {\n try {\n const decodedToken = await adminAuth.verifyIdToken(token);\n return {\n ...decodedToken,\n valid: true,\n };\n } catch (error) {\n console.error(\"[VerifyNextTernIdToken] Error verifying session:\", error);\n const authError = handleFirebaseAuthError(error);\n return {\n valid: false,\n error: authError,\n };\n }\n}\n\nexport async function VerifyNextTernSessionCookie(\n session: string\n): Promise<TernVerificationResult> {\n try {\n const res = await adminAuth.verifySessionCookie(session);\n console.warn(\n \"[VerifyNextTernSessionCookie] uid in Decoded Token:\",\n res.uid\n );\n return {\n valid: true,\n ...res,\n };\n } catch (error) {\n console.error(\n \"[VerifyNextTernSessionCookie] Error verifying session:\",\n error\n );\n const authError = handleFirebaseAuthError(error);\n return {\n valid: false,\n error: authError,\n };\n }\n}\n\nexport async function ClearNextSessionCookie(tenantId?: string) {\n try {\n console.log(\"[clearSessionCookie] Clearing session for tenant:\", tenantId);\n const tenantAuth = getAuthForTenant(tenantId);\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get(SESSION_CONSTANTS.COOKIE_NAME);\n\n cookieStore.delete(SESSION_CONSTANTS.COOKIE_NAME);\n cookieStore.delete(constants.Cookies.IdToken);\n\n if (\n SESSION_CONSTANTS.REVOKE_REFRESH_TOKENS_ON_SIGNOUT &&\n sessionCookie?.value\n ) {\n try {\n const decodedClaims = await tenantAuth.verifySessionCookie(\n sessionCookie.value\n );\n await tenantAuth.revokeRefreshTokens(decodedClaims.sub);\n console.log(\n `[clearSessionCookie] Successfully revoked tokens for user: ${decodedClaims.sub}`\n );\n } catch (revokeError) {\n console.error(\n \"[ClearNextSessionCookie] Failed to revoke refresh tokens:\",\n revokeError\n );\n }\n }\n return { success: true, message: \"Session cleared successfully\" };\n } catch (error) {\n console.error(\"Error clearing session:\", error);\n return { success: false, message: \"Failed to clear session cookies\" };\n }\n}\n","import { parse } from \"cookie\";\n\nimport { constants } from \"../constants\";\nimport type { TernUrl } from \"./ternUrl\";\nimport { createTernUrl } from \"./ternUrl\";\n\nclass TernSecureRequest extends Request {\n readonly ternUrl: TernUrl;\n readonly cookies: Map<string, string | undefined>;\n\n public constructor(\n input: TernSecureRequest | Request | RequestInfo,\n init?: RequestInit\n ) {\n const url =\n typeof input !== \"string\" && \"url\" in input ? input.url : String(input);\n super(url, init || typeof input === \"string\" ? undefined : input);\n this.ternUrl = this.deriveUrlFromHeaders(this);\n this.cookies = this.parseCookies(this);\n }\n\n public toJSON() {\n return {\n url: this.ternUrl.href,\n method: this.method,\n headers: JSON.stringify(Object.fromEntries(this.headers)),\n ternUrl: this.ternUrl.toString(),\n cookies: JSON.stringify(Object.fromEntries(this.cookies)),\n };\n }\n\n private deriveUrlFromHeaders(req: Request) {\n const initialUrl = new URL(req.url);\n const forwardedProto = req.headers.get(constants.Headers.ForwardedProto);\n const forwardedHost = req.headers.get(constants.Headers.ForwardedHost);\n const host = req.headers.get(constants.Headers.Host);\n const protocol = initialUrl.protocol;\n\n const resolvedHost = this.getFirstValueFromHeader(forwardedHost) ?? host;\n const resolvedProtocol =\n this.getFirstValueFromHeader(forwardedProto) ??\n protocol?.replace(/[:/]/, \"\");\n const origin =\n resolvedHost && resolvedProtocol\n ? `${resolvedProtocol}://${resolvedHost}`\n : initialUrl.origin;\n\n if (origin === initialUrl.origin) {\n return createTernUrl(initialUrl);\n }\n\n return createTernUrl(initialUrl.pathname + initialUrl.search, origin);\n }\n\n private getFirstValueFromHeader(value?: string | null) {\n return value?.split(\",\")[0];\n }\n\n private parseCookies(req: Request) {\n const cookiesRecord = parse(\n this.decodeCookieValue(req.headers.get(\"cookie\") || \"\")\n );\n return new Map(Object.entries(cookiesRecord));\n }\n\n private decodeCookieValue(str: string) {\n return str ? str.replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent) : str;\n }\n}\n\nexport const createTernSecureRequest = (\n ...args: ConstructorParameters<typeof TernSecureRequest>\n): TernSecureRequest => {\n return args[0] instanceof TernSecureRequest\n ? args[0]\n : new TernSecureRequest(...args);\n};\n\nexport type { TernSecureRequest };\n","class TernUrl extends URL {\n public isCrossOrigin(other: URL | string) {\n return this.origin !== new URL(other.toString()).origin;\n }\n}\n\nexport type WithTernUrl<T> = T & {\n /**\n * When a NextJs app is hosted on a platform different from Vercel\n * or inside a container (Netlify, Fly.io, AWS Amplify, docker etc),\n * req.url is always set to `localhost:3000` instead of the actual host of the app.\n *\n */\n ternUrl: TernUrl;\n};\n\nexport const createTernUrl = (\n ...args: ConstructorParameters<typeof TernUrl>\n): TernUrl => {\n return new TernUrl(...args);\n};\n\nexport type { TernUrl };\n","import type { CheckCustomClaims, DecodedIdToken,SharedSignInAuthObjectProperties } from \"@tern-secure/types\";\n\nimport { VerifyNextTernSessionCookie } from \"../admin/nextSessionTernSecure\";\nimport type { TernSecureRequest} from \"../tokens/ternSecureRequest\";\nimport { createTernSecureRequest } from \"../tokens/ternSecureRequest\";\n\nexport type SignInAuthObject = SharedSignInAuthObjectProperties & {\n has: CheckCustomClaims\n}\n\nexport type SignInState = {\n auth: () => SignInAuthObject\n token: string\n headers: Headers\n}\n\nexport type RequestState = SignInState\n\nexport interface BackendInstance {\n ternSecureRequest: TernSecureRequest;\n requestState: RequestState;\n}\n\nexport const createBackendInstance = async (request: Request): Promise<BackendInstance> => {\n const ternSecureRequest = createTernSecureRequest(request);\n const requestState = await authenticateRequest(request);\n \n return {\n ternSecureRequest,\n requestState,\n };\n};\n\nexport async function authenticateRequest(request: Request): Promise<RequestState> {\n const sessionCookie = request.headers.get('cookie');\n const sessionToken = sessionCookie?.split(';')\n .find(c => c.trim().startsWith('_session_cookie='))\n ?.split('=')[1];\n \n if (!sessionToken) {\n throw new Error(\"No session token found\");\n }\n\n const verificationResult = await VerifyNextTernSessionCookie(sessionToken);\n\n if (!verificationResult.valid) {\n throw new Error(\"Invalid session token\");\n }\n\n return signedIn(\n verificationResult as DecodedIdToken,\n new Headers(request.headers),\n sessionToken\n );\n}\n\nexport function signInAuthObject(\n session: DecodedIdToken,\n): SignInAuthObject {\n return {\n session,\n userId: session.uid,\n has: {} as CheckCustomClaims,\n };\n}\n\nexport function signedIn(\n session: DecodedIdToken,\n headers: Headers = new Headers(),\n token: string\n): SignInState {\n const authObject = signInAuthObject(session);\n return {\n auth: () => authObject,\n token,\n headers,\n };\n}\n"],"mappings":"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","names":["Headers","admin","import_errors","SESSION_CONSTANTS"]}
@@ -1,8 +1,7 @@
1
1
  import {
2
- createTernSecureRequest,
3
- getCookieOptions,
4
- getSessionConfig
5
- } from "../chunk-ZIO4EKS5.mjs";
2
+ constants,
3
+ createTernSecureRequest
4
+ } from "../chunk-ZMDLKXUP.mjs";
6
5
 
7
6
  // src/admin/sessionTernSecure.ts
8
7
  import { handleFirebaseAuthError } from "@tern-secure/shared/errors";
@@ -86,108 +85,137 @@ var COOKIE_OPTIONS = {
86
85
  sameSite: "strict",
87
86
  path: "/"
88
87
  };
88
+ var DEFAULT_COOKIE_CONFIG = {
89
+ DEFAULT_EXPIRES_IN_MS: 5 * 60 * 1e3,
90
+ // 5 minutes
91
+ DEFAULT_EXPIRES_IN_SECONDS: 5 * 60,
92
+ REVOKE_REFRESH_TOKENS_ON_SIGNOUT: true
93
+ };
94
+ var DEFAULT_COOKIE_OPTIONS = {
95
+ httpOnly: true,
96
+ secure: process.env.NODE_ENV === "production",
97
+ sameSite: "strict",
98
+ path: "/"
99
+ };
100
+ var getCookieName = (baseName, prefix) => {
101
+ return prefix ? `${prefix}${baseName}` : baseName;
102
+ };
103
+ var createCookieOptions = (maxAge, overrides) => {
104
+ return {
105
+ maxAge,
106
+ httpOnly: overrides?.httpOnly ?? DEFAULT_COOKIE_OPTIONS.httpOnly,
107
+ secure: overrides?.secure ?? DEFAULT_COOKIE_OPTIONS.secure,
108
+ sameSite: overrides?.sameSite ?? DEFAULT_COOKIE_OPTIONS.sameSite,
109
+ path: overrides?.path ?? DEFAULT_COOKIE_OPTIONS.path
110
+ };
111
+ };
112
+ var getCookiePrefix = () => {
113
+ const isProduction = process.env.NODE_ENV === "production";
114
+ return isProduction ? "__HOST-" : "__dev_";
115
+ };
89
116
  async function createSessionCookie(params, cookieStore, options) {
90
117
  try {
91
- const tenantAuth = getAuthForTenant(options?.tenantId);
92
- const sessionConfig = getSessionConfig(options);
93
- const cookieOptions = getCookieOptions(options);
94
- let decodedToken;
95
- let sessionCookie;
118
+ const tenantAuth = getAuthForTenant(options?.tenantId || "");
96
119
  const idToken = typeof params === "string" ? params : params.idToken;
120
+ const refreshToken = typeof params === "string" ? void 0 : params.refreshToken;
97
121
  if (!idToken) {
98
- const error = new Error("ID token is required for session creation");
99
- console.error("[createSessionCookie] Missing ID token:", error);
100
122
  return {
101
123
  success: false,
102
124
  message: "ID token is required",
103
- error: "INVALID_TOKEN",
104
- cookieSet: false
125
+ error: "INVALID_TOKEN"
105
126
  };
106
127
  }
128
+ let decodedToken;
107
129
  try {
108
- console.log("Verifying ID token for tenant:", options?.tenantId);
109
130
  decodedToken = await tenantAuth.verifyIdToken(idToken);
110
131
  } catch (verifyError) {
111
- console.error(
112
- "[createSessionCookie] ID token verification failed:",
113
- verifyError
114
- );
115
132
  const authError = handleFirebaseAuthError(verifyError);
116
133
  return {
117
134
  success: false,
118
135
  message: authError.message,
119
- error: authError.code,
120
- cookieSet: false
136
+ error: authError.code
121
137
  };
122
138
  }
123
- if (!decodedToken) {
124
- const error = new Error("Invalid ID token - verification returned null");
125
- console.error(
126
- "[createSessionCookie] Token verification returned null:",
127
- error
139
+ const cookiePromises = [];
140
+ const cookiePrefix = getCookiePrefix();
141
+ const idTokenCookieName = getCookieName(
142
+ constants.Cookies.IdToken,
143
+ cookiePrefix
144
+ );
145
+ cookiePromises.push(
146
+ cookieStore.set(
147
+ idTokenCookieName,
148
+ idToken,
149
+ createCookieOptions(DEFAULT_COOKIE_CONFIG.DEFAULT_EXPIRES_IN_SECONDS)
150
+ )
151
+ );
152
+ if (refreshToken) {
153
+ const refreshTokenCookieName = getCookieName(
154
+ constants.Cookies.Refresh,
155
+ cookiePrefix
128
156
  );
129
- return {
130
- success: false,
131
- message: "Invalid ID token",
132
- error: "INVALID_TOKEN",
133
- cookieSet: false
134
- };
135
- }
136
- try {
137
- sessionCookie = await tenantAuth.createSessionCookie(idToken, {
138
- expiresIn: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_MS
139
- });
140
- } catch (sessionError) {
141
- console.error(
142
- "[createSessionCookie] Firebase session cookie creation failed:",
143
- sessionError
157
+ cookiePromises.push(
158
+ cookieStore.set(
159
+ refreshTokenCookieName,
160
+ refreshToken,
161
+ createCookieOptions(DEFAULT_COOKIE_CONFIG.DEFAULT_EXPIRES_IN_SECONDS)
162
+ )
144
163
  );
145
- const authError = handleFirebaseAuthError(sessionError);
146
- return {
147
- success: false,
148
- message: authError.message,
149
- error: authError.code,
150
- cookieSet: false
151
- };
152
164
  }
153
- let cookieSetSuccessfully = false;
154
- try {
155
- cookieStore.set(SESSION_CONSTANTS.COOKIE_NAME, sessionCookie, {
156
- maxAge: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_SECONDS,
157
- ...COOKIE_OPTIONS
158
- });
159
- const verifySetCookie = await cookieStore.get(
160
- SESSION_CONSTANTS.COOKIE_NAME
161
- );
162
- cookieSetSuccessfully = !!verifySetCookie?.value;
163
- if (!cookieSetSuccessfully) {
164
- const error = new Error("Session cookie was not set successfully");
165
+ if (options?.cookies?.session) {
166
+ const sessionOptions = options.cookies.session;
167
+ const sessionCookieName = getCookieName(constants.Cookies.Session);
168
+ const expiresIn = sessionOptions.maxAge ? sessionOptions.maxAge * 1e3 : DEFAULT_COOKIE_CONFIG.DEFAULT_EXPIRES_IN_MS;
169
+ try {
170
+ const sessionCookie = await tenantAuth.createSessionCookie(idToken, { expiresIn });
171
+ cookiePromises.push(
172
+ cookieStore.set(
173
+ sessionCookieName,
174
+ sessionCookie,
175
+ createCookieOptions(
176
+ sessionOptions.maxAge || DEFAULT_COOKIE_CONFIG.DEFAULT_EXPIRES_IN_SECONDS,
177
+ {
178
+ httpOnly: sessionOptions.httpOnly,
179
+ sameSite: sessionOptions.sameSite,
180
+ path: sessionOptions.path
181
+ }
182
+ )
183
+ )
184
+ );
185
+ } catch (sessionError) {
165
186
  console.error(
166
- "[createSessionCookie] Cookie verification failed:",
167
- error
187
+ "[createSessionCookie] Firebase session cookie creation failed:",
188
+ sessionError
168
189
  );
169
- throw error;
190
+ const authError = handleFirebaseAuthError(sessionError);
191
+ return {
192
+ success: false,
193
+ message: authError.message,
194
+ error: authError.code
195
+ };
170
196
  }
171
- } catch (cookieError) {
172
- console.error(
173
- "[createSessionCookie] Failed to set session cookie:",
174
- cookieError
197
+ }
198
+ if (options?.enableCustomToken && decodedToken?.uid) {
199
+ const customTokenCookieName = getCookieName(
200
+ constants.Cookies.Custom,
201
+ cookiePrefix
175
202
  );
176
- return {
177
- success: false,
178
- message: "Failed to set session cookie",
179
- error: "COOKIE_SET_FAILED",
180
- cookieSet: false
181
- };
203
+ const customToken = await createCustomToken(decodedToken.uid, options);
204
+ if (customToken) {
205
+ cookiePromises.push(
206
+ cookieStore.set(
207
+ customTokenCookieName,
208
+ customToken,
209
+ createCookieOptions(DEFAULT_COOKIE_CONFIG.DEFAULT_EXPIRES_IN_SECONDS)
210
+ )
211
+ );
212
+ }
182
213
  }
183
- console.log(
184
- `[createSessionCookie] Session cookie created successfully for user: ${decodedToken.uid}`
185
- );
214
+ await Promise.all(cookiePromises);
186
215
  return {
187
216
  success: true,
188
217
  message: "Session created successfully",
189
- expiresIn: SESSION_CONSTANTS.DEFAULT_EXPIRES_IN_SECONDS,
190
- cookieSet: cookieSetSuccessfully
218
+ expiresIn: DEFAULT_COOKIE_CONFIG.DEFAULT_EXPIRES_IN_SECONDS
191
219
  };
192
220
  } catch (error) {
193
221
  console.error("[createSessionCookie] Unexpected error:", error);
@@ -195,51 +223,71 @@ async function createSessionCookie(params, cookieStore, options) {
195
223
  return {
196
224
  success: false,
197
225
  message: authError.message || "Failed to create session",
198
- error: authError.code || "INTERNAL_ERROR",
199
- cookieSet: false
226
+ error: authError.code || "INTERNAL_ERROR"
200
227
  };
201
228
  }
202
229
  }
203
230
  async function clearSessionCookie(cookieStore, options) {
204
231
  try {
205
- const adminAuth = getAuthForTenant(options?.tenantId);
206
- const sessionCookie = await cookieStore.get(SESSION_CONSTANTS.COOKIE_NAME);
207
- await cookieStore.delete(SESSION_CONSTANTS.COOKIE_NAME);
208
- await cookieStore.delete("_session_token");
209
- await cookieStore.delete("_session");
210
- if (SESSION_CONSTANTS.REVOKE_REFRESH_TOKENS_ON_SIGNOUT && sessionCookie?.value) {
232
+ const adminAuth = getAuthForTenant(options?.tenantId || "");
233
+ const cookiePrefix = getCookiePrefix();
234
+ const sessionCookieName = getCookieName(
235
+ constants.Cookies.Session,
236
+ cookiePrefix
237
+ );
238
+ const sessionCookie = await cookieStore.get(sessionCookieName);
239
+ const deletionPromises = [];
240
+ if (options?.cookies?.session) {
241
+ deletionPromises.push(cookieStore.delete(sessionCookieName));
242
+ }
243
+ const idTokenCookieName = getCookieName(
244
+ constants.Cookies.IdToken,
245
+ cookiePrefix
246
+ );
247
+ deletionPromises.push(cookieStore.delete(idTokenCookieName));
248
+ const refreshTokenCookieName = getCookieName(
249
+ constants.Cookies.Refresh,
250
+ cookiePrefix
251
+ );
252
+ deletionPromises.push(cookieStore.delete(refreshTokenCookieName));
253
+ const customTokenCookieName = getCookieName(
254
+ constants.Cookies.Custom,
255
+ cookiePrefix
256
+ );
257
+ deletionPromises.push(cookieStore.delete(customTokenCookieName));
258
+ deletionPromises.push(cookieStore.delete(constants.Cookies.Session));
259
+ await Promise.all(deletionPromises);
260
+ if (DEFAULT_COOKIE_CONFIG.REVOKE_REFRESH_TOKENS_ON_SIGNOUT && sessionCookie?.value) {
211
261
  try {
212
- const decodedClaims = await adminAuth.verifySessionCookie(
213
- sessionCookie.value
214
- );
262
+ const decodedClaims = await adminAuth.verifySessionCookie(sessionCookie.value);
215
263
  await adminAuth.revokeRefreshTokens(decodedClaims.sub);
216
- console.log(
217
- `[clearSessionCookie] Successfully revoked tokens for user: ${decodedClaims.sub}`
218
- );
219
264
  } catch (revokeError) {
220
- console.error(
221
- "[clearSessionCookie] Failed to revoke refresh tokens:",
222
- revokeError
223
- );
265
+ console.error("[clearSessionCookie] Failed to revoke refresh tokens:", revokeError);
224
266
  }
225
267
  }
226
- console.log("[clearSessionCookie] Session cookies cleared successfully");
227
268
  return {
228
269
  success: true,
229
- message: "Session cleared successfully",
230
- cookieSet: false
270
+ message: "Session cleared successfully"
231
271
  };
232
272
  } catch (error) {
233
- console.error("[clearSessionCookie] Unexpected error:", error);
234
273
  const authError = handleFirebaseAuthError(error);
235
274
  return {
236
275
  success: false,
237
276
  message: authError.message || "Failed to clear session",
238
- error: authError.code || "INTERNAL_ERROR",
239
- cookieSet: false
277
+ error: authError.code || "INTERNAL_ERROR"
240
278
  };
241
279
  }
242
280
  }
281
+ async function createCustomToken(uid, options) {
282
+ const adminAuth = getAuthForTenant(options?.tenantId || "");
283
+ try {
284
+ const customToken = await adminAuth.createCustomToken(uid);
285
+ return customToken;
286
+ } catch (error) {
287
+ console.error("[createCustomToken] Error creating custom token:", error);
288
+ return null;
289
+ }
290
+ }
243
291
 
244
292
  // src/admin/tenant.ts
245
293
  async function createTenant(displayName, emailSignInConfig, multiFactorConfig) {
@@ -284,7 +332,7 @@ async function createTenantUser(email, password, tenantId) {
284
332
  import { handleFirebaseAuthError as handleFirebaseAuthError2 } from "@tern-secure/shared/errors";
285
333
  import { cookies } from "next/headers";
286
334
  var SESSION_CONSTANTS2 = {
287
- COOKIE_NAME: "_session_cookie",
335
+ COOKIE_NAME: constants.Cookies.Session,
288
336
  DEFAULT_EXPIRES_IN_MS: 60 * 60 * 24 * 5 * 1e3,
289
337
  // 5 days
290
338
  DEFAULT_EXPIRES_IN_SECONDS: 60 * 60 * 24 * 5,
@@ -297,7 +345,7 @@ async function CreateNextSessionCookie(idToken) {
297
345
  expiresIn
298
346
  });
299
347
  const cookieStore = await cookies();
300
- cookieStore.set("_session_cookie", sessionCookie, {
348
+ cookieStore.set(constants.Cookies.Session, sessionCookie, {
301
349
  maxAge: expiresIn,
302
350
  httpOnly: true,
303
351
  secure: process.env.NODE_ENV === "production",
@@ -423,8 +471,7 @@ async function ClearNextSessionCookie(tenantId) {
423
471
  const cookieStore = await cookies();
424
472
  const sessionCookie = cookieStore.get(SESSION_CONSTANTS2.COOKIE_NAME);
425
473
  cookieStore.delete(SESSION_CONSTANTS2.COOKIE_NAME);
426
- cookieStore.delete("_session_token");
427
- cookieStore.delete("_session");
474
+ cookieStore.delete(constants.Cookies.IdToken);
428
475
  if (SESSION_CONSTANTS2.REVOKE_REFRESH_TOKENS_ON_SIGNOUT && sessionCookie?.value) {
429
476
  try {
430
477
  const decodedClaims = await tenantAuth.verifySessionCookie(