@tern-secure/backend 1.2.0-canary.v20251030165007 → 1.2.0-canary.v20251108045933
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/request.test.d.ts +2 -0
- package/dist/__tests__/request.test.d.ts.map +1 -0
- package/dist/admin/index.js +31 -8
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/index.mjs +17 -8
- package/dist/admin/index.mjs.map +1 -1
- package/dist/admin/nextSessionTernSecure.d.ts.map +1 -1
- package/dist/admin/sessionTernSecure.d.ts.map +1 -1
- package/dist/auth/getauth.d.ts +1 -0
- package/dist/auth/getauth.d.ts.map +1 -1
- package/dist/auth/index.js +49 -31
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/index.mjs +3 -3
- package/dist/{chunk-IBABNFOK.mjs → chunk-ASGV4MFO.mjs} +2 -2
- package/dist/{chunk-5AP2WM3W.mjs → chunk-DDUNOEIM.mjs} +20 -31
- package/dist/chunk-DDUNOEIM.mjs.map +1 -0
- package/dist/{chunk-VY5FVZL2.mjs → chunk-DFAJCSBJ.mjs} +17 -3
- package/dist/chunk-DFAJCSBJ.mjs.map +1 -0
- package/dist/{chunk-A5G3CWO5.mjs → chunk-MS6L7M3C.mjs} +9 -4
- package/dist/chunk-MS6L7M3C.mjs.map +1 -0
- package/dist/constants.d.ts +13 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/index.js +156 -39
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +121 -11
- package/dist/index.mjs.map +1 -1
- package/dist/jwt/index.js +19 -30
- package/dist/jwt/index.js.map +1 -1
- package/dist/jwt/index.mjs +1 -1
- package/dist/jwt/verifyJwt.d.ts.map +1 -1
- package/dist/tokens/authstate.d.ts +16 -4
- package/dist/tokens/authstate.d.ts.map +1 -1
- package/dist/tokens/c-authenticateRequestProcessor.d.ts +5 -0
- package/dist/tokens/c-authenticateRequestProcessor.d.ts.map +1 -1
- package/dist/tokens/request.d.ts.map +1 -1
- package/dist/tokens/types.d.ts +4 -0
- package/dist/tokens/types.d.ts.map +1 -1
- package/package.json +9 -7
- package/dist/chunk-5AP2WM3W.mjs.map +0 -1
- package/dist/chunk-A5G3CWO5.mjs.map +0 -1
- package/dist/chunk-VY5FVZL2.mjs.map +0 -1
- /package/dist/{chunk-IBABNFOK.mjs.map → chunk-ASGV4MFO.mjs.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/request.test.ts"],"names":[],"mappings":""}
|
package/dist/admin/index.js
CHANGED
|
@@ -69,15 +69,28 @@ var Attributes = {
|
|
|
69
69
|
};
|
|
70
70
|
var Cookies = {
|
|
71
71
|
Session: "__session",
|
|
72
|
-
CsrfToken: "
|
|
72
|
+
CsrfToken: "__terncf",
|
|
73
73
|
IdToken: "TernSecure_[DEFAULT]",
|
|
74
74
|
Refresh: "TernSecureID_[DEFAULT]",
|
|
75
75
|
Custom: "__custom",
|
|
76
|
+
TernAut: "tern_aut",
|
|
76
77
|
Handshake: "__ternsecure_handshake",
|
|
77
78
|
DevBrowser: "__ternsecure_db_jwt",
|
|
78
79
|
RedirectCount: "__ternsecure_redirect_count",
|
|
79
80
|
HandshakeNonce: "__ternsecure_handshake_nonce"
|
|
80
81
|
};
|
|
82
|
+
var QueryParameters = {
|
|
83
|
+
TernSynced: "__tern_synced",
|
|
84
|
+
SuffixedCookies: "suffixed_cookies",
|
|
85
|
+
TernRedirectUrl: "__tern_redirect_url",
|
|
86
|
+
// use the reference to Cookies to indicate that it's the same value
|
|
87
|
+
DevBrowser: Cookies.DevBrowser,
|
|
88
|
+
Handshake: Cookies.Handshake,
|
|
89
|
+
HandshakeHelp: "__tern_help",
|
|
90
|
+
LegacyDevBrowser: "__dev_session",
|
|
91
|
+
HandshakeReason: "__tern_hs_reason",
|
|
92
|
+
HandshakeNonce: Cookies.HandshakeNonce
|
|
93
|
+
};
|
|
81
94
|
var Headers2 = {
|
|
82
95
|
Accept: "accept",
|
|
83
96
|
AuthMessage: "x-ternsecure-auth-message",
|
|
@@ -114,7 +127,8 @@ var constants = {
|
|
|
114
127
|
Attributes,
|
|
115
128
|
Cookies,
|
|
116
129
|
Headers: Headers2,
|
|
117
|
-
ContentTypes
|
|
130
|
+
ContentTypes,
|
|
131
|
+
QueryParameters
|
|
118
132
|
};
|
|
119
133
|
|
|
120
134
|
// src/utils/admin-init.ts
|
|
@@ -252,8 +266,8 @@ async function createSessionCookie(params, cookieStore, options) {
|
|
|
252
266
|
)
|
|
253
267
|
);
|
|
254
268
|
}
|
|
255
|
-
if (options?.cookies
|
|
256
|
-
const sessionOptions = options.cookies
|
|
269
|
+
if (options?.cookies) {
|
|
270
|
+
const sessionOptions = options.cookies;
|
|
257
271
|
const sessionCookieName = getCookieName(constants.Cookies.Session);
|
|
258
272
|
const expiresIn = sessionOptions.maxAge ? sessionOptions.maxAge * 1e3 : DEFAULT_COOKIE_CONFIG.DEFAULT_EXPIRES_IN_MS;
|
|
259
273
|
try {
|
|
@@ -321,7 +335,7 @@ async function clearSessionCookie(cookieStore, options) {
|
|
|
321
335
|
const sessionCookieName = getCookieName(constants.Cookies.Session, cookiePrefix);
|
|
322
336
|
const sessionCookie = await cookieStore.get(sessionCookieName);
|
|
323
337
|
const deletionPromises = [];
|
|
324
|
-
if (options?.cookies
|
|
338
|
+
if (options?.cookies) {
|
|
325
339
|
deletionPromises.push(cookieStore.delete(sessionCookieName));
|
|
326
340
|
}
|
|
327
341
|
const idTokenCookieName = getCookieName(constants.Cookies.IdToken, cookiePrefix);
|
|
@@ -330,6 +344,8 @@ async function clearSessionCookie(cookieStore, options) {
|
|
|
330
344
|
deletionPromises.push(cookieStore.delete(refreshTokenCookieName));
|
|
331
345
|
const customTokenCookieName = getCookieName(constants.Cookies.Custom, cookiePrefix);
|
|
332
346
|
deletionPromises.push(cookieStore.delete(customTokenCookieName));
|
|
347
|
+
const authTimeCookieName = constants.Cookies.TernAut;
|
|
348
|
+
deletionPromises.push(cookieStore.delete(authTimeCookieName));
|
|
333
349
|
deletionPromises.push(cookieStore.delete(constants.Cookies.Session));
|
|
334
350
|
await Promise.all(deletionPromises);
|
|
335
351
|
if (DEFAULT_COOKIE_CONFIG.REVOKE_REFRESH_TOKENS_ON_SIGNOUT && sessionCookie?.value) {
|
|
@@ -571,13 +587,20 @@ async function ClearNextSessionCookie(tenantId, deleteOptions) {
|
|
|
571
587
|
secure: deleteOptions?.secure,
|
|
572
588
|
sameSite: deleteOptions?.sameSite
|
|
573
589
|
};
|
|
590
|
+
const idRefreshCustomTokenDeleteOptions = {
|
|
591
|
+
path: "/",
|
|
592
|
+
httpOnly: true,
|
|
593
|
+
secure: process.env.NODE_ENV === "production",
|
|
594
|
+
sameSite: "strict"
|
|
595
|
+
};
|
|
574
596
|
cookieStore.delete({ name: SESSION_CONSTANTS.COOKIE_NAME, ...finalDeleteOptions });
|
|
575
|
-
cookieStore.delete({ name:
|
|
597
|
+
cookieStore.delete({ name: constants.Cookies.TernAut });
|
|
598
|
+
cookieStore.delete({ name: idTokenCookieName, ...idRefreshCustomTokenDeleteOptions });
|
|
576
599
|
cookieStore.delete({
|
|
577
600
|
name: (0, import_cookie.getCookieName)(constants.Cookies.Refresh, cookiePrefix),
|
|
578
|
-
...
|
|
601
|
+
...idRefreshCustomTokenDeleteOptions
|
|
579
602
|
});
|
|
580
|
-
cookieStore.delete({ name: constants.Cookies.Custom, ...
|
|
603
|
+
cookieStore.delete({ name: constants.Cookies.Custom, ...idRefreshCustomTokenDeleteOptions });
|
|
581
604
|
const shouldRevokeTokens = deleteOptions?.revokeRefreshTokensOnSignOut ?? SESSION_CONSTANTS.REVOKE_REFRESH_TOKENS_ON_SIGNOUT;
|
|
582
605
|
if (shouldRevokeTokens) {
|
|
583
606
|
try {
|
package/dist/admin/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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 createCustomTokenClaims,\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\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(constants.Cookies.IdToken, cookiePrefix);\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(constants.Cookies.Refresh, cookiePrefix);\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);\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(constants.Cookies.Custom, cookiePrefix);\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(constants.Cookies.Session, cookiePrefix);\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(constants.Cookies.IdToken, cookiePrefix);\r\n deletionPromises.push(cookieStore.delete(idTokenCookieName));\r\n\r\n const refreshTokenCookieName = getCookieName(constants.Cookies.Refresh, cookiePrefix);\r\n deletionPromises.push(cookieStore.delete(refreshTokenCookieName));\r\n\r\n const customTokenCookieName = getCookieName(constants.Cookies.Custom, cookiePrefix);\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\r\n\r\nexport async function createCustomTokenClaims(\r\n uid: string,\r\n developerClaims?: { [key: string]: unknown },\r\n): Promise<string> {\r\n const adminAuth = getAuthForTenant();\r\n try {\r\n const customToken = await adminAuth.createCustomToken(uid, developerClaims);\r\n return customToken;\r\n } catch (error) {\r\n console.error('[createCustomToken] Error creating custom token:', error);\r\n return '';\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: 'TernSecure_[DEFAULT]',\n Refresh: 'TernSecureID_[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 status: 'success',\r\n user: userRecord,\r\n message: 'Tenant user created successfully',\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 { getCookieName, getCookiePrefix } from '@tern-secure/shared/cookie';\nimport { handleFirebaseAuthError } from '@tern-secure/shared/errors';\nimport type { CookieStore, SessionResult, 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\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\n/**\n * Helper function to log debug messages only in development environment\n */\nconst debugLog = {\n log: (...args: unknown[]) => {\n if (process.env.NODE_ENV === 'development') {\n console.log(...args);\n }\n },\n warn: (...args: unknown[]) => {\n if (process.env.NODE_ENV === 'development') {\n console.warn(...args);\n }\n },\n error: (...args: unknown[]) => {\n console.error(...args);\n },\n};\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(sessionCookie, true);\n return {\n token: sessionCookie,\n userId: decondeClaims.uid,\n };\n } catch (error) {\n console.error('Error verifying session:', error);\n throw new Error('Invalid Session');\n }\n}\n\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(token: string): 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('[VerifyNextTernSessionCookie] uid in Decoded Token:', res.uid);\n return {\n valid: true,\n ...res,\n };\n } catch (error) {\n console.error('[VerifyNextTernSessionCookie] Error verifying session:', error);\n const authError = handleFirebaseAuthError(error);\n return {\n valid: false,\n error: authError,\n };\n }\n}\n\nexport async function ClearNextSessionCookie(\n tenantId?: string,\n deleteOptions?: {\n path?: string;\n domain?: string;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: 'lax' | 'strict' | 'none';\n revokeRefreshTokensOnSignOut?: boolean;\n },\n): Promise<SessionResult> {\n try {\n const tenantAuth = getAuthForTenant(tenantId || '');\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get(SESSION_CONSTANTS.COOKIE_NAME);\n const cookiePrefix = getCookiePrefix();\n const idTokenCookieName = getCookieName(constants.Cookies.IdToken, cookiePrefix);\n const idTokenCookie = cookieStore.get(idTokenCookieName);\n\n const finalDeleteOptions = {\n path: deleteOptions?.path,\n domain: deleteOptions?.domain,\n httpOnly: deleteOptions?.httpOnly,\n secure: deleteOptions?.secure,\n sameSite: deleteOptions?.sameSite,\n };\n\n cookieStore.delete({ name: SESSION_CONSTANTS.COOKIE_NAME, ...finalDeleteOptions });\n cookieStore.delete({ name: idTokenCookieName, ...finalDeleteOptions });\n cookieStore.delete({\n name: getCookieName(constants.Cookies.Refresh, cookiePrefix),\n ...finalDeleteOptions,\n });\n cookieStore.delete({ name: constants.Cookies.Custom, ...finalDeleteOptions });\n\n const shouldRevokeTokens =\n deleteOptions?.revokeRefreshTokensOnSignOut ??\n SESSION_CONSTANTS.REVOKE_REFRESH_TOKENS_ON_SIGNOUT;\n\n if (shouldRevokeTokens) {\n try {\n let userSub: string | undefined;\n\n // Try to get user sub from session cookie first\n if (sessionCookie?.value) {\n try {\n const decodedClaims = await tenantAuth.verifySessionCookie(sessionCookie.value);\n userSub = decodedClaims.sub;\n } catch (sessionError) {\n debugLog.warn(\n '[ClearNextSessionCookie] Session cookie verification failed:',\n sessionError,\n );\n }\n }\n\n // If no session cookie, try idToken cookie\n if (!userSub) {\n if (idTokenCookie?.value) {\n try {\n const decodedIdToken = await tenantAuth.verifyIdToken(idTokenCookie.value);\n userSub = decodedIdToken.sub;\n } catch (idTokenError) {\n debugLog.warn('[ClearNextSessionCookie] ID token verification failed:', idTokenError);\n }\n }\n }\n\n // Revoke tokens if we got a user sub\n if (userSub) {\n await tenantAuth.revokeRefreshTokens(userSub);\n debugLog.log(`[ClearNextSessionCookie] Successfully revoked tokens for user: ${userSub}`);\n } else {\n debugLog.warn('[ClearNextSessionCookie] No valid token found for revocation');\n }\n } catch (revokeError) {\n debugLog.error('[ClearNextSessionCookie] Failed to revoke refresh tokens:', revokeError);\n }\n }\n return { success: true, message: 'Session cleared successfully' };\n } catch (error) {\n debugLog.error('Error clearing session:', error);\n return { success: false, message: 'Failed to clear session cookies' };\n }\n}\n\nexport async function ClearNextSessionCookie_old(cookieStore: CookieStore): Promise<SessionResult> {\n try {\n const cookiePrefix = getCookiePrefix();\n\n const deletionPromises: Promise<void>[] = [];\n\n // Always delete default cookies\n const idTokenCookieName = getCookieName(constants.Cookies.IdToken, cookiePrefix);\n deletionPromises.push(cookieStore.delete(idTokenCookieName));\n\n const refreshTokenCookieName = getCookieName(constants.Cookies.Refresh, cookiePrefix);\n deletionPromises.push(cookieStore.delete(refreshTokenCookieName));\n\n const customTokenCookieName = getCookieName(constants.Cookies.Custom, cookiePrefix);\n deletionPromises.push(cookieStore.delete(customTokenCookieName));\n\n // Also delete legacy cookie names for backward compatibility\n deletionPromises.push(cookieStore.delete(constants.Cookies.Session));\n\n await Promise.all(deletionPromises);\n\n return {\n success: true,\n message: 'Session cleared successfully',\n };\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n return {\n success: false,\n message: authError.message || 'Failed to clear session',\n error: authError.code || 'INTERNAL_ERROR',\n };\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","import_cookie"]}
|
|
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 createCustomTokenClaims,\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\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(constants.Cookies.IdToken, cookiePrefix);\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(constants.Cookies.Refresh, cookiePrefix);\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) {\r\n const sessionOptions = options.cookies;\r\n const sessionCookieName = getCookieName(constants.Cookies.Session);\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(constants.Cookies.Custom, cookiePrefix);\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(constants.Cookies.Session, cookiePrefix);\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) {\r\n deletionPromises.push(cookieStore.delete(sessionCookieName));\r\n }\r\n\r\n // Always delete default cookies\r\n const idTokenCookieName = getCookieName(constants.Cookies.IdToken, cookiePrefix);\r\n deletionPromises.push(cookieStore.delete(idTokenCookieName));\r\n\r\n const refreshTokenCookieName = getCookieName(constants.Cookies.Refresh, cookiePrefix);\r\n deletionPromises.push(cookieStore.delete(refreshTokenCookieName));\r\n\r\n const customTokenCookieName = getCookieName(constants.Cookies.Custom, cookiePrefix);\r\n deletionPromises.push(cookieStore.delete(customTokenCookieName));\r\n\r\n // Delete auth_time cookie\r\n const authTimeCookieName = constants.Cookies.TernAut;\r\n deletionPromises.push(cookieStore.delete(authTimeCookieName));\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\r\n\r\nexport async function createCustomTokenClaims(\r\n uid: string,\r\n developerClaims?: { [key: string]: unknown },\r\n): Promise<string> {\r\n const adminAuth = getAuthForTenant();\r\n try {\r\n const customToken = await adminAuth.createCustomToken(uid, developerClaims);\r\n return customToken;\r\n } catch (error) {\r\n console.error('[createCustomToken] Error creating custom token:', error);\r\n return '';\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: '__terncf',\n IdToken: 'TernSecure_[DEFAULT]',\n Refresh: 'TernSecureID_[DEFAULT]',\n Custom: '__custom',\n TernAut: 'tern_aut',\n Handshake: '__ternsecure_handshake',\n DevBrowser: '__ternsecure_db_jwt',\n RedirectCount: '__ternsecure_redirect_count',\n HandshakeNonce: '__ternsecure_handshake_nonce',\n} as const;\n\n\nconst QueryParameters = {\n TernSynced: '__tern_synced',\n SuffixedCookies: 'suffixed_cookies',\n TernRedirectUrl: '__tern_redirect_url',\n // use the reference to Cookies to indicate that it's the same value\n DevBrowser: Cookies.DevBrowser,\n Handshake: Cookies.Handshake,\n HandshakeHelp: '__tern_help',\n LegacyDevBrowser: '__dev_session',\n HandshakeReason: '__tern_hs_reason',\n HandshakeNonce: Cookies.HandshakeNonce,\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 QueryParameters,\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 status: 'success',\r\n user: userRecord,\r\n message: 'Tenant user created successfully',\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 { getCookieName, getCookiePrefix } from '@tern-secure/shared/cookie';\nimport { handleFirebaseAuthError } from '@tern-secure/shared/errors';\nimport type { CookieStore, SessionResult, 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\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\n/**\n * Helper function to log debug messages only in development environment\n */\nconst debugLog = {\n log: (...args: unknown[]) => {\n if (process.env.NODE_ENV === 'development') {\n console.log(...args);\n }\n },\n warn: (...args: unknown[]) => {\n if (process.env.NODE_ENV === 'development') {\n console.warn(...args);\n }\n },\n error: (...args: unknown[]) => {\n console.error(...args);\n },\n};\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(sessionCookie, true);\n return {\n token: sessionCookie,\n userId: decondeClaims.uid,\n };\n } catch (error) {\n console.error('Error verifying session:', error);\n throw new Error('Invalid Session');\n }\n}\n\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(token: string): 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('[VerifyNextTernSessionCookie] uid in Decoded Token:', res.uid);\n return {\n valid: true,\n ...res,\n };\n } catch (error) {\n console.error('[VerifyNextTernSessionCookie] Error verifying session:', error);\n const authError = handleFirebaseAuthError(error);\n return {\n valid: false,\n error: authError,\n };\n }\n}\n\nexport async function ClearNextSessionCookie(\n tenantId?: string,\n deleteOptions?: {\n path?: string;\n domain?: string;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: 'lax' | 'strict' | 'none';\n revokeRefreshTokensOnSignOut?: boolean;\n },\n): Promise<SessionResult> {\n try {\n const tenantAuth = getAuthForTenant(tenantId || '');\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get(SESSION_CONSTANTS.COOKIE_NAME);\n const cookiePrefix = getCookiePrefix();\n const idTokenCookieName = getCookieName(constants.Cookies.IdToken, cookiePrefix);\n const idTokenCookie = cookieStore.get(idTokenCookieName);\n\n const finalDeleteOptions = {\n path: deleteOptions?.path,\n domain: deleteOptions?.domain,\n httpOnly: deleteOptions?.httpOnly,\n secure: deleteOptions?.secure,\n sameSite: deleteOptions?.sameSite,\n };\n\n const idRefreshCustomTokenDeleteOptions = {\n path: '/',\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'strict' as const,\n };\n\n cookieStore.delete({ name: SESSION_CONSTANTS.COOKIE_NAME, ...finalDeleteOptions });\n cookieStore.delete({ name: constants.Cookies.TernAut });\n \n cookieStore.delete({ name: idTokenCookieName, ...idRefreshCustomTokenDeleteOptions });\n cookieStore.delete({\n name: getCookieName(constants.Cookies.Refresh, cookiePrefix),\n ...idRefreshCustomTokenDeleteOptions,\n });\n cookieStore.delete({ name: constants.Cookies.Custom, ...idRefreshCustomTokenDeleteOptions });\n\n const shouldRevokeTokens =\n deleteOptions?.revokeRefreshTokensOnSignOut ??\n SESSION_CONSTANTS.REVOKE_REFRESH_TOKENS_ON_SIGNOUT;\n\n if (shouldRevokeTokens) {\n try {\n let userSub: string | undefined;\n\n // Try to get user sub from session cookie first\n if (sessionCookie?.value) {\n try {\n const decodedClaims = await tenantAuth.verifySessionCookie(sessionCookie.value);\n userSub = decodedClaims.sub;\n } catch (sessionError) {\n debugLog.warn(\n '[ClearNextSessionCookie] Session cookie verification failed:',\n sessionError,\n );\n }\n }\n\n // If no session cookie, try idToken cookie\n if (!userSub) {\n if (idTokenCookie?.value) {\n try {\n const decodedIdToken = await tenantAuth.verifyIdToken(idTokenCookie.value);\n userSub = decodedIdToken.sub;\n } catch (idTokenError) {\n debugLog.warn('[ClearNextSessionCookie] ID token verification failed:', idTokenError);\n }\n }\n }\n\n // Revoke tokens if we got a user sub\n if (userSub) {\n await tenantAuth.revokeRefreshTokens(userSub);\n debugLog.log(`[ClearNextSessionCookie] Successfully revoked tokens for user: ${userSub}`);\n } else {\n debugLog.warn('[ClearNextSessionCookie] No valid token found for revocation');\n }\n } catch (revokeError) {\n debugLog.error('[ClearNextSessionCookie] Failed to revoke refresh tokens:', revokeError);\n }\n }\n return { success: true, message: 'Session cleared successfully' };\n } catch (error) {\n debugLog.error('Error clearing session:', error);\n return { success: false, message: 'Failed to clear session cookies' };\n }\n}\n\nexport async function ClearNextSessionCookie_old(cookieStore: CookieStore): Promise<SessionResult> {\n try {\n const cookiePrefix = getCookiePrefix();\n\n const deletionPromises: Promise<void>[] = [];\n\n // Always delete default cookies\n const idTokenCookieName = getCookieName(constants.Cookies.IdToken, cookiePrefix);\n deletionPromises.push(cookieStore.delete(idTokenCookieName));\n\n const refreshTokenCookieName = getCookieName(constants.Cookies.Refresh, cookiePrefix);\n deletionPromises.push(cookieStore.delete(refreshTokenCookieName));\n\n const customTokenCookieName = getCookieName(constants.Cookies.Custom, cookiePrefix);\n deletionPromises.push(cookieStore.delete(customTokenCookieName));\n\n // Also delete legacy cookie names for backward compatibility\n deletionPromises.push(cookieStore.delete(constants.Cookies.Session));\n\n await Promise.all(deletionPromises);\n\n return {\n success: true,\n message: 'Session cleared successfully',\n };\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n return {\n success: false,\n message: authError.message || 'Failed to clear session',\n error: authError.code || 'INTERNAL_ERROR',\n };\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","import_cookie"]}
|
package/dist/admin/index.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createTernSecureRequest
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-ASGV4MFO.mjs";
|
|
4
4
|
import {
|
|
5
5
|
constants
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-DFAJCSBJ.mjs";
|
|
7
7
|
|
|
8
8
|
// src/admin/sessionTernSecure.ts
|
|
9
9
|
import { handleFirebaseAuthError } from "@tern-secure/shared/errors";
|
|
@@ -143,8 +143,8 @@ async function createSessionCookie(params, cookieStore, options) {
|
|
|
143
143
|
)
|
|
144
144
|
);
|
|
145
145
|
}
|
|
146
|
-
if (options?.cookies
|
|
147
|
-
const sessionOptions = options.cookies
|
|
146
|
+
if (options?.cookies) {
|
|
147
|
+
const sessionOptions = options.cookies;
|
|
148
148
|
const sessionCookieName = getCookieName(constants.Cookies.Session);
|
|
149
149
|
const expiresIn = sessionOptions.maxAge ? sessionOptions.maxAge * 1e3 : DEFAULT_COOKIE_CONFIG.DEFAULT_EXPIRES_IN_MS;
|
|
150
150
|
try {
|
|
@@ -212,7 +212,7 @@ async function clearSessionCookie(cookieStore, options) {
|
|
|
212
212
|
const sessionCookieName = getCookieName(constants.Cookies.Session, cookiePrefix);
|
|
213
213
|
const sessionCookie = await cookieStore.get(sessionCookieName);
|
|
214
214
|
const deletionPromises = [];
|
|
215
|
-
if (options?.cookies
|
|
215
|
+
if (options?.cookies) {
|
|
216
216
|
deletionPromises.push(cookieStore.delete(sessionCookieName));
|
|
217
217
|
}
|
|
218
218
|
const idTokenCookieName = getCookieName(constants.Cookies.IdToken, cookiePrefix);
|
|
@@ -221,6 +221,8 @@ async function clearSessionCookie(cookieStore, options) {
|
|
|
221
221
|
deletionPromises.push(cookieStore.delete(refreshTokenCookieName));
|
|
222
222
|
const customTokenCookieName = getCookieName(constants.Cookies.Custom, cookiePrefix);
|
|
223
223
|
deletionPromises.push(cookieStore.delete(customTokenCookieName));
|
|
224
|
+
const authTimeCookieName = constants.Cookies.TernAut;
|
|
225
|
+
deletionPromises.push(cookieStore.delete(authTimeCookieName));
|
|
224
226
|
deletionPromises.push(cookieStore.delete(constants.Cookies.Session));
|
|
225
227
|
await Promise.all(deletionPromises);
|
|
226
228
|
if (DEFAULT_COOKIE_CONFIG.REVOKE_REFRESH_TOKENS_ON_SIGNOUT && sessionCookie?.value) {
|
|
@@ -462,13 +464,20 @@ async function ClearNextSessionCookie(tenantId, deleteOptions) {
|
|
|
462
464
|
secure: deleteOptions?.secure,
|
|
463
465
|
sameSite: deleteOptions?.sameSite
|
|
464
466
|
};
|
|
467
|
+
const idRefreshCustomTokenDeleteOptions = {
|
|
468
|
+
path: "/",
|
|
469
|
+
httpOnly: true,
|
|
470
|
+
secure: process.env.NODE_ENV === "production",
|
|
471
|
+
sameSite: "strict"
|
|
472
|
+
};
|
|
465
473
|
cookieStore.delete({ name: SESSION_CONSTANTS.COOKIE_NAME, ...finalDeleteOptions });
|
|
466
|
-
cookieStore.delete({ name:
|
|
474
|
+
cookieStore.delete({ name: constants.Cookies.TernAut });
|
|
475
|
+
cookieStore.delete({ name: idTokenCookieName, ...idRefreshCustomTokenDeleteOptions });
|
|
467
476
|
cookieStore.delete({
|
|
468
477
|
name: getCookieName2(constants.Cookies.Refresh, cookiePrefix),
|
|
469
|
-
...
|
|
478
|
+
...idRefreshCustomTokenDeleteOptions
|
|
470
479
|
});
|
|
471
|
-
cookieStore.delete({ name: constants.Cookies.Custom, ...
|
|
480
|
+
cookieStore.delete({ name: constants.Cookies.Custom, ...idRefreshCustomTokenDeleteOptions });
|
|
472
481
|
const shouldRevokeTokens = deleteOptions?.revokeRefreshTokensOnSignOut ?? SESSION_CONSTANTS.REVOKE_REFRESH_TOKENS_ON_SIGNOUT;
|
|
473
482
|
if (shouldRevokeTokens) {
|
|
474
483
|
try {
|
package/dist/admin/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/admin/sessionTernSecure.ts","../../src/utils/admin-init.ts","../../src/utils/config.ts","../../src/admin/tenant.ts","../../src/admin/nextSessionTernSecure.ts","../../src/instance/backendInstance.ts"],"sourcesContent":["'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\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(constants.Cookies.IdToken, cookiePrefix);\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(constants.Cookies.Refresh, cookiePrefix);\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);\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(constants.Cookies.Custom, cookiePrefix);\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(constants.Cookies.Session, cookiePrefix);\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(constants.Cookies.IdToken, cookiePrefix);\r\n deletionPromises.push(cookieStore.delete(idTokenCookieName));\r\n\r\n const refreshTokenCookieName = getCookieName(constants.Cookies.Refresh, cookiePrefix);\r\n deletionPromises.push(cookieStore.delete(refreshTokenCookieName));\r\n\r\n const customTokenCookieName = getCookieName(constants.Cookies.Custom, cookiePrefix);\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\r\n\r\nexport async function createCustomTokenClaims(\r\n uid: string,\r\n developerClaims?: { [key: string]: unknown },\r\n): Promise<string> {\r\n const adminAuth = getAuthForTenant();\r\n try {\r\n const customToken = await adminAuth.createCustomToken(uid, developerClaims);\r\n return customToken;\r\n } catch (error) {\r\n console.error('[createCustomToken] Error creating custom token:', error);\r\n return '';\r\n }\r\n}\r\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 status: 'success',\r\n user: userRecord,\r\n message: 'Tenant user created successfully',\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 { getCookieName, getCookiePrefix } from '@tern-secure/shared/cookie';\nimport { handleFirebaseAuthError } from '@tern-secure/shared/errors';\nimport type { CookieStore, SessionResult, 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\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\n/**\n * Helper function to log debug messages only in development environment\n */\nconst debugLog = {\n log: (...args: unknown[]) => {\n if (process.env.NODE_ENV === 'development') {\n console.log(...args);\n }\n },\n warn: (...args: unknown[]) => {\n if (process.env.NODE_ENV === 'development') {\n console.warn(...args);\n }\n },\n error: (...args: unknown[]) => {\n console.error(...args);\n },\n};\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(sessionCookie, true);\n return {\n token: sessionCookie,\n userId: decondeClaims.uid,\n };\n } catch (error) {\n console.error('Error verifying session:', error);\n throw new Error('Invalid Session');\n }\n}\n\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(token: string): 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('[VerifyNextTernSessionCookie] uid in Decoded Token:', res.uid);\n return {\n valid: true,\n ...res,\n };\n } catch (error) {\n console.error('[VerifyNextTernSessionCookie] Error verifying session:', error);\n const authError = handleFirebaseAuthError(error);\n return {\n valid: false,\n error: authError,\n };\n }\n}\n\nexport async function ClearNextSessionCookie(\n tenantId?: string,\n deleteOptions?: {\n path?: string;\n domain?: string;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: 'lax' | 'strict' | 'none';\n revokeRefreshTokensOnSignOut?: boolean;\n },\n): Promise<SessionResult> {\n try {\n const tenantAuth = getAuthForTenant(tenantId || '');\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get(SESSION_CONSTANTS.COOKIE_NAME);\n const cookiePrefix = getCookiePrefix();\n const idTokenCookieName = getCookieName(constants.Cookies.IdToken, cookiePrefix);\n const idTokenCookie = cookieStore.get(idTokenCookieName);\n\n const finalDeleteOptions = {\n path: deleteOptions?.path,\n domain: deleteOptions?.domain,\n httpOnly: deleteOptions?.httpOnly,\n secure: deleteOptions?.secure,\n sameSite: deleteOptions?.sameSite,\n };\n\n cookieStore.delete({ name: SESSION_CONSTANTS.COOKIE_NAME, ...finalDeleteOptions });\n cookieStore.delete({ name: idTokenCookieName, ...finalDeleteOptions });\n cookieStore.delete({\n name: getCookieName(constants.Cookies.Refresh, cookiePrefix),\n ...finalDeleteOptions,\n });\n cookieStore.delete({ name: constants.Cookies.Custom, ...finalDeleteOptions });\n\n const shouldRevokeTokens =\n deleteOptions?.revokeRefreshTokensOnSignOut ??\n SESSION_CONSTANTS.REVOKE_REFRESH_TOKENS_ON_SIGNOUT;\n\n if (shouldRevokeTokens) {\n try {\n let userSub: string | undefined;\n\n // Try to get user sub from session cookie first\n if (sessionCookie?.value) {\n try {\n const decodedClaims = await tenantAuth.verifySessionCookie(sessionCookie.value);\n userSub = decodedClaims.sub;\n } catch (sessionError) {\n debugLog.warn(\n '[ClearNextSessionCookie] Session cookie verification failed:',\n sessionError,\n );\n }\n }\n\n // If no session cookie, try idToken cookie\n if (!userSub) {\n if (idTokenCookie?.value) {\n try {\n const decodedIdToken = await tenantAuth.verifyIdToken(idTokenCookie.value);\n userSub = decodedIdToken.sub;\n } catch (idTokenError) {\n debugLog.warn('[ClearNextSessionCookie] ID token verification failed:', idTokenError);\n }\n }\n }\n\n // Revoke tokens if we got a user sub\n if (userSub) {\n await tenantAuth.revokeRefreshTokens(userSub);\n debugLog.log(`[ClearNextSessionCookie] Successfully revoked tokens for user: ${userSub}`);\n } else {\n debugLog.warn('[ClearNextSessionCookie] No valid token found for revocation');\n }\n } catch (revokeError) {\n debugLog.error('[ClearNextSessionCookie] Failed to revoke refresh tokens:', revokeError);\n }\n }\n return { success: true, message: 'Session cleared successfully' };\n } catch (error) {\n debugLog.error('Error clearing session:', error);\n return { success: false, message: 'Failed to clear session cookies' };\n }\n}\n\nexport async function ClearNextSessionCookie_old(cookieStore: CookieStore): Promise<SessionResult> {\n try {\n const cookiePrefix = getCookiePrefix();\n\n const deletionPromises: Promise<void>[] = [];\n\n // Always delete default cookies\n const idTokenCookieName = getCookieName(constants.Cookies.IdToken, cookiePrefix);\n deletionPromises.push(cookieStore.delete(idTokenCookieName));\n\n const refreshTokenCookieName = getCookieName(constants.Cookies.Refresh, cookiePrefix);\n deletionPromises.push(cookieStore.delete(refreshTokenCookieName));\n\n const customTokenCookieName = getCookieName(constants.Cookies.Custom, cookiePrefix);\n deletionPromises.push(cookieStore.delete(customTokenCookieName));\n\n // Also delete legacy cookie names for backward compatibility\n deletionPromises.push(cookieStore.delete(constants.Cookies.Session));\n\n await Promise.all(deletionPromises);\n\n return {\n success: true,\n message: 'Session cleared successfully',\n };\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n return {\n success: false,\n message: authError.message || 'Failed to clear session',\n error: authError.code || 'INTERNAL_ERROR',\n };\n }\n}\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":["getCookieName","getCookiePrefix","handleFirebaseAuthError","handleFirebaseAuthError","getCookiePrefix","getCookieName"]}
|
|
1
|
+
{"version":3,"sources":["../../src/admin/sessionTernSecure.ts","../../src/utils/admin-init.ts","../../src/utils/config.ts","../../src/admin/tenant.ts","../../src/admin/nextSessionTernSecure.ts","../../src/instance/backendInstance.ts"],"sourcesContent":["'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\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(constants.Cookies.IdToken, cookiePrefix);\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(constants.Cookies.Refresh, cookiePrefix);\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) {\r\n const sessionOptions = options.cookies;\r\n const sessionCookieName = getCookieName(constants.Cookies.Session);\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(constants.Cookies.Custom, cookiePrefix);\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(constants.Cookies.Session, cookiePrefix);\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) {\r\n deletionPromises.push(cookieStore.delete(sessionCookieName));\r\n }\r\n\r\n // Always delete default cookies\r\n const idTokenCookieName = getCookieName(constants.Cookies.IdToken, cookiePrefix);\r\n deletionPromises.push(cookieStore.delete(idTokenCookieName));\r\n\r\n const refreshTokenCookieName = getCookieName(constants.Cookies.Refresh, cookiePrefix);\r\n deletionPromises.push(cookieStore.delete(refreshTokenCookieName));\r\n\r\n const customTokenCookieName = getCookieName(constants.Cookies.Custom, cookiePrefix);\r\n deletionPromises.push(cookieStore.delete(customTokenCookieName));\r\n\r\n // Delete auth_time cookie\r\n const authTimeCookieName = constants.Cookies.TernAut;\r\n deletionPromises.push(cookieStore.delete(authTimeCookieName));\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\r\n\r\nexport async function createCustomTokenClaims(\r\n uid: string,\r\n developerClaims?: { [key: string]: unknown },\r\n): Promise<string> {\r\n const adminAuth = getAuthForTenant();\r\n try {\r\n const customToken = await adminAuth.createCustomToken(uid, developerClaims);\r\n return customToken;\r\n } catch (error) {\r\n console.error('[createCustomToken] Error creating custom token:', error);\r\n return '';\r\n }\r\n}\r\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 status: 'success',\r\n user: userRecord,\r\n message: 'Tenant user created successfully',\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 { getCookieName, getCookiePrefix } from '@tern-secure/shared/cookie';\nimport { handleFirebaseAuthError } from '@tern-secure/shared/errors';\nimport type { CookieStore, SessionResult, 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\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\n/**\n * Helper function to log debug messages only in development environment\n */\nconst debugLog = {\n log: (...args: unknown[]) => {\n if (process.env.NODE_ENV === 'development') {\n console.log(...args);\n }\n },\n warn: (...args: unknown[]) => {\n if (process.env.NODE_ENV === 'development') {\n console.warn(...args);\n }\n },\n error: (...args: unknown[]) => {\n console.error(...args);\n },\n};\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(sessionCookie, true);\n return {\n token: sessionCookie,\n userId: decondeClaims.uid,\n };\n } catch (error) {\n console.error('Error verifying session:', error);\n throw new Error('Invalid Session');\n }\n}\n\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(token: string): 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('[VerifyNextTernSessionCookie] uid in Decoded Token:', res.uid);\n return {\n valid: true,\n ...res,\n };\n } catch (error) {\n console.error('[VerifyNextTernSessionCookie] Error verifying session:', error);\n const authError = handleFirebaseAuthError(error);\n return {\n valid: false,\n error: authError,\n };\n }\n}\n\nexport async function ClearNextSessionCookie(\n tenantId?: string,\n deleteOptions?: {\n path?: string;\n domain?: string;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: 'lax' | 'strict' | 'none';\n revokeRefreshTokensOnSignOut?: boolean;\n },\n): Promise<SessionResult> {\n try {\n const tenantAuth = getAuthForTenant(tenantId || '');\n const cookieStore = await cookies();\n const sessionCookie = cookieStore.get(SESSION_CONSTANTS.COOKIE_NAME);\n const cookiePrefix = getCookiePrefix();\n const idTokenCookieName = getCookieName(constants.Cookies.IdToken, cookiePrefix);\n const idTokenCookie = cookieStore.get(idTokenCookieName);\n\n const finalDeleteOptions = {\n path: deleteOptions?.path,\n domain: deleteOptions?.domain,\n httpOnly: deleteOptions?.httpOnly,\n secure: deleteOptions?.secure,\n sameSite: deleteOptions?.sameSite,\n };\n\n const idRefreshCustomTokenDeleteOptions = {\n path: '/',\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'strict' as const,\n };\n\n cookieStore.delete({ name: SESSION_CONSTANTS.COOKIE_NAME, ...finalDeleteOptions });\n cookieStore.delete({ name: constants.Cookies.TernAut });\n \n cookieStore.delete({ name: idTokenCookieName, ...idRefreshCustomTokenDeleteOptions });\n cookieStore.delete({\n name: getCookieName(constants.Cookies.Refresh, cookiePrefix),\n ...idRefreshCustomTokenDeleteOptions,\n });\n cookieStore.delete({ name: constants.Cookies.Custom, ...idRefreshCustomTokenDeleteOptions });\n\n const shouldRevokeTokens =\n deleteOptions?.revokeRefreshTokensOnSignOut ??\n SESSION_CONSTANTS.REVOKE_REFRESH_TOKENS_ON_SIGNOUT;\n\n if (shouldRevokeTokens) {\n try {\n let userSub: string | undefined;\n\n // Try to get user sub from session cookie first\n if (sessionCookie?.value) {\n try {\n const decodedClaims = await tenantAuth.verifySessionCookie(sessionCookie.value);\n userSub = decodedClaims.sub;\n } catch (sessionError) {\n debugLog.warn(\n '[ClearNextSessionCookie] Session cookie verification failed:',\n sessionError,\n );\n }\n }\n\n // If no session cookie, try idToken cookie\n if (!userSub) {\n if (idTokenCookie?.value) {\n try {\n const decodedIdToken = await tenantAuth.verifyIdToken(idTokenCookie.value);\n userSub = decodedIdToken.sub;\n } catch (idTokenError) {\n debugLog.warn('[ClearNextSessionCookie] ID token verification failed:', idTokenError);\n }\n }\n }\n\n // Revoke tokens if we got a user sub\n if (userSub) {\n await tenantAuth.revokeRefreshTokens(userSub);\n debugLog.log(`[ClearNextSessionCookie] Successfully revoked tokens for user: ${userSub}`);\n } else {\n debugLog.warn('[ClearNextSessionCookie] No valid token found for revocation');\n }\n } catch (revokeError) {\n debugLog.error('[ClearNextSessionCookie] Failed to revoke refresh tokens:', revokeError);\n }\n }\n return { success: true, message: 'Session cleared successfully' };\n } catch (error) {\n debugLog.error('Error clearing session:', error);\n return { success: false, message: 'Failed to clear session cookies' };\n }\n}\n\nexport async function ClearNextSessionCookie_old(cookieStore: CookieStore): Promise<SessionResult> {\n try {\n const cookiePrefix = getCookiePrefix();\n\n const deletionPromises: Promise<void>[] = [];\n\n // Always delete default cookies\n const idTokenCookieName = getCookieName(constants.Cookies.IdToken, cookiePrefix);\n deletionPromises.push(cookieStore.delete(idTokenCookieName));\n\n const refreshTokenCookieName = getCookieName(constants.Cookies.Refresh, cookiePrefix);\n deletionPromises.push(cookieStore.delete(refreshTokenCookieName));\n\n const customTokenCookieName = getCookieName(constants.Cookies.Custom, cookiePrefix);\n deletionPromises.push(cookieStore.delete(customTokenCookieName));\n\n // Also delete legacy cookie names for backward compatibility\n deletionPromises.push(cookieStore.delete(constants.Cookies.Session));\n\n await Promise.all(deletionPromises);\n\n return {\n success: true,\n message: 'Session cleared successfully',\n };\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n return {\n success: false,\n message: authError.message || 'Failed to clear session',\n error: authError.code || 'INTERNAL_ERROR',\n };\n }\n}\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":["getCookieName","getCookiePrefix","handleFirebaseAuthError","handleFirebaseAuthError","getCookiePrefix","getCookieName"]}
|