@tern-secure/auth 1.1.0-canary.v20251008165428 → 1.1.0-canary.v20251019190011

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/cjs/{resources → auth}/AuthCookieManager.js +12 -1
  2. package/dist/cjs/auth/AuthCookieManager.js.map +1 -0
  3. package/dist/cjs/auth/cookies/session.js +83 -0
  4. package/dist/cjs/auth/cookies/session.js.map +1 -0
  5. package/dist/cjs/auth/request.js +159 -0
  6. package/dist/cjs/auth/request.js.map +1 -0
  7. package/dist/cjs/instance/TernAuth.js +109 -19
  8. package/dist/cjs/instance/TernAuth.js.map +1 -1
  9. package/dist/cjs/instance/events.js +3 -2
  10. package/dist/cjs/instance/events.js.map +1 -1
  11. package/dist/cjs/instance/jwtClient.js +72 -0
  12. package/dist/cjs/instance/jwtClient.js.map +1 -0
  13. package/dist/cjs/resources/Base.js +7 -0
  14. package/dist/cjs/resources/Base.js.map +1 -1
  15. package/dist/cjs/resources/Session.js +105 -0
  16. package/dist/cjs/resources/Session.js.map +1 -0
  17. package/dist/cjs/resources/SignIn.js +25 -27
  18. package/dist/cjs/resources/SignIn.js.map +1 -1
  19. package/dist/cjs/resources/Token.js +32 -0
  20. package/dist/cjs/resources/Token.js.map +1 -0
  21. package/dist/cjs/resources/UserData.js +43 -0
  22. package/dist/cjs/resources/UserData.js.map +1 -0
  23. package/dist/cjs/resources/cookie.js +154 -0
  24. package/dist/cjs/resources/cookie.js.map +1 -0
  25. package/dist/cjs/resources/internal.js +4 -2
  26. package/dist/cjs/resources/internal.js.map +1 -1
  27. package/dist/cjs/utils/jwt.js +46 -0
  28. package/dist/cjs/utils/jwt.js.map +1 -0
  29. package/dist/cjs/utils/mapDecode.js +33 -0
  30. package/dist/cjs/utils/mapDecode.js.map +1 -0
  31. package/dist/esm/{resources → auth}/AuthCookieManager.js +13 -4
  32. package/dist/esm/auth/AuthCookieManager.js.map +1 -0
  33. package/dist/esm/auth/cookies/session.js +58 -0
  34. package/dist/esm/auth/cookies/session.js.map +1 -0
  35. package/dist/esm/auth/request.js +134 -0
  36. package/dist/esm/auth/request.js.map +1 -0
  37. package/dist/esm/instance/TernAuth.js +111 -20
  38. package/dist/esm/instance/TernAuth.js.map +1 -1
  39. package/dist/esm/instance/events.js +3 -2
  40. package/dist/esm/instance/events.js.map +1 -1
  41. package/dist/esm/instance/jwtClient.js +47 -0
  42. package/dist/esm/instance/jwtClient.js.map +1 -0
  43. package/dist/esm/resources/Base.js +7 -0
  44. package/dist/esm/resources/Base.js.map +1 -1
  45. package/dist/esm/resources/Session.js +81 -0
  46. package/dist/esm/resources/Session.js.map +1 -0
  47. package/dist/esm/resources/SignIn.js +25 -27
  48. package/dist/esm/resources/SignIn.js.map +1 -1
  49. package/dist/esm/resources/Token.js +8 -0
  50. package/dist/esm/resources/Token.js.map +1 -0
  51. package/dist/esm/resources/UserData.js +19 -0
  52. package/dist/esm/resources/UserData.js.map +1 -0
  53. package/dist/esm/resources/cookie.js +130 -0
  54. package/dist/esm/resources/cookie.js.map +1 -0
  55. package/dist/esm/resources/internal.js +2 -1
  56. package/dist/esm/resources/internal.js.map +1 -1
  57. package/dist/esm/utils/jwt.js +22 -0
  58. package/dist/esm/utils/jwt.js.map +1 -0
  59. package/dist/esm/utils/mapDecode.js +9 -0
  60. package/dist/esm/utils/mapDecode.js.map +1 -0
  61. package/dist/types/{resources → auth}/AuthCookieManager.d.ts +5 -1
  62. package/dist/types/auth/AuthCookieManager.d.ts.map +1 -0
  63. package/dist/types/auth/cookies/session.d.ts +8 -0
  64. package/dist/types/auth/cookies/session.d.ts.map +1 -0
  65. package/dist/types/auth/request.d.ts +49 -0
  66. package/dist/types/auth/request.d.ts.map +1 -0
  67. package/dist/types/instance/TernAuth.d.ts +17 -1
  68. package/dist/types/instance/TernAuth.d.ts.map +1 -1
  69. package/dist/types/instance/events.d.ts +9 -1
  70. package/dist/types/instance/events.d.ts.map +1 -1
  71. package/dist/types/instance/jwtClient.d.ts +22 -0
  72. package/dist/types/instance/jwtClient.d.ts.map +1 -0
  73. package/dist/types/resources/Base.d.ts +6 -0
  74. package/dist/types/resources/Base.d.ts.map +1 -1
  75. package/dist/types/resources/Session.d.ts +49 -0
  76. package/dist/types/resources/Session.d.ts.map +1 -0
  77. package/dist/types/resources/SignIn.d.ts +3 -1
  78. package/dist/types/resources/SignIn.d.ts.map +1 -1
  79. package/dist/types/resources/Token.d.ts +5 -0
  80. package/dist/types/resources/Token.d.ts.map +1 -0
  81. package/dist/types/resources/UserData.d.ts +8 -0
  82. package/dist/types/resources/UserData.d.ts.map +1 -0
  83. package/dist/types/resources/cookie.d.ts +24 -0
  84. package/dist/types/resources/cookie.d.ts.map +1 -0
  85. package/dist/types/resources/internal.d.ts +2 -1
  86. package/dist/types/resources/internal.d.ts.map +1 -1
  87. package/dist/types/utils/jwt.d.ts +12 -0
  88. package/dist/types/utils/jwt.d.ts.map +1 -0
  89. package/dist/types/utils/mapDecode.d.ts +4 -0
  90. package/dist/types/utils/mapDecode.d.ts.map +1 -0
  91. package/package.json +3 -3
  92. package/dist/cjs/resources/AuthCookieManager.js.map +0 -1
  93. package/dist/esm/resources/AuthCookieManager.js.map +0 -1
  94. package/dist/types/resources/AuthCookieManager.d.ts.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/instance/TernAuth.ts"],"sourcesContent":["import { handleFirebaseAuthError } from '@tern-secure/shared/errors';\nimport { createTernAuthEventBus, ternEvents } from '@tern-secure/shared/ternStatusEvent';\nimport { stripScheme } from '@tern-secure/shared/url';\nimport { handleValueOrFn } from '@tern-secure/shared/utils';\nimport type {\n DomainOrProxyUrl,\n InstanceType,\n ListenerCallback,\n RedirectOptions,\n SignedInSession,\n SignInRedirectOptions,\n SignInResource,\n SignInResponse,\n SignOut,\n SignOutOptions,\n SignUpRedirectOptions,\n SignUpResource,\n TernAuthSDK,\n TernSecureAuth as TernSecureAuthInterface,\n TernSecureAuthOptions,\n TernSecureAuthStatus,\n TernSecureConfig,\n TernSecureResources,\n TernSecureUser,\n UnsubscribeCallback,\n} from '@tern-secure/types';\nimport type { FirebaseApp } from 'firebase/app';\nimport { getApps, initializeApp } from 'firebase/app';\nimport type { Auth, Auth as TernAuth } from 'firebase/auth';\nimport {\n browserLocalPersistence,\n browserSessionPersistence,\n connectAuthEmulator,\n getRedirectResult,\n initializeAuth,\n inMemoryPersistence,\n onAuthStateChanged,\n onIdTokenChanged,\n} from 'firebase/auth';\nimport { getInstallations } from 'firebase/installations';\n\nimport { AuthCookieManager, SignIn, SignUp, TernSecureBase } from '../resources/internal';\nimport { buildURL, hasRedirectLoop } from '../utils/construct';\nimport { type ApiClient, createCoreApiClient } from './c_coreApiClient';\nimport { eventBus, events } from './events';\n\nexport function inBrowser(): boolean {\n return typeof window !== 'undefined';\n}\n\nexport { TernAuth };\n\n/**\n * Firebase implementation of the TernSecureAuth interface\n */\nexport class TernSecureAuth implements TernSecureAuthInterface {\n public static version: string = PACKAGE_VERSION;\n public static sdkMetadata: TernAuthSDK = {\n name: PACKAGE_NAME,\n version: PACKAGE_VERSION,\n environment: process.env.NODE_ENV || 'production',\n };\n private static instance: TernSecureAuth | null = null;\n private _currentUser: TernSecureUser | null = null;\n private signedInSession: SignedInSession | null = null;\n private firebaseClientApp: FirebaseApp | undefined;\n private authStateUnsubscribe: (() => void) | null = null;\n private auth!: Auth;\n private csrfToken: string | undefined;\n public isLoading = false;\n public error: Error | null = null;\n public user: TernSecureUser | null | undefined = null;\n public __internal_country?: string | null;\n #domain: DomainOrProxyUrl['domain'];\n #apiClient: ApiClient;\n #apiUrl: string;\n #instanceType?: InstanceType;\n #status: TernSecureAuthInterface['status'] = 'loading';\n #listeners: Array<(emission: TernSecureResources) => void> = [];\n #options: TernSecureAuthOptions = {};\n #authCookieManager?: AuthCookieManager;\n #publicEventBus = createTernAuthEventBus();\n\n signIn!: SignInResource;\n signUp!: SignUpResource;\n\n get isReady(): boolean {\n return this.status === 'ready';\n }\n\n get status(): TernSecureAuthInterface['status'] {\n return this.#status;\n }\n\n get version(): string {\n return TernSecureAuth.version;\n }\n\n set sdkMetadata(metadata: TernAuthSDK) {\n TernSecureAuth.sdkMetadata = metadata;\n }\n\n get sdkMetadata(): TernAuthSDK {\n return TernSecureAuth.sdkMetadata;\n }\n\n get requiresVerification(): boolean {\n return this.#options.requiresVerification ?? true;\n }\n\n get apiUrl(): string {\n return this.#apiUrl;\n }\n\n get domain(): string {\n if (inBrowser()) {\n const strippedDomainString = stripScheme(\n handleValueOrFn(this.#domain, new URL(window.location.href)),\n );\n if (this.#instanceType === 'production') {\n return strippedDomainString;\n }\n return strippedDomainString;\n }\n return '';\n }\n\n get instanceType() {\n return this.#instanceType;\n }\n\n public constructor(options?: TernSecureAuthOptions) {\n this.#domain = options?.ternSecureConfig?.authDomain;\n this.#apiUrl = options?.apiUrl || '';\n this.#instanceType = (process.env.NODE_ENV as InstanceType) || 'production';\n\n this.#apiClient = createCoreApiClient({\n domain: this.#domain,\n apiUrl: options?.apiUrl,\n instanceType: this.instanceType as InstanceType,\n });\n\n this.#publicEventBus.emit(ternEvents.Status, 'loading');\n TernSecureBase.ternsecure = this;\n }\n\n public getApiClient = (): ApiClient => this.#apiClient;\n\n public setLoading(isLoading: boolean): void {\n this.isLoading = isLoading;\n }\n\n public authCookieManager(): AuthCookieManager | undefined {\n return this.#authCookieManager;\n }\n\n public _internal_getOption<K extends keyof TernSecureAuthOptions>(\n key: K,\n ): TernSecureAuthOptions[K] {\n return this.#options[key];\n }\n\n public _internal_getAllOptions(): Readonly<TernSecureAuthOptions> {\n return Object.freeze({ ...this.#options });\n }\n\n static getorCreateInstance(options?: TernSecureAuthOptions): TernSecureAuth {\n if (!this.instance) {\n this.instance = new TernSecureAuth(options);\n }\n return this.instance;\n }\n\n static clearInstance() {\n if (TernSecureAuth.instance) {\n if (TernSecureAuth.instance.authStateUnsubscribe) {\n TernSecureAuth.instance.authStateUnsubscribe();\n TernSecureAuth.instance.authStateUnsubscribe = null;\n }\n TernSecureAuth.instance = null;\n }\n }\n\n public static initialize(options: TernSecureAuthOptions): TernSecureAuth {\n const instance = this.getorCreateInstance(options);\n instance.#initialize(options);\n return instance;\n }\n\n #initialize = (options: TernSecureAuthOptions): TernSecureAuth => {\n this.#options = this.#initOptions(options);\n\n try {\n if (!this.#options.ternSecureConfig) {\n throw new Error('TernSecureConfig is required to initialize TernSecureAuth');\n }\n\n if (!this.#options.apiUrl) {\n throw new Error('apiUrl is required to initialize TernSecureAuth');\n }\n\n this.initializeFirebaseApp(this.#options.ternSecureConfig);\n this.authStateUnsubscribe = this.initAuthStateListener();\n // /this.authStateUnsubscribe = this._onIdTokenChanged();\n\n this.#authCookieManager = new AuthCookieManager();\n this.csrfToken = this.#authCookieManager.getCSRFToken();\n\n this.signIn = new SignIn(this.auth, this.csrfToken);\n this.signUp = new SignUp(this.auth);\n\n this.#setStatus('ready');\n this.#publicEventBus.emit(ternEvents.Status, 'ready');\n\n return this;\n } catch (error) {\n this.error = error as Error;\n this.#setStatus('error');\n this.#publicEventBus.emit(ternEvents.Status, 'error');\n throw error;\n }\n };\n\n private initializeFirebaseApp(config: TernSecureConfig) {\n const appName = config.appName || '[DEFAULT]';\n this.firebaseClientApp = getApps().length === 0 ? initializeApp(config, appName) : getApps()[0];\n\n const persistence = this.#setPersistence();\n const auth = initializeAuth(this.firebaseClientApp, {\n persistence,\n });\n\n this.auth = auth;\n\n if (config.tenantId) {\n this.auth.tenantId = config.tenantId;\n }\n\n this.#configureEmulator();\n\n getInstallations(this.firebaseClientApp);\n }\n\n public signOut: SignOut = async (options?: SignOutOptions) => {\n const redirectUrl = options?.redirectUrl || this.#constructAfterSignOutUrl();\n if (options?.onBeforeSignOut) {\n await options.onBeforeSignOut();\n }\n\n await this.auth.signOut();\n\n if (options?.onAfterSignOut) {\n await options.onAfterSignOut();\n }\n if (inBrowser()) {\n window.location.href = redirectUrl;\n }\n eventBus.emit(events.UserSignOut, null);\n eventBus.emit(events.TokenRefreshed, { token: null });\n this.#emit();\n };\n\n get currentSession(): SignedInSession | null {\n return this.signedInSession;\n }\n\n private initAuthStateListener(): () => void {\n return onAuthStateChanged(this.auth, async (user: TernSecureUser | null) => {\n await this.auth.authStateReady();\n this._currentUser = user;\n await this.updateCurrentSession();\n\n this.#emit();\n });\n }\n\n private _onIdTokenChanged(): () => void {\n return onIdTokenChanged(this.auth, async (user: TernSecureUser | null) => {\n await this.auth.authStateReady();\n this._currentUser = user;\n await this.updateCurrentSession();\n\n //eventBus.emit(events.TokenRefreshed, { token: user ? await user.getIdTokenResult() : null });\n this.#emit();\n });\n }\n\n public onAuthStateChanged(callback: (cb: any) => void): () => void {\n return onAuthStateChanged(this.auth, callback);\n }\n\n public onIdTokenChanged(callback: (cb: any) => void): () => void {\n return onIdTokenChanged(this.auth, callback);\n }\n\n private async updateCurrentSession(): Promise<void> {\n if (!this._currentUser) {\n this.signedInSession = null;\n return;\n }\n\n try {\n const res = await this._currentUser.getIdTokenResult();\n this.signedInSession = {\n status: 'active',\n token: res.token,\n claims: res.claims,\n issuedAtTime: res.issuedAtTime,\n expirationTime: res.expirationTime,\n authTime: res.authTime,\n signInProvider: res.signInProvider || 'unknown',\n };\n } catch (error) {\n console.error('[TernSecureAuth] Error updating session:', error);\n this.signedInSession = null;\n }\n }\n\n public async checkRedirectResult(): Promise<SignInResponse | null> {\n try {\n const result = await getRedirectResult(this.auth);\n if (result) {\n return {\n success: true,\n user: result.user as TernSecureUser,\n };\n }\n return null;\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n return {\n success: false,\n message: authError.message,\n error: authError.code,\n user: null,\n };\n }\n }\n\n public getRedirectResult = async (): Promise<any> => {\n throw new Error('getRedirectResult not implemented');\n };\n\n public addListener = (listener: ListenerCallback): UnsubscribeCallback => {\n this.#listeners.push(listener);\n if (this._currentUser) {\n listener({\n user: this._currentUser,\n session: this.signedInSession,\n });\n }\n\n const unsubscribe = () => {\n this.#listeners = this.#listeners.filter(l => l !== listener);\n };\n return unsubscribe;\n };\n\n public on: TernSecureAuthInterface['on'] = (...args) => {\n this.#publicEventBus.on(...args);\n };\n\n public off: TernSecureAuthInterface['off'] = (...args) => {\n this.#publicEventBus.off(...args);\n };\n\n public initialize(options: TernSecureAuthOptions): Promise<void> {\n this._initialize(options);\n return Promise.resolve();\n }\n\n public static create(options: TernSecureAuthOptions): TernSecureAuth {\n const instance = this.getorCreateInstance();\n instance.initialize(options);\n return instance;\n }\n\n _initialize = (options: TernSecureAuthOptions): void => {\n this.#options = this.#initOptions(options);\n try {\n if (!this.#options.ternSecureConfig) {\n throw new Error('TernSecureConfig is required to initialize TernSecureAuth');\n }\n\n this.initializeFirebaseApp(this.#options.ternSecureConfig);\n\n this.signIn = new SignIn(this.auth, this.csrfToken);\n this.signUp = new SignUp(this.auth);\n\n this.#setStatus('ready');\n } catch (error) {\n this.error = error as Error;\n this.#setStatus('error');\n throw error;\n }\n };\n\n public constructUrlWithAuthRedirect = (to: string): string => {\n const baseUrl = window.location.origin;\n const url = new URL(to, baseUrl);\n\n if (url.origin === window.location.origin) {\n return url.href;\n }\n\n return url.toString();\n };\n\n #buildUrl = (key: 'signInUrl' | 'signUpUrl', options: RedirectOptions): string => {\n if (!key || !this.isReady) {\n return '';\n }\n\n const baseUrlConfig = key === 'signInUrl' ? this.#options.signInUrl : this.#options.signUpUrl;\n const defaultPagePath = key === 'signInUrl' ? '/sign-in' : '/sign-up';\n const base = baseUrlConfig || defaultPagePath;\n\n let effectiveRedirectUrl: string | null | undefined;\n\n // Priority 1: Get redirect URL from options (signInForceRedirectUrl or signUpForceRedirectUrl)\n if (key === 'signInUrl' && 'signInForceRedirectUrl' in options) {\n effectiveRedirectUrl = options.signInForceRedirectUrl;\n } else if (key === 'signUpUrl' && 'signUpForceRedirectUrl' in options) {\n effectiveRedirectUrl = options.signUpForceRedirectUrl;\n }\n\n // Priority 2: If no force redirect from options, check 'redirect' param in current URL (only in browser)\n if (!effectiveRedirectUrl && inBrowser()) {\n const currentUrlParams = new URLSearchParams(window.location.search);\n const existingRedirectParam = currentUrlParams.get('redirect_url');\n if (existingRedirectParam) {\n effectiveRedirectUrl = existingRedirectParam;\n }\n }\n\n // Priority 3: If still no redirect URL, fallback to current page's full path (only in browser)\n // This ensures that if the call originates from a page, it attempts to redirect back there by default.\n if (!effectiveRedirectUrl && inBrowser()) {\n effectiveRedirectUrl =\n window.location.pathname + window.location.search + window.location.hash;\n }\n\n if (effectiveRedirectUrl && inBrowser()) {\n let signInPagePath: string | undefined;\n try {\n signInPagePath = this.#options.signInUrl\n ? new URL(this.#options.signInUrl, window.location.origin).pathname\n : defaultPagePath;\n } catch {\n signInPagePath = defaultPagePath;\n }\n\n let signUpPagePath: string | undefined;\n try {\n signUpPagePath = this.#options.signUpUrl\n ? new URL(this.#options.signUpUrl, window.location.origin).pathname\n : key === 'signUpUrl'\n ? defaultPagePath\n : '/sign-in';\n } catch {\n signUpPagePath = key === 'signUpUrl' ? defaultPagePath : '/sign-in';\n }\n\n const redirectTargetObj = new URL(effectiveRedirectUrl, window.location.origin);\n\n if (\n redirectTargetObj.pathname === signInPagePath ||\n redirectTargetObj.pathname === signUpPagePath\n ) {\n // If the intended redirect path is the sign-in or sign-up page itself,\n // change the redirect target to the application root ('/').\n effectiveRedirectUrl = '/';\n }\n }\n\n const paramsForBuildUrl: Parameters<typeof buildURL>[0] = {\n base,\n searchParams: new URLSearchParams(),\n };\n\n if (effectiveRedirectUrl) {\n // Check if a redirect URL was determined\n if (inBrowser()) {\n const absoluteRedirectUrl = new URL(effectiveRedirectUrl, window.location.origin).href;\n paramsForBuildUrl.searchParams?.set('redirect', absoluteRedirectUrl);\n } else {\n // If not in browser, use the effectiveRedirectUrl as is.\n // This assumes it's either absolute or a path the server can interpret.\n paramsForBuildUrl.searchParams?.set('redirect', effectiveRedirectUrl);\n }\n }\n\n const constructedUrl = buildURL(paramsForBuildUrl, {\n stringify: true,\n skipOrigin: false,\n });\n\n if (typeof constructedUrl !== 'string') {\n console.error(\n '[TernSecure] Error: buildURL did not return a string as expected. Falling back to base URL.',\n );\n if (inBrowser()) {\n try {\n return new URL(base, window.location.origin).href;\n } catch {\n return base;\n }\n }\n return base;\n }\n\n return this.constructUrlWithAuthRedirect(constructedUrl);\n };\n\n #constructAfterSignInUrl = (): string => {\n if (!inBrowser()) {\n return '/';\n }\n\n let redirectPath: string | null | undefined = undefined;\n const defaultRedirectPath = '/';\n\n // Priority 1: Check for signInForceRedirectUrl from instance options\n if (this.#options.signInForceRedirectUrl) {\n redirectPath = this.#options.signInForceRedirectUrl;\n }\n\n // Priority 2: If no force redirect, check 'redirect' param in current URL\n if (!redirectPath) {\n const urlParams = new URLSearchParams(window.location.search);\n const redirectPathFromParams = urlParams.get('redirect_url');\n if (redirectPathFromParams) {\n redirectPath = redirectPathFromParams;\n }\n }\n\n // Priority 3: Fallback to default path\n if (!redirectPath) {\n redirectPath = defaultRedirectPath;\n }\n\n const currentPath = window.location.pathname;\n\n if (hasRedirectLoop(currentPath, redirectPath)) {\n //console.warn('[TernSecure] Redirect loop detected. Redirecting to default path.');\n return defaultRedirectPath;\n }\n\n return this.constructUrlWithAuthRedirect(redirectPath);\n };\n\n #constructAfterSignOutUrl = (): string => {\n if (!this.#options.afterSignOutUrl) {\n return '/';\n }\n return this.constructUrlWithAuthRedirect(this.#options.afterSignOutUrl);\n };\n\n public redirectToSignIn = async (options?: SignInRedirectOptions): Promise<unknown> => {\n if (inBrowser()) {\n const url = this.constructSignInUrl(options);\n window.location.href = url;\n }\n return;\n };\n\n public redirectToSignUp = async (options?: SignUpRedirectOptions): Promise<unknown> => {\n if (inBrowser()) {\n const redirectUrl = this.constructSignUpUrl();\n window.location.href = redirectUrl;\n }\n return;\n };\n\n redirectAfterSignIn = async (): Promise<void> => {\n if (inBrowser()) {\n const destinationUrl = this.#constructAfterSignInUrl();\n window.location.href = destinationUrl;\n }\n };\n\n redirectAfterSignUp = (): void => {\n throw new Error('redirectAfterSignUp is not implemented yet');\n };\n\n public constructSignInUrl = (options?: SignInRedirectOptions): string => {\n return this.#buildUrl('signInUrl', { ...options });\n };\n\n public constructSignUpUrl = (options?: SignUpRedirectOptions): string => {\n return this.#buildUrl('signUpUrl', { ...options });\n };\n\n __internal_setCountry = (country: string | null) => {\n if (!this.__internal_country) {\n this.__internal_country = country;\n }\n };\n\n #initOptions = (options: TernSecureAuthOptions): TernSecureAuthOptions => {\n return {\n ...options,\n };\n };\n\n #emit = (): void => {\n if (this._currentUser) {\n for (const listener of this.#listeners) {\n listener({\n user: this._currentUser,\n session: this.signedInSession,\n });\n }\n }\n };\n\n #setStatus(newStatus: TernSecureAuthStatus): void {\n if (this.#status !== newStatus) {\n this.#status = newStatus;\n this.#publicEventBus.emit(ternEvents.Status, this.#status);\n\n if (newStatus === 'ready') {\n this.#publicEventBus.emit(ternEvents.Status, 'ready');\n }\n }\n }\n\n #setPersistence = () => {\n const persistenceType = this.#options.persistence || 'none';\n\n switch (persistenceType) {\n case 'browserCookie':\n return inMemoryPersistence;\n case 'session':\n return browserSessionPersistence;\n case 'local':\n return browserLocalPersistence;\n case 'none':\n default:\n return inMemoryPersistence;\n }\n };\n\n #emulatorHost = (): string | undefined => {\n if (typeof process === 'undefined') return undefined;\n return process.env.FIREBASE_AUTH_EMULATOR_HOST;\n };\n\n #configureEmulator = (): void => {\n const host = this.#emulatorHost();\n const isDev = this.#instanceType === 'development';\n const shouldUseEmulator = isDev && !!host;\n if (!shouldUseEmulator || !host) {\n return;\n }\n\n const emulatorUrl = host.startsWith('http') ? host : `http://${host}`;\n\n try {\n //(this.auth as unknown as any)._canInitEmulator = true;\n connectAuthEmulator(this.auth, emulatorUrl, { disableWarnings: true });\n console.warn(`[TernSecure] Firebase Auth Emulator connected at ${emulatorUrl}`);\n } catch (error) {\n console.error('[TernSecure] Error connecting to Firebase Auth Emulator:', error);\n }\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/instance/TernAuth.ts"],"sourcesContent":["import { handleFirebaseAuthError } from '@tern-secure/shared/errors';\nimport { createTernAuthEventBus, ternEvents } from '@tern-secure/shared/ternStatusEvent';\nimport { stripScheme } from '@tern-secure/shared/url';\nimport { handleValueOrFn } from '@tern-secure/shared/utils';\nimport type {\n CreateActiveSession,\n DomainOrProxyUrl,\n InstanceType,\n ListenerCallback,\n RedirectOptions,\n SessionResource,\n SignedInSession,\n SignInRedirectOptions,\n SignInResource,\n SignInResponse,\n SignOut,\n SignOutOptions,\n SignUpRedirectOptions,\n SignUpResource,\n TernAuthSDK,\n TernSecureAuth as TernSecureAuthInterface,\n TernSecureAuthOptions,\n TernSecureAuthStatus,\n TernSecureConfig,\n TernSecureResources,\n TernSecureUser,\n TernSecureUserData,\n UnsubscribeCallback,\n} from '@tern-secure/types';\nimport type { FirebaseApp } from 'firebase/app';\nimport { getApps, initializeApp } from 'firebase/app';\nimport type { Auth, Auth as TernAuth } from 'firebase/auth';\nimport {\n browserLocalPersistence,\n browserSessionPersistence,\n connectAuthEmulator,\n getIdToken,\n getRedirectResult,\n initializeAuth,\n inMemoryPersistence,\n onAuthStateChanged,\n onIdTokenChanged,\n} from 'firebase/auth';\nimport { getInstallations } from 'firebase/installations';\n\nimport { type ClientAuthRequest, createClientAuthRequest } from '../auth/request';\nimport { AuthCookieManager, Session, SignIn, SignUp, TernSecureBase } from '../resources/internal';\nimport { buildURL, hasRedirectLoop } from '../utils/construct';\nimport { type ApiClient, createCoreApiClient } from './c_coreApiClient';\nimport { eventBus, events } from './events';\nimport { createClientFromJwt } from './jwtClient';\n\nexport function inBrowser(): boolean {\n return typeof window !== 'undefined';\n}\n\nexport { TernAuth };\n\n/**\n * Firebase implementation of the TernSecureAuth interface\n */\nexport class TernSecureAuth implements TernSecureAuthInterface {\n public static version: string = PACKAGE_VERSION;\n public static sdkMetadata: TernAuthSDK = {\n name: PACKAGE_NAME,\n version: PACKAGE_VERSION,\n environment: process.env.NODE_ENV || 'production',\n };\n private static instance: TernSecureAuth | null = null;\n private _currentUser: TernSecureUser | null = null;\n private signedInSession: SignedInSession | null = null;\n private firebaseClientApp: FirebaseApp | undefined;\n private authStateUnsubscribe: (() => void) | null = null;\n private auth!: Auth;\n private csrfToken: string | undefined;\n public isLoading = false;\n public error: Error | null = null;\n public user: TernSecureUser | null | undefined = null;\n public __internal_country?: string | null;\n #domain: DomainOrProxyUrl['domain'];\n #apiClient: ApiClient;\n #apiUrl: string;\n #instanceType?: InstanceType;\n #status: TernSecureAuthInterface['status'] = 'loading';\n #listeners: Array<(emission: TernSecureResources) => void> = [];\n #options: TernSecureAuthOptions = {};\n #authCookieManager?: AuthCookieManager;\n #clientAuthRequest?: ClientAuthRequest;\n #publicEventBus = createTernAuthEventBus();\n\n signIn!: SignInResource;\n signUp!: SignUpResource;\n session!: SessionResource;\n\n get isReady(): boolean {\n return this.status === 'ready';\n }\n\n get status(): TernSecureAuthInterface['status'] {\n return this.#status;\n }\n\n get version(): string {\n return TernSecureAuth.version;\n }\n\n set sdkMetadata(metadata: TernAuthSDK) {\n TernSecureAuth.sdkMetadata = metadata;\n }\n\n get sdkMetadata(): TernAuthSDK {\n return TernSecureAuth.sdkMetadata;\n }\n\n get requiresVerification(): boolean {\n return this.#options.requiresVerification ?? true;\n }\n\n get apiUrl(): string {\n return this.#apiUrl;\n }\n\n get domain(): string {\n if (inBrowser()) {\n const strippedDomainString = stripScheme(\n handleValueOrFn(this.#domain, new URL(window.location.href)),\n );\n if (this.#instanceType === 'production') {\n return strippedDomainString;\n }\n return strippedDomainString;\n }\n return '';\n }\n\n get instanceType() {\n return this.#instanceType;\n }\n\n public constructor(options?: TernSecureAuthOptions) {\n this.#domain = options?.ternSecureConfig?.authDomain;\n this.#apiUrl = options?.apiUrl || '';\n this.#instanceType = (process.env.NODE_ENV as InstanceType) || 'production';\n\n this.#apiClient = createCoreApiClient({\n domain: this.#domain,\n apiUrl: options?.apiUrl,\n instanceType: this.instanceType as InstanceType,\n });\n\n this.#publicEventBus.emit(ternEvents.Status, 'loading');\n TernSecureBase.ternsecure = this;\n }\n\n public getApiClient = (): ApiClient => this.#apiClient;\n\n /**\n * Get user data for the provided ID token via backend API\n */\n public async getUserData(): Promise<TernSecureUserData | null> {\n if (!this.#clientAuthRequest) {\n throw new Error('Client auth request not initialized');\n }\n\n return this.#clientAuthRequest.getUserData();\n }\n\n public setLoading(isLoading: boolean): void {\n this.isLoading = isLoading;\n }\n\n public authCookieManager(): AuthCookieManager | undefined {\n return this.#authCookieManager;\n }\n\n public _internal_getOption<K extends keyof TernSecureAuthOptions>(\n key: K,\n ): TernSecureAuthOptions[K] {\n return this.#options[key];\n }\n\n public _internal_getAllOptions(): Readonly<TernSecureAuthOptions> {\n return Object.freeze({ ...this.#options });\n }\n\n static getorCreateInstance(options?: TernSecureAuthOptions): TernSecureAuth {\n if (!this.instance) {\n this.instance = new TernSecureAuth(options);\n }\n return this.instance;\n }\n\n static clearInstance() {\n if (TernSecureAuth.instance) {\n if (TernSecureAuth.instance.authStateUnsubscribe) {\n TernSecureAuth.instance.authStateUnsubscribe();\n TernSecureAuth.instance.authStateUnsubscribe = null;\n }\n TernSecureAuth.instance = null;\n }\n }\n\n public static initialize(options: TernSecureAuthOptions): TernSecureAuth {\n const instance = this.getorCreateInstance(options);\n instance.#initialize(options);\n return instance;\n }\n\n #initialize = (options: TernSecureAuthOptions): TernSecureAuth => {\n this.#options = this.#initOptions(options);\n\n try {\n if (!this.#options.ternSecureConfig) {\n throw new Error('TernSecureConfig is required to initialize TernSecureAuth');\n }\n\n if (!this.#options.apiUrl) {\n throw new Error('apiUrl is required to initialize TernSecureAuth');\n }\n\n this.initializeFirebaseApp(this.#options.ternSecureConfig);\n\n const isBrowserCookiePersistence = this.#options.persistence === 'browserCookie';\n\n if (!isBrowserCookiePersistence) {\n this.authStateUnsubscribe = this.initAuthStateListener();\n }\n\n this.#authCookieManager = new AuthCookieManager();\n this.csrfToken = this.#authCookieManager.getCSRFToken();\n\n this.#clientAuthRequest = createClientAuthRequest();\n\n this.signIn = new SignIn(this.auth, this.csrfToken);\n this.signUp = new SignUp(this.auth);\n\n eventBus.on(events.SessionChanged, () => {\n this.#setCreatedActiveSession(this.user || null);\n this.#emit();\n });\n\n this.#setStatus('ready');\n this.#publicEventBus.emit(ternEvents.Status, 'ready');\n\n return this;\n } catch (error) {\n this.error = error as Error;\n this.#setStatus('error');\n this.#publicEventBus.emit(ternEvents.Status, 'error');\n throw error;\n }\n };\n\n private initializeFirebaseApp(config: TernSecureConfig) {\n const appName = config.appName || '[DEFAULT]';\n this.firebaseClientApp = getApps().length === 0 ? initializeApp(config, appName) : getApps()[0];\n\n const persistence = this.#setPersistence();\n const auth = initializeAuth(this.firebaseClientApp, {\n persistence,\n });\n\n this.auth = auth;\n\n if (config.tenantId) {\n this.auth.tenantId = config.tenantId;\n }\n\n this.#configureEmulator();\n\n getInstallations(this.firebaseClientApp);\n }\n\n\n /**\n * use when cookie are not httpOnly\n */\n initClient = () => {\n const idTokenInCookie = this.#authCookieManager?.getIdTokenCookie();\n const jwtClient = createClientFromJwt(idTokenInCookie || null);\n this.user = jwtClient as TernSecureUser | null;\n this.#emit();\n };\n\n\n /**\n * @deprecated will be removed in future releases.\n */\n initClientAuthRequest = () => {\n this.#clientAuthRequest\n ?.getIdTokenFromCookie()\n .then(idTokenInCookie => {\n const { token } = idTokenInCookie;\n const jwtClient = createClientFromJwt(token || null);\n this.user = jwtClient as TernSecureUser | null;\n this.#emit();\n })\n .catch(error => {\n console.error(\n '[ternauth] Error during client auth request initialization:',\n error\n );\n this.user = null;\n this.#emit();\n });\n };\n\n public signOut: SignOut = async (options?: SignOutOptions) => {\n const redirectUrl = options?.redirectUrl || this.#constructAfterSignOutUrl();\n if (options?.onBeforeSignOut) {\n await options.onBeforeSignOut();\n }\n\n await this.auth.signOut();\n\n if (options?.onAfterSignOut) {\n await options.onAfterSignOut();\n }\n if (inBrowser()) {\n window.location.href = redirectUrl;\n }\n eventBus.emit(events.UserSignOut, null);\n eventBus.emit(events.TokenUpdate, { token: null });\n this.#emit();\n };\n\n get currentSession(): SignedInSession | null {\n return this.signedInSession;\n }\n\n private initAuthListener(): () => void {\n (async () => {\n await this.auth.authStateReady();\n const user = this.auth.currentUser as TernSecureUser | null;\n this._currentUser = user;\n this.user = user;\n await this.updateCurrentSession();\n this.#emit();\n })();\n\n // Return a no-op unsubscribe function since we're not setting up a listener\n return () => {\n // No-op: nothing to unsubscribe from\n };\n }\n\n private initAuthStateListener(): () => void {\n return onAuthStateChanged(this.auth, async (user: TernSecureUser | null) => {\n await this.auth.authStateReady();\n this._currentUser = user;\n this.user = user;\n await this.updateCurrentSession();\n\n this.#emit();\n });\n }\n\n private _onIdTokenChanged(): () => void {\n return onIdTokenChanged(this.auth, async (user: TernSecureUser | null) => {\n await this.auth.authStateReady();\n this._currentUser = user;\n this.user = user;\n await this.updateCurrentSession();\n\n this.#emit();\n });\n }\n\n private async getIdToken(): Promise<string | null> {\n await this.auth.authStateReady();\n if (!this.auth.currentUser) {\n return null;\n }\n return getIdToken(this.auth.currentUser);\n }\n\n public onAuthStateChanged(callback: (cb: any) => void): () => void {\n return onAuthStateChanged(this.auth, callback);\n }\n\n public onIdTokenChanged(callback: (cb: any) => void): () => void {\n return onIdTokenChanged(this.auth, callback);\n }\n\n private async updateCurrentSession(): Promise<void> {\n if (!this._currentUser) {\n this.signedInSession = null;\n return;\n }\n\n try {\n const res = await this._currentUser.getIdTokenResult();\n this.signedInSession = {\n status: 'active',\n token: res.token,\n claims: res.claims,\n issuedAtTime: res.issuedAtTime,\n expirationTime: res.expirationTime,\n authTime: res.authTime,\n signInProvider: res.signInProvider || 'unknown',\n signInSecondFactor: res.signInSecondFactor,\n };\n } catch (error) {\n console.error('[TernSecureAuth] Error updating session:', error);\n this.signedInSession = null;\n }\n }\n\n public async checkRedirectResult(): Promise<SignInResponse | null> {\n try {\n const result = await getRedirectResult(this.auth);\n if (result) {\n return {\n status: 'success',\n user: result.user as TernSecureUser,\n };\n }\n return null;\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n return {\n status: 'error',\n message: authError.message,\n error: authError.code,\n };\n }\n }\n\n public getRedirectResult = async (): Promise<any> => {\n throw new Error('getRedirectResult not implemented');\n };\n\n public addListener = (listener: ListenerCallback): UnsubscribeCallback => {\n this.#listeners.push(listener);\n if (this._currentUser) {\n listener({\n user: this._currentUser,\n session: this.signedInSession,\n });\n }\n\n const unsubscribe = () => {\n this.#listeners = this.#listeners.filter(l => l !== listener);\n };\n return unsubscribe;\n };\n\n public on: TernSecureAuthInterface['on'] = (...args) => {\n this.#publicEventBus.on(...args);\n };\n\n public off: TernSecureAuthInterface['off'] = (...args) => {\n this.#publicEventBus.off(...args);\n };\n\n public createActiveSession: CreateActiveSession = async ({\n session,\n redirectUrl,\n }): Promise<void> => {\n try {\n if (!session) {\n throw new Error('No session provided to createActiveSession');\n }\n const sessionResult = await session.getIdTokenResult();\n const sessionData = new Session(sessionResult);\n await sessionData.create(this.csrfToken || '');\n await this.redirectAfterSignIn();\n this.#setCreatedActiveSession(session);\n this.#emit();\n } catch (error) {\n console.error('[TernSecureAuth] Error creating active session:', error);\n }\n };\n\n public initialize(options: TernSecureAuthOptions): Promise<void> {\n this._initialize(options);\n return Promise.resolve();\n }\n\n public static create(options: TernSecureAuthOptions): TernSecureAuth {\n const instance = this.getorCreateInstance();\n instance.initialize(options);\n return instance;\n }\n\n _initialize = (options: TernSecureAuthOptions): void => {\n this.#options = this.#initOptions(options);\n try {\n if (!this.#options.ternSecureConfig) {\n throw new Error('TernSecureConfig is required to initialize TernSecureAuth');\n }\n\n this.initializeFirebaseApp(this.#options.ternSecureConfig);\n\n this.signIn = new SignIn(this.auth, this.csrfToken);\n this.signUp = new SignUp(this.auth);\n\n this.#setStatus('ready');\n } catch (error) {\n this.error = error as Error;\n this.#setStatus('error');\n throw error;\n }\n };\n\n public constructUrlWithAuthRedirect = (to: string): string => {\n const baseUrl = window.location.origin;\n const url = new URL(to, baseUrl);\n\n if (url.origin === window.location.origin) {\n return url.href;\n }\n\n return url.toString();\n };\n\n #buildUrl = (key: 'signInUrl' | 'signUpUrl', options: RedirectOptions): string => {\n if (!key || !this.isReady) {\n return '';\n }\n\n const baseUrlConfig = key === 'signInUrl' ? this.#options.signInUrl : this.#options.signUpUrl;\n const defaultPagePath = key === 'signInUrl' ? '/sign-in' : '/sign-up';\n const base = baseUrlConfig || defaultPagePath;\n\n let effectiveRedirectUrl: string | null | undefined;\n\n // Priority 1: Get redirect URL from options (signInForceRedirectUrl or signUpForceRedirectUrl)\n if (key === 'signInUrl' && 'signInForceRedirectUrl' in options) {\n effectiveRedirectUrl = options.signInForceRedirectUrl;\n } else if (key === 'signUpUrl' && 'signUpForceRedirectUrl' in options) {\n effectiveRedirectUrl = options.signUpForceRedirectUrl;\n }\n\n // Priority 2: If no force redirect from options, check 'redirect' param in current URL (only in browser)\n if (!effectiveRedirectUrl && inBrowser()) {\n const currentUrlParams = new URLSearchParams(window.location.search);\n const existingRedirectParam = currentUrlParams.get('redirect_url');\n if (existingRedirectParam) {\n effectiveRedirectUrl = existingRedirectParam;\n }\n }\n\n // Priority 3: If still no redirect URL, fallback to current page's full path (only in browser)\n // This ensures that if the call originates from a page, it attempts to redirect back there by default.\n if (!effectiveRedirectUrl && inBrowser()) {\n effectiveRedirectUrl =\n window.location.pathname + window.location.search + window.location.hash;\n }\n\n if (effectiveRedirectUrl && inBrowser()) {\n let signInPagePath: string | undefined;\n try {\n signInPagePath = this.#options.signInUrl\n ? new URL(this.#options.signInUrl, window.location.origin).pathname\n : defaultPagePath;\n } catch {\n signInPagePath = defaultPagePath;\n }\n\n let signUpPagePath: string | undefined;\n try {\n signUpPagePath = this.#options.signUpUrl\n ? new URL(this.#options.signUpUrl, window.location.origin).pathname\n : key === 'signUpUrl'\n ? defaultPagePath\n : '/sign-in';\n } catch {\n signUpPagePath = key === 'signUpUrl' ? defaultPagePath : '/sign-in';\n }\n\n const redirectTargetObj = new URL(effectiveRedirectUrl, window.location.origin);\n\n if (\n redirectTargetObj.pathname === signInPagePath ||\n redirectTargetObj.pathname === signUpPagePath\n ) {\n // If the intended redirect path is the sign-in or sign-up page itself,\n // change the redirect target to the application root ('/').\n effectiveRedirectUrl = '/';\n }\n }\n\n const paramsForBuildUrl: Parameters<typeof buildURL>[0] = {\n base,\n searchParams: new URLSearchParams(),\n };\n\n if (effectiveRedirectUrl) {\n // Check if a redirect URL was determined\n if (inBrowser()) {\n const absoluteRedirectUrl = new URL(effectiveRedirectUrl, window.location.origin).href;\n paramsForBuildUrl.searchParams?.set('redirect_url', absoluteRedirectUrl);\n } else {\n // If not in browser, use the effectiveRedirectUrl as is.\n // This assumes it's either absolute or a path the server can interpret.\n paramsForBuildUrl.searchParams?.set('redirect_url', effectiveRedirectUrl);\n }\n }\n\n const constructedUrl = buildURL(paramsForBuildUrl, {\n stringify: true,\n skipOrigin: false,\n });\n\n if (typeof constructedUrl !== 'string') {\n console.error(\n '[TernSecure] Error: buildURL did not return a string as expected. Falling back to base URL.',\n );\n if (inBrowser()) {\n try {\n return new URL(base, window.location.origin).href;\n } catch {\n return base;\n }\n }\n return base;\n }\n\n return this.constructUrlWithAuthRedirect(constructedUrl);\n };\n\n #constructAfterSignInUrl = (): string => {\n if (!inBrowser()) {\n return '/';\n }\n\n let redirectPath: string | null | undefined = undefined;\n const defaultRedirectPath = '/';\n\n // Priority 1: Check for signInForceRedirectUrl from instance options\n if (this.#options.signInForceRedirectUrl) {\n redirectPath = this.#options.signInForceRedirectUrl;\n }\n\n // Priority 2: If no force redirect, check 'redirect' param in current URL\n if (!redirectPath) {\n const urlParams = new URLSearchParams(window.location.search);\n const redirectPathFromParams = urlParams.get('redirect_url');\n if (redirectPathFromParams) {\n redirectPath = redirectPathFromParams;\n }\n }\n\n // Priority 3: Fallback to default path\n if (!redirectPath) {\n redirectPath = defaultRedirectPath;\n }\n\n const currentPath = window.location.pathname;\n\n if (hasRedirectLoop(currentPath, redirectPath)) {\n //console.warn('[TernSecure] Redirect loop detected. Redirecting to default path.');\n return defaultRedirectPath;\n }\n\n return this.constructUrlWithAuthRedirect(redirectPath);\n };\n\n #constructAfterSignOutUrl = (): string => {\n if (!this.#options.afterSignOutUrl) {\n return '/';\n }\n return this.constructUrlWithAuthRedirect(this.#options.afterSignOutUrl);\n };\n\n public redirectToSignIn = async (options?: SignInRedirectOptions): Promise<unknown> => {\n if (inBrowser()) {\n const url = this.constructSignInUrl(options);\n window.location.href = url;\n }\n return;\n };\n\n public redirectToSignUp = async (options?: SignUpRedirectOptions): Promise<unknown> => {\n if (inBrowser()) {\n const redirectUrl = this.constructSignUpUrl();\n window.location.href = redirectUrl;\n }\n return;\n };\n\n redirectAfterSignIn = async (): Promise<void> => {\n if (inBrowser()) {\n const destinationUrl = this.#constructAfterSignInUrl();\n window.location.href = destinationUrl;\n }\n };\n\n redirectAfterSignUp = (): void => {\n throw new Error('redirectAfterSignUp is not implemented yet');\n };\n\n public constructSignInUrl = (options?: SignInRedirectOptions): string => {\n return this.#buildUrl('signInUrl', { ...options });\n };\n\n public constructSignUpUrl = (options?: SignUpRedirectOptions): string => {\n return this.#buildUrl('signUpUrl', { ...options });\n };\n\n __internal_setCountry = (country: string | null) => {\n if (!this.__internal_country) {\n this.__internal_country = country;\n }\n };\n\n #initOptions = (options: TernSecureAuthOptions): TernSecureAuthOptions => {\n return {\n ...options,\n };\n };\n\n #emit = (): void => {\n for (const listener of this.#listeners) {\n listener({\n user: this.user,\n session: this.signedInSession,\n });\n }\n };\n\n #setStatus(newStatus: TernSecureAuthStatus): void {\n if (this.#status !== newStatus) {\n this.#status = newStatus;\n this.#publicEventBus.emit(ternEvents.Status, this.#status);\n\n if (newStatus === 'ready') {\n this.#publicEventBus.emit(ternEvents.Status, 'ready');\n }\n }\n }\n\n #setCreatedActiveSession = (session: TernSecureUser | null) => {\n this.user = session;\n };\n\n #setPersistence = () => {\n const persistenceType = this.#options.persistence;\n\n switch (persistenceType) {\n case 'browserCookie':\n return inMemoryPersistence;\n case 'session':\n return browserSessionPersistence;\n case 'local':\n return browserLocalPersistence;\n case 'none':\n default:\n return inMemoryPersistence;\n }\n };\n\n #emulatorHost = (): string | undefined => {\n if (typeof process === 'undefined') return undefined;\n return process.env.FIREBASE_AUTH_EMULATOR_HOST;\n };\n\n #configureEmulator = (): void => {\n const host = this.#emulatorHost();\n const isDev = this.#instanceType === 'development';\n const shouldUseEmulator = isDev && !!host;\n if (!shouldUseEmulator || !host) {\n return;\n }\n\n const emulatorUrl = host.startsWith('http') ? host : `http://${host}`;\n\n try {\n //(this.auth as unknown as any)._canInitEmulator = true;\n connectAuthEmulator(this.auth, emulatorUrl, { disableWarnings: true });\n console.warn(`[TernSecure] Firebase Auth Emulator connected at ${emulatorUrl}`);\n } catch (error) {\n console.error('[TernSecure] Error connecting to Firebase Auth Emulator:', error);\n }\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAwC;AACxC,6BAAmD;AACnD,iBAA4B;AAC5B,mBAAgC;AA2BhC,iBAAuC;AAEvC,kBAUO;AACP,2BAAiC;AAEjC,qBAAgE;AAChE,sBAA2E;AAC3E,uBAA0C;AAC1C,6BAAoD;AACpD,oBAAiC;AACjC,uBAAoC;AAE7B,SAAS,YAAqB;AACnC,SAAO,OAAO,WAAW;AAC3B;AAOO,MAAM,eAAkD;AAAA,EAC7D,OAAc,UAAkB;AAAA,EAChC,OAAc,cAA2B;AAAA,IACvC,MAAM;AAAA,IACN,SAAS;AAAA,IACT,aAAa,QAAQ,IAAI,YAAY;AAAA,EACvC;AAAA,EACA,OAAe,WAAkC;AAAA,EACzC,eAAsC;AAAA,EACtC,kBAA0C;AAAA,EAC1C;AAAA,EACA,uBAA4C;AAAA,EAC5C;AAAA,EACA;AAAA,EACD,YAAY;AAAA,EACZ,QAAsB;AAAA,EACtB,OAA0C;AAAA,EAC1C;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAA6C;AAAA,EAC7C,aAA6D,CAAC;AAAA,EAC9D,WAAkC,CAAC;AAAA,EACnC;AAAA,EACA;AAAA,EACA,sBAAkB,+CAAuB;AAAA,EAEzC;AAAA,EACA;AAAA,EACA;AAAA,EAEA,IAAI,UAAmB;AACrB,WAAO,KAAK,WAAW;AAAA,EACzB;AAAA,EAEA,IAAI,SAA4C;AAC9C,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,UAAkB;AACpB,WAAO,eAAe;AAAA,EACxB;AAAA,EAEA,IAAI,YAAY,UAAuB;AACrC,mBAAe,cAAc;AAAA,EAC/B;AAAA,EAEA,IAAI,cAA2B;AAC7B,WAAO,eAAe;AAAA,EACxB;AAAA,EAEA,IAAI,uBAAgC;AAClC,WAAO,KAAK,SAAS,wBAAwB;AAAA,EAC/C;AAAA,EAEA,IAAI,SAAiB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,SAAiB;AACnB,QAAI,UAAU,GAAG;AACf,YAAM,2BAAuB;AAAA,YAC3B,8BAAgB,KAAK,SAAS,IAAI,IAAI,OAAO,SAAS,IAAI,CAAC;AAAA,MAC7D;AACA,UAAI,KAAK,kBAAkB,cAAc;AACvC,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,eAAe;AACjB,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,YAAY,SAAiC;AA3ItD;AA4II,SAAK,WAAU,wCAAS,qBAAT,mBAA2B;AAC1C,SAAK,WAAU,mCAAS,WAAU;AAClC,SAAK,gBAAiB,QAAQ,IAAI,YAA6B;AAE/D,SAAK,iBAAa,4CAAoB;AAAA,MACpC,QAAQ,KAAK;AAAA,MACb,QAAQ,mCAAS;AAAA,MACjB,cAAc,KAAK;AAAA,IACrB,CAAC;AAED,SAAK,gBAAgB,KAAK,kCAAW,QAAQ,SAAS;AACtD,mCAAe,aAAa;AAAA,EAC9B;AAAA,EAEO,eAAe,MAAiB,KAAK;AAAA;AAAA;AAAA;AAAA,EAK5C,MAAa,cAAkD;AAC7D,QAAI,CAAC,KAAK,oBAAoB;AAC5B,YAAM,IAAI,MAAM,qCAAqC;AAAA,IACvD;AAEA,WAAO,KAAK,mBAAmB,YAAY;AAAA,EAC7C;AAAA,EAEO,WAAW,WAA0B;AAC1C,SAAK,YAAY;AAAA,EACnB;AAAA,EAEO,oBAAmD;AACxD,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,oBACL,KAC0B;AAC1B,WAAO,KAAK,SAAS,GAAG;AAAA,EAC1B;AAAA,EAEO,0BAA2D;AAChE,WAAO,OAAO,OAAO,EAAE,GAAG,KAAK,SAAS,CAAC;AAAA,EAC3C;AAAA,EAEA,OAAO,oBAAoB,SAAiD;AAC1E,QAAI,CAAC,KAAK,UAAU;AAClB,WAAK,WAAW,IAAI,eAAe,OAAO;AAAA,IAC5C;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,OAAO,gBAAgB;AACrB,QAAI,eAAe,UAAU;AAC3B,UAAI,eAAe,SAAS,sBAAsB;AAChD,uBAAe,SAAS,qBAAqB;AAC7C,uBAAe,SAAS,uBAAuB;AAAA,MACjD;AACA,qBAAe,WAAW;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,OAAc,WAAW,SAAgD;AACvE,UAAM,WAAW,KAAK,oBAAoB,OAAO;AACjD,aAAS,YAAY,OAAO;AAC5B,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,CAAC,YAAmD;AAChE,SAAK,WAAW,KAAK,aAAa,OAAO;AAEzC,QAAI;AACF,UAAI,CAAC,KAAK,SAAS,kBAAkB;AACnC,cAAM,IAAI,MAAM,2DAA2D;AAAA,MAC7E;AAEA,UAAI,CAAC,KAAK,SAAS,QAAQ;AACzB,cAAM,IAAI,MAAM,iDAAiD;AAAA,MACnE;AAEA,WAAK,sBAAsB,KAAK,SAAS,gBAAgB;AAEzD,YAAM,6BAA6B,KAAK,SAAS,gBAAgB;AAEjE,UAAI,CAAC,4BAA4B;AAC/B,aAAK,uBAAuB,KAAK,sBAAsB;AAAA,MACzD;AAEA,WAAK,qBAAqB,IAAI,kCAAkB;AAChD,WAAK,YAAY,KAAK,mBAAmB,aAAa;AAEtD,WAAK,yBAAqB,wCAAwB;AAElD,WAAK,SAAS,IAAI,uBAAO,KAAK,MAAM,KAAK,SAAS;AAClD,WAAK,SAAS,IAAI,uBAAO,KAAK,IAAI;AAElC,6BAAS,GAAG,qBAAO,gBAAgB,MAAM;AACvC,aAAK,yBAAyB,KAAK,QAAQ,IAAI;AAC/C,aAAK,MAAM;AAAA,MACb,CAAC;AAED,WAAK,WAAW,OAAO;AACvB,WAAK,gBAAgB,KAAK,kCAAW,QAAQ,OAAO;AAEpD,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,QAAQ;AACb,WAAK,WAAW,OAAO;AACvB,WAAK,gBAAgB,KAAK,kCAAW,QAAQ,OAAO;AACpD,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,sBAAsB,QAA0B;AACtD,UAAM,UAAU,OAAO,WAAW;AAClC,SAAK,wBAAoB,oBAAQ,EAAE,WAAW,QAAI,0BAAc,QAAQ,OAAO,QAAI,oBAAQ,EAAE,CAAC;AAE9F,UAAM,cAAc,KAAK,gBAAgB;AACzC,UAAM,WAAO,4BAAe,KAAK,mBAAmB;AAAA,MAClD;AAAA,IACF,CAAC;AAED,SAAK,OAAO;AAEZ,QAAI,OAAO,UAAU;AACnB,WAAK,KAAK,WAAW,OAAO;AAAA,IAC9B;AAEA,SAAK,mBAAmB;AAExB,+CAAiB,KAAK,iBAAiB;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,MAAM;AArRrB;AAsRI,UAAM,mBAAkB,UAAK,uBAAL,mBAAyB;AACjD,UAAM,gBAAY,sCAAoB,mBAAmB,IAAI;AAC7D,SAAK,OAAO;AACZ,SAAK,MAAM;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAMA,wBAAwB,MAAM;AAhShC;AAiSI,eAAK,uBAAL,mBACI,uBACD,KAAK,qBAAmB;AACvB,YAAM,EAAE,MAAM,IAAI;AAClB,YAAM,gBAAY,sCAAoB,SAAS,IAAI;AACnD,WAAK,OAAO;AACZ,WAAK,MAAM;AAAA,IACb,GACC,MAAM,WAAS;AACd,cAAQ;AAAA,QACN;AAAA,QACA;AAAA,MACF;AACA,WAAK,OAAO;AACZ,WAAK,MAAM;AAAA,IACb;AAAA,EACJ;AAAA,EAEO,UAAmB,OAAO,YAA6B;AAC5D,UAAM,eAAc,mCAAS,gBAAe,KAAK,0BAA0B;AAC3E,QAAI,mCAAS,iBAAiB;AAC5B,YAAM,QAAQ,gBAAgB;AAAA,IAChC;AAEA,UAAM,KAAK,KAAK,QAAQ;AAExB,QAAI,mCAAS,gBAAgB;AAC3B,YAAM,QAAQ,eAAe;AAAA,IAC/B;AACA,QAAI,UAAU,GAAG;AACf,aAAO,SAAS,OAAO;AAAA,IACzB;AACA,2BAAS,KAAK,qBAAO,aAAa,IAAI;AACtC,2BAAS,KAAK,qBAAO,aAAa,EAAE,OAAO,KAAK,CAAC;AACjD,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,IAAI,iBAAyC;AAC3C,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,mBAA+B;AACrC,KAAC,YAAY;AACX,YAAM,KAAK,KAAK,eAAe;AAC/B,YAAM,OAAO,KAAK,KAAK;AACvB,WAAK,eAAe;AACpB,WAAK,OAAO;AACZ,YAAM,KAAK,qBAAqB;AAChC,WAAK,MAAM;AAAA,IACb,GAAG;AAGH,WAAO,MAAM;AAAA,IAEb;AAAA,EACF;AAAA,EAEQ,wBAAoC;AAC1C,eAAO,gCAAmB,KAAK,MAAM,OAAO,SAAgC;AAC1E,YAAM,KAAK,KAAK,eAAe;AAC/B,WAAK,eAAe;AACpB,WAAK,OAAO;AACZ,YAAM,KAAK,qBAAqB;AAEhC,WAAK,MAAM;AAAA,IACb,CAAC;AAAA,EACH;AAAA,EAEQ,oBAAgC;AACtC,eAAO,8BAAiB,KAAK,MAAM,OAAO,SAAgC;AACxE,YAAM,KAAK,KAAK,eAAe;AAC/B,WAAK,eAAe;AACpB,WAAK,OAAO;AACZ,YAAM,KAAK,qBAAqB;AAEhC,WAAK,MAAM;AAAA,IACb,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,aAAqC;AACjD,UAAM,KAAK,KAAK,eAAe;AAC/B,QAAI,CAAC,KAAK,KAAK,aAAa;AAC1B,aAAO;AAAA,IACT;AACA,eAAO,wBAAW,KAAK,KAAK,WAAW;AAAA,EACzC;AAAA,EAEO,mBAAmB,UAAyC;AACjE,eAAO,gCAAmB,KAAK,MAAM,QAAQ;AAAA,EAC/C;AAAA,EAEO,iBAAiB,UAAyC;AAC/D,eAAO,8BAAiB,KAAK,MAAM,QAAQ;AAAA,EAC7C;AAAA,EAEA,MAAc,uBAAsC;AAClD,QAAI,CAAC,KAAK,cAAc;AACtB,WAAK,kBAAkB;AACvB;AAAA,IACF;AAEA,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,aAAa,iBAAiB;AACrD,WAAK,kBAAkB;AAAA,QACrB,QAAQ;AAAA,QACR,OAAO,IAAI;AAAA,QACX,QAAQ,IAAI;AAAA,QACZ,cAAc,IAAI;AAAA,QAClB,gBAAgB,IAAI;AAAA,QACpB,UAAU,IAAI;AAAA,QACd,gBAAgB,IAAI,kBAAkB;AAAA,QACtC,oBAAoB,IAAI;AAAA,MAC1B;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,4CAA4C,KAAK;AAC/D,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,MAAa,sBAAsD;AACjE,QAAI;AACF,YAAM,SAAS,UAAM,+BAAkB,KAAK,IAAI;AAChD,UAAI,QAAQ;AACV,eAAO;AAAA,UACL,QAAQ;AAAA,UACR,MAAM,OAAO;AAAA,QACf;AAAA,MACF;AACA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,gBAAY,uCAAwB,KAAK;AAC/C,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,SAAS,UAAU;AAAA,QACnB,OAAO,UAAU;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAAA,EAEO,oBAAoB,YAA0B;AACnD,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AAAA,EAEO,cAAc,CAAC,aAAoD;AACxE,SAAK,WAAW,KAAK,QAAQ;AAC7B,QAAI,KAAK,cAAc;AACrB,eAAS;AAAA,QACP,MAAM,KAAK;AAAA,QACX,SAAS,KAAK;AAAA,MAChB,CAAC;AAAA,IACH;AAEA,UAAM,cAAc,MAAM;AACxB,WAAK,aAAa,KAAK,WAAW,OAAO,OAAK,MAAM,QAAQ;AAAA,IAC9D;AACA,WAAO;AAAA,EACT;AAAA,EAEO,KAAoC,IAAI,SAAS;AACtD,SAAK,gBAAgB,GAAG,GAAG,IAAI;AAAA,EACjC;AAAA,EAEO,MAAsC,IAAI,SAAS;AACxD,SAAK,gBAAgB,IAAI,GAAG,IAAI;AAAA,EAClC;AAAA,EAEO,sBAA2C,OAAO;AAAA,IACvD;AAAA,IACA;AAAA,EACF,MAAqB;AACnB,QAAI;AACF,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,4CAA4C;AAAA,MAC9D;AACA,YAAM,gBAAgB,MAAM,QAAQ,iBAAiB;AACrD,YAAM,cAAc,IAAI,wBAAQ,aAAa;AAC7C,YAAM,YAAY,OAAO,KAAK,aAAa,EAAE;AAC7C,YAAM,KAAK,oBAAoB;AAC/B,WAAK,yBAAyB,OAAO;AACrC,WAAK,MAAM;AAAA,IACb,SAAS,OAAO;AACd,cAAQ,MAAM,mDAAmD,KAAK;AAAA,IACxE;AAAA,EACF;AAAA,EAEO,WAAW,SAA+C;AAC/D,SAAK,YAAY,OAAO;AACxB,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA,EAEA,OAAc,OAAO,SAAgD;AACnE,UAAM,WAAW,KAAK,oBAAoB;AAC1C,aAAS,WAAW,OAAO;AAC3B,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,CAAC,YAAyC;AACtD,SAAK,WAAW,KAAK,aAAa,OAAO;AACzC,QAAI;AACF,UAAI,CAAC,KAAK,SAAS,kBAAkB;AACnC,cAAM,IAAI,MAAM,2DAA2D;AAAA,MAC7E;AAEA,WAAK,sBAAsB,KAAK,SAAS,gBAAgB;AAEzD,WAAK,SAAS,IAAI,uBAAO,KAAK,MAAM,KAAK,SAAS;AAClD,WAAK,SAAS,IAAI,uBAAO,KAAK,IAAI;AAElC,WAAK,WAAW,OAAO;AAAA,IACzB,SAAS,OAAO;AACd,WAAK,QAAQ;AACb,WAAK,WAAW,OAAO;AACvB,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEO,+BAA+B,CAAC,OAAuB;AAC5D,UAAM,UAAU,OAAO,SAAS;AAChC,UAAM,MAAM,IAAI,IAAI,IAAI,OAAO;AAE/B,QAAI,IAAI,WAAW,OAAO,SAAS,QAAQ;AACzC,aAAO,IAAI;AAAA,IACb;AAEA,WAAO,IAAI,SAAS;AAAA,EACtB;AAAA,EAEA,YAAY,CAAC,KAAgC,YAAqC;AApgBpF;AAqgBI,QAAI,CAAC,OAAO,CAAC,KAAK,SAAS;AACzB,aAAO;AAAA,IACT;AAEA,UAAM,gBAAgB,QAAQ,cAAc,KAAK,SAAS,YAAY,KAAK,SAAS;AACpF,UAAM,kBAAkB,QAAQ,cAAc,aAAa;AAC3D,UAAM,OAAO,iBAAiB;AAE9B,QAAI;AAGJ,QAAI,QAAQ,eAAe,4BAA4B,SAAS;AAC9D,6BAAuB,QAAQ;AAAA,IACjC,WAAW,QAAQ,eAAe,4BAA4B,SAAS;AACrE,6BAAuB,QAAQ;AAAA,IACjC;AAGA,QAAI,CAAC,wBAAwB,UAAU,GAAG;AACxC,YAAM,mBAAmB,IAAI,gBAAgB,OAAO,SAAS,MAAM;AACnE,YAAM,wBAAwB,iBAAiB,IAAI,cAAc;AACjE,UAAI,uBAAuB;AACzB,+BAAuB;AAAA,MACzB;AAAA,IACF;AAIA,QAAI,CAAC,wBAAwB,UAAU,GAAG;AACxC,6BACE,OAAO,SAAS,WAAW,OAAO,SAAS,SAAS,OAAO,SAAS;AAAA,IACxE;AAEA,QAAI,wBAAwB,UAAU,GAAG;AACvC,UAAI;AACJ,UAAI;AACF,yBAAiB,KAAK,SAAS,YAC3B,IAAI,IAAI,KAAK,SAAS,WAAW,OAAO,SAAS,MAAM,EAAE,WACzD;AAAA,MACN,QAAQ;AACN,yBAAiB;AAAA,MACnB;AAEA,UAAI;AACJ,UAAI;AACF,yBAAiB,KAAK,SAAS,YAC3B,IAAI,IAAI,KAAK,SAAS,WAAW,OAAO,SAAS,MAAM,EAAE,WACzD,QAAQ,cACN,kBACA;AAAA,MACR,QAAQ;AACN,yBAAiB,QAAQ,cAAc,kBAAkB;AAAA,MAC3D;AAEA,YAAM,oBAAoB,IAAI,IAAI,sBAAsB,OAAO,SAAS,MAAM;AAE9E,UACE,kBAAkB,aAAa,kBAC/B,kBAAkB,aAAa,gBAC/B;AAGA,+BAAuB;AAAA,MACzB;AAAA,IACF;AAEA,UAAM,oBAAoD;AAAA,MACxD;AAAA,MACA,cAAc,IAAI,gBAAgB;AAAA,IACpC;AAEA,QAAI,sBAAsB;AAExB,UAAI,UAAU,GAAG;AACf,cAAM,sBAAsB,IAAI,IAAI,sBAAsB,OAAO,SAAS,MAAM,EAAE;AAClF,gCAAkB,iBAAlB,mBAAgC,IAAI,gBAAgB;AAAA,MACtD,OAAO;AAGL,gCAAkB,iBAAlB,mBAAgC,IAAI,gBAAgB;AAAA,MACtD;AAAA,IACF;AAEA,UAAM,qBAAiB,2BAAS,mBAAmB;AAAA,MACjD,WAAW;AAAA,MACX,YAAY;AAAA,IACd,CAAC;AAED,QAAI,OAAO,mBAAmB,UAAU;AACtC,cAAQ;AAAA,QACN;AAAA,MACF;AACA,UAAI,UAAU,GAAG;AACf,YAAI;AACF,iBAAO,IAAI,IAAI,MAAM,OAAO,SAAS,MAAM,EAAE;AAAA,QAC/C,QAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAEA,WAAO,KAAK,6BAA6B,cAAc;AAAA,EACzD;AAAA,EAEA,2BAA2B,MAAc;AACvC,QAAI,CAAC,UAAU,GAAG;AAChB,aAAO;AAAA,IACT;AAEA,QAAI,eAA0C;AAC9C,UAAM,sBAAsB;AAG5B,QAAI,KAAK,SAAS,wBAAwB;AACxC,qBAAe,KAAK,SAAS;AAAA,IAC/B;AAGA,QAAI,CAAC,cAAc;AACjB,YAAM,YAAY,IAAI,gBAAgB,OAAO,SAAS,MAAM;AAC5D,YAAM,yBAAyB,UAAU,IAAI,cAAc;AAC3D,UAAI,wBAAwB;AAC1B,uBAAe;AAAA,MACjB;AAAA,IACF;AAGA,QAAI,CAAC,cAAc;AACjB,qBAAe;AAAA,IACjB;AAEA,UAAM,cAAc,OAAO,SAAS;AAEpC,YAAI,kCAAgB,aAAa,YAAY,GAAG;AAE9C,aAAO;AAAA,IACT;AAEA,WAAO,KAAK,6BAA6B,YAAY;AAAA,EACvD;AAAA,EAEA,4BAA4B,MAAc;AACxC,QAAI,CAAC,KAAK,SAAS,iBAAiB;AAClC,aAAO;AAAA,IACT;AACA,WAAO,KAAK,6BAA6B,KAAK,SAAS,eAAe;AAAA,EACxE;AAAA,EAEO,mBAAmB,OAAO,YAAsD;AACrF,QAAI,UAAU,GAAG;AACf,YAAM,MAAM,KAAK,mBAAmB,OAAO;AAC3C,aAAO,SAAS,OAAO;AAAA,IACzB;AACA;AAAA,EACF;AAAA,EAEO,mBAAmB,OAAO,YAAsD;AACrF,QAAI,UAAU,GAAG;AACf,YAAM,cAAc,KAAK,mBAAmB;AAC5C,aAAO,SAAS,OAAO;AAAA,IACzB;AACA;AAAA,EACF;AAAA,EAEA,sBAAsB,YAA2B;AAC/C,QAAI,UAAU,GAAG;AACf,YAAM,iBAAiB,KAAK,yBAAyB;AACrD,aAAO,SAAS,OAAO;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,sBAAsB,MAAY;AAChC,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AAAA,EAEO,qBAAqB,CAAC,YAA4C;AACvE,WAAO,KAAK,UAAU,aAAa,EAAE,GAAG,QAAQ,CAAC;AAAA,EACnD;AAAA,EAEO,qBAAqB,CAAC,YAA4C;AACvE,WAAO,KAAK,UAAU,aAAa,EAAE,GAAG,QAAQ,CAAC;AAAA,EACnD;AAAA,EAEA,wBAAwB,CAAC,YAA2B;AAClD,QAAI,CAAC,KAAK,oBAAoB;AAC5B,WAAK,qBAAqB;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,eAAe,CAAC,YAA0D;AACxE,WAAO;AAAA,MACL,GAAG;AAAA,IACL;AAAA,EACF;AAAA,EAEA,QAAQ,MAAY;AAClB,eAAW,YAAY,KAAK,YAAY;AACtC,eAAS;AAAA,QACP,MAAM,KAAK;AAAA,QACX,SAAS,KAAK;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,WAAW,WAAuC;AAChD,QAAI,KAAK,YAAY,WAAW;AAC9B,WAAK,UAAU;AACf,WAAK,gBAAgB,KAAK,kCAAW,QAAQ,KAAK,OAAO;AAEzD,UAAI,cAAc,SAAS;AACzB,aAAK,gBAAgB,KAAK,kCAAW,QAAQ,OAAO;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,2BAA2B,CAAC,YAAmC;AAC7D,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,kBAAkB,MAAM;AACtB,UAAM,kBAAkB,KAAK,SAAS;AAEtC,YAAQ,iBAAiB;AAAA,MACvB,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AAAA,MACL;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA,EAEA,gBAAgB,MAA0B;AACxC,QAAI,OAAO,YAAY,YAAa,QAAO;AAC3C,WAAO,QAAQ,IAAI;AAAA,EACrB;AAAA,EAEA,qBAAqB,MAAY;AAC/B,UAAM,OAAO,KAAK,cAAc;AAChC,UAAM,QAAQ,KAAK,kBAAkB;AACrC,UAAM,oBAAoB,SAAS,CAAC,CAAC;AACrC,QAAI,CAAC,qBAAqB,CAAC,MAAM;AAC/B;AAAA,IACF;AAEA,UAAM,cAAc,KAAK,WAAW,MAAM,IAAI,OAAO,UAAU,IAAI;AAEnE,QAAI;AAEF,2CAAoB,KAAK,MAAM,aAAa,EAAE,iBAAiB,KAAK,CAAC;AACrE,cAAQ,KAAK,oDAAoD,WAAW,EAAE;AAAA,IAChF,SAAS,OAAO;AACd,cAAQ,MAAM,4DAA4D,KAAK;AAAA,IACjF;AAAA,EACF;AACF;","names":[]}
@@ -24,10 +24,11 @@ __export(events_exports, {
24
24
  module.exports = __toCommonJS(events_exports);
25
25
  var import_eventBus = require("@tern-secure/shared/eventBus");
26
26
  const events = {
27
- //UserChanged: "user:userChanged",
28
27
  UserSignOut: "user:userSignOut",
29
28
  SessionChanged: "session:sessionChanged",
30
- TokenRefreshed: "token:tokenRefreshed"
29
+ TokenRefreshed: "token:tokenRefreshed",
30
+ TokenUpdate: "token:tokenUpdate",
31
+ TokenJwt: "token:tokenJwt"
31
32
  };
32
33
  const eventBus = (0, import_eventBus.createEventBus)();
33
34
  // Annotate the CommonJS export names for ESM import in node:
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/instance/events.ts"],"sourcesContent":["import { createEventBus } from \"@tern-secure/shared/eventBus\";\n//import type { TernSecureUser } from \"@tern-secure/types\";\nimport type { IdTokenResult } from \"firebase/auth\";\n\nexport const events = {\n //UserChanged: \"user:userChanged\",\n UserSignOut: \"user:userSignOut\",\n SessionChanged: \"session:sessionChanged\",\n TokenRefreshed: \"token:tokenRefreshed\",\n} as const;\n\ntype TokenUpdatePayload = { token: IdTokenResult | null };\n\n\ntype InternalEvents = {\n //[events.UserChanged]: TernSecureUser | null;\n [events.UserSignOut]: null;\n [events.SessionChanged]: null;\n [events.TokenRefreshed]: TokenUpdatePayload;\n};\n\nexport const eventBus = createEventBus<InternalEvents>();\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAA+B;AAIxB,MAAM,SAAS;AAAA;AAAA,EAEpB,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,gBAAgB;AAClB;AAYO,MAAM,eAAW,gCAA+B;","names":[]}
1
+ {"version":3,"sources":["../../../src/instance/events.ts"],"sourcesContent":["import { createEventBus } from '@tern-secure/shared/eventBus';\nimport type { IdTokenResult } from '@tern-secure/types';\n\nexport const events = {\n UserSignOut: 'user:userSignOut',\n SessionChanged: 'session:sessionChanged',\n TokenRefreshed: 'token:tokenRefreshed',\n TokenUpdate: 'token:tokenUpdate',\n TokenJwt: 'token:tokenJwt',\n} as const;\n\ntype TokenUpdatePayload = { token: IdTokenResult | null };\ntype TokenJwt = { tokenType: 'idToken' | 'sessionToken' | 'refreshToken' | 'customToken', response: string };\n\ntype InternalEvents = {\n [events.UserSignOut]: null;\n [events.SessionChanged]: null;\n [events.TokenRefreshed]: TokenUpdatePayload;\n [events.TokenUpdate]: TokenUpdatePayload;\n [events.TokenJwt]: TokenJwt;\n};\n\nexport const eventBus = createEventBus<InternalEvents>();\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAA+B;AAGxB,MAAM,SAAS;AAAA,EACpB,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,UAAU;AACZ;AAaO,MAAM,eAAW,gCAA+B;","names":[]}
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var jwtClient_exports = {};
20
+ __export(jwtClient_exports, {
21
+ createClientFromJwt: () => createClientFromJwt,
22
+ updateClient: () => updateClient
23
+ });
24
+ module.exports = __toCommonJS(jwtClient_exports);
25
+ var import_jwt = require("../utils/jwt");
26
+ const createClientFromJwt = (jwtToken) => {
27
+ if (!jwtToken) {
28
+ return null;
29
+ }
30
+ const { decoded } = (0, import_jwt.decode)(jwtToken);
31
+ console.log("[TernAuth] Loaded user from JWT:", decoded);
32
+ return decoded;
33
+ };
34
+ const updateClient = (user, options) => {
35
+ try {
36
+ if (options.onUserUpdate) {
37
+ options.onUserUpdate(user);
38
+ }
39
+ if (user && options.onSessionUpdate) {
40
+ user.getIdTokenResult().then((tokenResult) => {
41
+ const session = {
42
+ status: "active",
43
+ token: tokenResult.token,
44
+ claims: tokenResult.claims,
45
+ issuedAtTime: tokenResult.issuedAtTime,
46
+ expirationTime: tokenResult.expirationTime,
47
+ authTime: tokenResult.authTime,
48
+ signInProvider: tokenResult.signInProvider || "unknown",
49
+ signInSecondFactor: tokenResult.signInSecondFactor
50
+ };
51
+ if (options.onSessionUpdate) {
52
+ options.onSessionUpdate(session);
53
+ }
54
+ }).catch((error) => {
55
+ console.error("[TernAuth] Error getting token result for session:", error);
56
+ if (options.onSessionUpdate) {
57
+ options.onSessionUpdate(null);
58
+ }
59
+ });
60
+ } else if (options.onSessionUpdate) {
61
+ options.onSessionUpdate(null);
62
+ }
63
+ } catch (error) {
64
+ console.error("[TernAuth] Error updating client:", error);
65
+ }
66
+ };
67
+ // Annotate the CommonJS export names for ESM import in node:
68
+ 0 && (module.exports = {
69
+ createClientFromJwt,
70
+ updateClient
71
+ });
72
+ //# sourceMappingURL=jwtClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/instance/jwtClient.ts"],"sourcesContent":["import type { DecodedIdToken, SignedInSession, TernSecureUser } from '@tern-secure/types';\n\nimport type { AuthCookieManager } from '../auth/AuthCookieManager';\nimport { decode } from '../utils/jwt';\n\n/**\n * Utility functions for loading user from JWT cookie and updating client state\n * This addresses the issue where user is undefined when client loads on page refresh\n */\n\nexport interface ClientUpdateOptions {\n authCookieManager: AuthCookieManager;\n onUserUpdate?: (user: TernSecureUser | null) => void;\n onSessionUpdate?: (session: SignedInSession | null) => void;\n}\n\n/**\n * Creates Firebase user from stored JWT token (ID token)\n * Since the token is already a Firebase ID token, we validate it and wait for auth state\n */\nconst createClientFromJwt = (jwtToken: string | null): DecodedIdToken | null => {\n if (!jwtToken) {\n return null;\n }\n\n const { decoded } = decode(jwtToken);\n\n console.log('[TernAuth] Loaded user from JWT:', decoded);\n\n return decoded;\n};\n\n/**\n * Updates client user state and triggers callbacks\n */\nconst updateClient = (\n user: TernSecureUser | null,\n options: Pick<ClientUpdateOptions, 'onUserUpdate' | 'onSessionUpdate'>,\n): void => {\n try {\n // Update user\n if (options.onUserUpdate) {\n options.onUserUpdate(user);\n }\n\n // Update session if user exists\n if (user && options.onSessionUpdate) {\n user\n .getIdTokenResult()\n .then(tokenResult => {\n const session: SignedInSession = {\n status: 'active',\n token: tokenResult.token,\n claims: tokenResult.claims,\n issuedAtTime: tokenResult.issuedAtTime,\n expirationTime: tokenResult.expirationTime,\n authTime: tokenResult.authTime,\n signInProvider: tokenResult.signInProvider || 'unknown',\n signInSecondFactor: tokenResult.signInSecondFactor,\n };\n if (options.onSessionUpdate) {\n options.onSessionUpdate(session);\n }\n })\n .catch(error => {\n console.error('[TernAuth] Error getting token result for session:', error);\n if (options.onSessionUpdate) {\n options.onSessionUpdate(null);\n }\n });\n } else if (options.onSessionUpdate) {\n options.onSessionUpdate(null);\n }\n } catch (error) {\n console.error('[TernAuth] Error updating client:', error);\n }\n};\n\nexport { createClientFromJwt, updateClient };\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,iBAAuB;AAiBvB,MAAM,sBAAsB,CAAC,aAAmD;AAC9E,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,QAAM,EAAE,QAAQ,QAAI,mBAAO,QAAQ;AAEnC,UAAQ,IAAI,oCAAoC,OAAO;AAEvD,SAAO;AACT;AAKA,MAAM,eAAe,CACnB,MACA,YACS;AACT,MAAI;AAEF,QAAI,QAAQ,cAAc;AACxB,cAAQ,aAAa,IAAI;AAAA,IAC3B;AAGA,QAAI,QAAQ,QAAQ,iBAAiB;AACnC,WACG,iBAAiB,EACjB,KAAK,iBAAe;AACnB,cAAM,UAA2B;AAAA,UAC/B,QAAQ;AAAA,UACR,OAAO,YAAY;AAAA,UACnB,QAAQ,YAAY;AAAA,UACpB,cAAc,YAAY;AAAA,UAC1B,gBAAgB,YAAY;AAAA,UAC5B,UAAU,YAAY;AAAA,UACtB,gBAAgB,YAAY,kBAAkB;AAAA,UAC9C,oBAAoB,YAAY;AAAA,QAClC;AACA,YAAI,QAAQ,iBAAiB;AAC3B,kBAAQ,gBAAgB,OAAO;AAAA,QACjC;AAAA,MACF,CAAC,EACA,MAAM,WAAS;AACd,gBAAQ,MAAM,sDAAsD,KAAK;AACzE,YAAI,QAAQ,iBAAiB;AAC3B,kBAAQ,gBAAgB,IAAI;AAAA,QAC9B;AAAA,MACF,CAAC;AAAA,IACL,WAAW,QAAQ,iBAAiB;AAClC,cAAQ,gBAAgB,IAAI;AAAA,IAC9B;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,qCAAqC,KAAK;AAAA,EAC1D;AACF;","names":[]}
@@ -101,6 +101,13 @@ class TernSecureBase {
101
101
  async basePost(params) {
102
102
  return TernSecureBase.basePost(params);
103
103
  }
104
+ /**
105
+ * Instance method to make GET requests
106
+ * This is a convenience method that sets the HTTP method to GET
107
+ */
108
+ async baseGet(params) {
109
+ return this.fetchFromCoreApi({ ...params, method: "GET" });
110
+ }
104
111
  /**
105
112
  * Protected instance method for making POST requests with specific path and body
106
113
  * This is designed to be used by child classes like SignIn
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/resources/Base.ts"],"sourcesContent":["import { isValidBrowserOnline } from '@tern-secure/shared/browser';\nimport type { TernSecureApiErrorJSON } from '@tern-secure/types';\n\nimport type { ApiRequestInit, ApiResponse, ApiResponseJSON } from '../instance/coreApiClient';\n//import { coreApiClient} from '../instance/coreApiClient';\nimport { TernSecureAPIResponseError, TernSecureRuntimeError } from './Error';\nimport type { AuthCookieManager, TernSecureAuth } from './internal';\n\nexport type HTTPMethod =\n | 'CONNECT'\n | 'DELETE'\n | 'GET'\n | 'HEAD'\n | 'OPTIONS'\n | 'PATCH'\n | 'POST'\n | 'PUT'\n | 'TRACE';\n\nexport type PostMutateParams = {\n action?: string | undefined;\n body?: any;\n method?: HTTPMethod | undefined;\n path?: string;\n};\n\nexport abstract class TernSecureBase {\n static ternsecure: TernSecureAuth;\n\n static get apiClient() {\n return TernSecureBase.ternsecure.getApiClient();\n }\n\n static get authCookieManager(): AuthCookieManager | undefined {\n return this.ternsecure.authCookieManager();\n }\n protected get authCookieManager(): AuthCookieManager | undefined {\n return TernSecureBase.authCookieManager;\n }\n\n /**\n * Core method to fetch data from API endpoints using coreApiClient\n * This method handles the complete request lifecycle including error handling\n */\n protected static async fetchFromCoreApi<J>(\n requestInit: ApiRequestInit,\n ): Promise<ApiResponseJSON<J> | null> {\n let apiResponse: ApiResponse<J>;\n try {\n apiResponse = await TernSecureBase.apiClient.request<J>(requestInit, { timeoutMs: 10000 });\n } catch (error) {\n if (this.shouldRethrowofflineNetworkError()) {\n throw new TernSecureRuntimeError((error as Error)?.message || String(error), {\n code: 'OFFLINE_NETWORK_ERROR',\n });\n } else if (!isValidBrowserOnline()) {\n console.warn(error);\n return null;\n } else {\n throw error;\n }\n }\n\n const { payload, status, statusText, headers } = apiResponse;\n\n if (headers) {\n const country = headers.get('x-country');\n this.ternsecure.__internal_setCountry(country ? country.toLowerCase() : null);\n }\n\n if (status >= 200 && status <= 299) {\n return payload;\n }\n\n if (status >= 400) {\n const errors = payload?.errors as TernSecureApiErrorJSON[];\n const message = errors?.[0]?.message;\n\n const apiResponseOptions: ConstructorParameters<typeof TernSecureAPIResponseError>[1] = {\n data: errors,\n status,\n };\n if (status === 429 && headers) {\n const retryAfter = headers.get('retry-After');\n if (retryAfter) {\n const value = parseInt(retryAfter, 10);\n if (!isNaN(value)) {\n apiResponseOptions.retryAfter = value;\n }\n }\n }\n\n throw new TernSecureAPIResponseError(message || statusText, apiResponseOptions);\n }\n\n return null;\n }\n\n /**\n * Convenience method for making POST requests\n */\n static async basePost(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi({ ...params, method: 'POST' });\n }\n\n /**\n * Instance method to fetch data from API endpoints\n */\n protected async fetchFromCoreApi(\n requestInit: ApiRequestInit,\n ): Promise<ApiResponseJSON<any> | null> {\n return TernSecureBase.fetchFromCoreApi(requestInit);\n }\n\n /**\n * Instance method for making POST requests\n */\n protected async basePost(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return TernSecureBase.basePost(params);\n }\n\n /**\n * Protected instance method for making POST requests with specific path and body\n * This is designed to be used by child classes like SignIn\n */\n protected async _post(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return this.basePost({\n path: params.path,\n body: params.body,\n });\n }\n\n static async makeApiRequest(requestInit: ApiRequestInit): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi(requestInit);\n }\n\n protected async makeApiRequest(\n requestInit: ApiRequestInit,\n ): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi(requestInit);\n }\n\n private static shouldRethrowofflineNetworkError(): boolean {\n const experimental = TernSecureBase.ternsecure?._internal_getOption?.('experimental');\n return experimental?.rethrowOfflineNetworkErrors || false;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAqC;AAKrC,mBAAmE;AAqB5D,MAAe,eAAe;AAAA,EACnC,OAAO;AAAA,EAEP,WAAW,YAAY;AACrB,WAAO,eAAe,WAAW,aAAa;AAAA,EAChD;AAAA,EAEA,WAAW,oBAAmD;AAC5D,WAAO,KAAK,WAAW,kBAAkB;AAAA,EAC3C;AAAA,EACA,IAAc,oBAAmD;AAC/D,WAAO,eAAe;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAuB,iBACrB,aACoC;AA9CxC;AA+CI,QAAI;AACJ,QAAI;AACF,oBAAc,MAAM,eAAe,UAAU,QAAW,aAAa,EAAE,WAAW,IAAM,CAAC;AAAA,IAC3F,SAAS,OAAO;AACd,UAAI,KAAK,iCAAiC,GAAG;AAC3C,cAAM,IAAI,qCAAwB,+BAAiB,YAAW,OAAO,KAAK,GAAG;AAAA,UAC3E,MAAM;AAAA,QACR,CAAC;AAAA,MACH,WAAW,KAAC,qCAAqB,GAAG;AAClC,gBAAQ,KAAK,KAAK;AAClB,eAAO;AAAA,MACT,OAAO;AACL,cAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,EAAE,SAAS,QAAQ,YAAY,QAAQ,IAAI;AAEjD,QAAI,SAAS;AACX,YAAM,UAAU,QAAQ,IAAI,WAAW;AACvC,WAAK,WAAW,sBAAsB,UAAU,QAAQ,YAAY,IAAI,IAAI;AAAA,IAC9E;AAEA,QAAI,UAAU,OAAO,UAAU,KAAK;AAClC,aAAO;AAAA,IACT;AAEA,QAAI,UAAU,KAAK;AACjB,YAAM,SAAS,mCAAS;AACxB,YAAM,WAAU,sCAAS,OAAT,mBAAa;AAE7B,YAAM,qBAAkF;AAAA,QACtF,MAAM;AAAA,QACN;AAAA,MACF;AACA,UAAI,WAAW,OAAO,SAAS;AAC7B,cAAM,aAAa,QAAQ,IAAI,aAAa;AAC5C,YAAI,YAAY;AACd,gBAAM,QAAQ,SAAS,YAAY,EAAE;AACrC,cAAI,CAAC,MAAM,KAAK,GAAG;AACjB,+BAAmB,aAAa;AAAA,UAClC;AAAA,QACF;AAAA,MACF;AAEA,YAAM,IAAI,wCAA2B,WAAW,YAAY,kBAAkB;AAAA,IAChF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,SAAS,QAAgE;AACpF,WAAO,KAAK,iBAAiB,EAAE,GAAG,QAAQ,QAAQ,OAAO,CAAC;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,iBACd,aACsC;AACtC,WAAO,eAAe,iBAAiB,WAAW;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,SAAS,QAAgE;AACvF,WAAO,eAAe,SAAS,MAAM;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAgB,MAAM,QAAgE;AACpF,WAAO,KAAK,SAAS;AAAA,MACnB,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,IACf,CAAC;AAAA,EACH;AAAA,EAEA,aAAa,eAAe,aAAmE;AAC7F,WAAO,KAAK,iBAAiB,WAAW;AAAA,EAC1C;AAAA,EAEA,MAAgB,eACd,aACsC;AACtC,WAAO,KAAK,iBAAiB,WAAW;AAAA,EAC1C;AAAA,EAEA,OAAe,mCAA4C;AA9I7D;AA+II,UAAM,gBAAe,0BAAe,eAAf,mBAA2B,wBAA3B,4BAAiD;AACtE,YAAO,6CAAc,gCAA+B;AAAA,EACtD;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/resources/Base.ts"],"sourcesContent":["import { isValidBrowserOnline } from '@tern-secure/shared/browser';\nimport type { TernSecureApiErrorJSON } from '@tern-secure/types';\n\nimport type { ApiRequestInit, ApiResponse, ApiResponseJSON } from '../instance/coreApiClient';\n//import { coreApiClient} from '../instance/coreApiClient';\nimport { TernSecureAPIResponseError, TernSecureRuntimeError } from './Error';\nimport type { AuthCookieManager, TernSecureAuth } from './internal';\n\nexport type HTTPMethod =\n | 'CONNECT'\n | 'DELETE'\n | 'GET'\n | 'HEAD'\n | 'OPTIONS'\n | 'PATCH'\n | 'POST'\n | 'PUT'\n | 'TRACE';\n\nexport type PostMutateParams = {\n action?: string | undefined;\n body?: any;\n method?: HTTPMethod | undefined;\n path?: string;\n search?: ConstructorParameters<typeof URLSearchParams>[0];\n};\n\nexport abstract class TernSecureBase {\n static ternsecure: TernSecureAuth;\n\n static get apiClient() {\n return TernSecureBase.ternsecure.getApiClient();\n }\n\n static get authCookieManager(): AuthCookieManager | undefined {\n return this.ternsecure.authCookieManager();\n }\n protected get authCookieManager(): AuthCookieManager | undefined {\n return TernSecureBase.authCookieManager;\n }\n\n /**\n * Core method to fetch data from API endpoints using coreApiClient\n * This method handles the complete request lifecycle including error handling\n */\n protected static async fetchFromCoreApi<J>(\n requestInit: ApiRequestInit,\n ): Promise<ApiResponseJSON<J> | null> {\n let apiResponse: ApiResponse<J>;\n try {\n apiResponse = await TernSecureBase.apiClient.request<J>(requestInit, { timeoutMs: 10000 });\n } catch (error) {\n if (this.shouldRethrowofflineNetworkError()) {\n throw new TernSecureRuntimeError((error as Error)?.message || String(error), {\n code: 'OFFLINE_NETWORK_ERROR',\n });\n } else if (!isValidBrowserOnline()) {\n console.warn(error);\n return null;\n } else {\n throw error;\n }\n }\n\n const { payload, status, statusText, headers } = apiResponse;\n\n if (headers) {\n const country = headers.get('x-country');\n this.ternsecure.__internal_setCountry(country ? country.toLowerCase() : null);\n }\n\n if (status >= 200 && status <= 299) {\n return payload;\n }\n\n if (status >= 400) {\n const errors = payload?.errors as TernSecureApiErrorJSON[];\n const message = errors?.[0]?.message;\n\n const apiResponseOptions: ConstructorParameters<typeof TernSecureAPIResponseError>[1] = {\n data: errors,\n status,\n };\n if (status === 429 && headers) {\n const retryAfter = headers.get('retry-After');\n if (retryAfter) {\n const value = parseInt(retryAfter, 10);\n if (!isNaN(value)) {\n apiResponseOptions.retryAfter = value;\n }\n }\n }\n\n throw new TernSecureAPIResponseError(message || statusText, apiResponseOptions);\n }\n\n return null;\n }\n\n /**\n * Convenience method for making POST requests\n */\n static async basePost(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi({ ...params, method: 'POST' });\n }\n\n /**\n * Instance method to fetch data from API endpoints\n */\n protected async fetchFromCoreApi(\n requestInit: ApiRequestInit,\n ): Promise<ApiResponseJSON<any> | null> {\n return TernSecureBase.fetchFromCoreApi(requestInit);\n }\n\n /**\n * Instance method for making POST requests\n */\n protected async basePost(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return TernSecureBase.basePost(params);\n }\n\n /**\n * Instance method to make GET requests\n * This is a convenience method that sets the HTTP method to GET\n */\n protected async baseGet(params: Omit<PostMutateParams, 'method'>): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi({ ...params, method: 'GET' });\n }\n\n /**\n * Protected instance method for making POST requests with specific path and body\n * This is designed to be used by child classes like SignIn\n */\n protected async _post(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return this.basePost({\n path: params.path,\n body: params.body,\n });\n }\n\n static async makeApiRequest(requestInit: ApiRequestInit): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi(requestInit);\n }\n\n protected async makeApiRequest(\n requestInit: ApiRequestInit,\n ): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi(requestInit);\n }\n\n private static shouldRethrowofflineNetworkError(): boolean {\n const experimental = TernSecureBase.ternsecure?._internal_getOption?.('experimental');\n return experimental?.rethrowOfflineNetworkErrors || false;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAAqC;AAKrC,mBAAmE;AAsB5D,MAAe,eAAe;AAAA,EACnC,OAAO;AAAA,EAEP,WAAW,YAAY;AACrB,WAAO,eAAe,WAAW,aAAa;AAAA,EAChD;AAAA,EAEA,WAAW,oBAAmD;AAC5D,WAAO,KAAK,WAAW,kBAAkB;AAAA,EAC3C;AAAA,EACA,IAAc,oBAAmD;AAC/D,WAAO,eAAe;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAuB,iBACrB,aACoC;AA/CxC;AAgDI,QAAI;AACJ,QAAI;AACF,oBAAc,MAAM,eAAe,UAAU,QAAW,aAAa,EAAE,WAAW,IAAM,CAAC;AAAA,IAC3F,SAAS,OAAO;AACd,UAAI,KAAK,iCAAiC,GAAG;AAC3C,cAAM,IAAI,qCAAwB,+BAAiB,YAAW,OAAO,KAAK,GAAG;AAAA,UAC3E,MAAM;AAAA,QACR,CAAC;AAAA,MACH,WAAW,KAAC,qCAAqB,GAAG;AAClC,gBAAQ,KAAK,KAAK;AAClB,eAAO;AAAA,MACT,OAAO;AACL,cAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,EAAE,SAAS,QAAQ,YAAY,QAAQ,IAAI;AAEjD,QAAI,SAAS;AACX,YAAM,UAAU,QAAQ,IAAI,WAAW;AACvC,WAAK,WAAW,sBAAsB,UAAU,QAAQ,YAAY,IAAI,IAAI;AAAA,IAC9E;AAEA,QAAI,UAAU,OAAO,UAAU,KAAK;AAClC,aAAO;AAAA,IACT;AAEA,QAAI,UAAU,KAAK;AACjB,YAAM,SAAS,mCAAS;AACxB,YAAM,WAAU,sCAAS,OAAT,mBAAa;AAE7B,YAAM,qBAAkF;AAAA,QACtF,MAAM;AAAA,QACN;AAAA,MACF;AACA,UAAI,WAAW,OAAO,SAAS;AAC7B,cAAM,aAAa,QAAQ,IAAI,aAAa;AAC5C,YAAI,YAAY;AACd,gBAAM,QAAQ,SAAS,YAAY,EAAE;AACrC,cAAI,CAAC,MAAM,KAAK,GAAG;AACjB,+BAAmB,aAAa;AAAA,UAClC;AAAA,QACF;AAAA,MACF;AAEA,YAAM,IAAI,wCAA2B,WAAW,YAAY,kBAAkB;AAAA,IAChF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,SAAS,QAAgE;AACpF,WAAO,KAAK,iBAAiB,EAAE,GAAG,QAAQ,QAAQ,OAAO,CAAC;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,iBACd,aACsC;AACtC,WAAO,eAAe,iBAAiB,WAAW;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,SAAS,QAAgE;AACvF,WAAO,eAAe,SAAS,MAAM;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAgB,QAAQ,QAAgF;AACtG,WAAO,KAAK,iBAAiB,EAAE,GAAG,QAAQ,QAAQ,MAAM,CAAC;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAgB,MAAM,QAAgE;AACpF,WAAO,KAAK,SAAS;AAAA,MACnB,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,IACf,CAAC;AAAA,EACH;AAAA,EAEA,aAAa,eAAe,aAAmE;AAC7F,WAAO,KAAK,iBAAiB,WAAW;AAAA,EAC1C;AAAA,EAEA,MAAgB,eACd,aACsC;AACtC,WAAO,KAAK,iBAAiB,WAAW;AAAA,EAC1C;AAAA,EAEA,OAAe,mCAA4C;AAvJ7D;AAwJI,UAAM,gBAAe,0BAAe,eAAf,mBAA2B,wBAA3B,4BAAiD;AACtE,YAAO,6CAAc,gCAA+B;AAAA,EACtD;AACF;","names":[]}
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var Session_exports = {};
20
+ __export(Session_exports, {
21
+ Session: () => Session
22
+ });
23
+ module.exports = __toCommonJS(Session_exports);
24
+ var import_events = require("../instance/events");
25
+ var import_Base = require("./Base");
26
+ class Session extends import_Base.TernSecureBase {
27
+ pathRoot = "/sessions/createsession";
28
+ status;
29
+ token;
30
+ claims;
31
+ authTime;
32
+ expirationTime;
33
+ issuedAtTime;
34
+ signInProvider;
35
+ signInSecondFactor;
36
+ user;
37
+ constructor(sessionData) {
38
+ super();
39
+ this.initializeFromSessionData(sessionData);
40
+ }
41
+ /**
42
+ * Initialize session from existing session data
43
+ */
44
+ initializeFromSessionData(sessionData) {
45
+ this.status = sessionData.status || "pending";
46
+ this.token = sessionData.token || "";
47
+ this.claims = sessionData.claims || {};
48
+ this.authTime = sessionData.authTime || "";
49
+ this.expirationTime = sessionData.expirationTime || "";
50
+ this.issuedAtTime = sessionData.issuedAtTime || "";
51
+ this.signInProvider = sessionData.signInProvider || null;
52
+ this.signInSecondFactor = sessionData.signInSecondFactor || null;
53
+ this.user = sessionData.user;
54
+ }
55
+ /**
56
+ * Create custom token from current session for server-side sync
57
+ * This calls the backend API to create a custom token from the current ID token
58
+ */
59
+ createSession = (idToken, csrfToken) => {
60
+ return this._post({
61
+ path: this.pathRoot,
62
+ body: {
63
+ idToken,
64
+ csrfToken
65
+ }
66
+ });
67
+ };
68
+ /**
69
+ * FIXED: Now properly returns the custom token string instead of the full API response
70
+ * This method correctly extracts the token from the API response structure
71
+ */
72
+ getIdAndRefreshToken = async (idToken, csrfToken) => {
73
+ await this.createSession(idToken, csrfToken);
74
+ };
75
+ /**
76
+ * NEW: create method that calls API to create session
77
+ * API handles everything, no return value needed
78
+ * This method works with the existing sessionData passed to constructor
79
+ */
80
+ create = async (csrfToken) => {
81
+ await this.createSession(this.token, csrfToken);
82
+ import_events.eventBus.emit(import_events.events.SessionChanged, null);
83
+ };
84
+ /**
85
+ * Convert session to plain object for serialization
86
+ */
87
+ toJSON() {
88
+ return {
89
+ status: this.status,
90
+ token: this.token,
91
+ claims: this.claims,
92
+ authTime: this.authTime,
93
+ expirationTime: this.expirationTime,
94
+ issuedAtTime: this.issuedAtTime,
95
+ signInProvider: this.signInProvider,
96
+ signInSecondFactor: this.signInSecondFactor,
97
+ user: this.user
98
+ };
99
+ }
100
+ }
101
+ // Annotate the CommonJS export names for ESM import in node:
102
+ 0 && (module.exports = {
103
+ Session
104
+ });
105
+ //# sourceMappingURL=Session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/resources/Session.ts"],"sourcesContent":["import type {\n IdTokenResult,\n SessionJson,\n SessionResource,\n SessionStatus,\n TernSecureUser,\n} from '@tern-secure/types';\n\nimport { eventBus, events } from '../instance/events';\nimport { TernSecureBase } from './Base';\n\n/**\n * Enhanced Session class that handles custom token authentication for client-server sync.\n *\n * Key Features:\n * - Manages custom tokens for server-side verification\n * - Uses TernSecureUser object directly (no Firebase Auth instance needed)\n * - Provides seamless client-server session synchronization\n * - Works with in-memory persistence by using custom tokens to restore auth state\n */\nexport class Session extends TernSecureBase implements SessionResource {\n pathRoot = '/sessions/createsession';\n\n status!: SessionStatus;\n token!: string;\n claims!: IdTokenResult['claims'];\n authTime!: string;\n expirationTime!: string;\n issuedAtTime!: string;\n signInProvider!: string | null;\n signInSecondFactor!: string | null;\n user?: TernSecureUser;\n\n constructor(sessionData: Partial<SessionResource>) {\n super();\n this.initializeFromSessionData(sessionData);\n }\n\n /**\n * Initialize session from existing session data\n */\n private initializeFromSessionData(sessionData: Partial<SessionResource>): void {\n this.status = sessionData.status || 'pending';\n this.token = sessionData.token || '';\n this.claims = sessionData.claims || {};\n this.authTime = sessionData.authTime || '';\n this.expirationTime = sessionData.expirationTime || '';\n this.issuedAtTime = sessionData.issuedAtTime || '';\n this.signInProvider = sessionData.signInProvider || null;\n this.signInSecondFactor = sessionData.signInSecondFactor || null;\n this.user = sessionData.user;\n }\n\n /**\n * Create custom token from current session for server-side sync\n * This calls the backend API to create a custom token from the current ID token\n */\n private createSession = (idToken: string, csrfToken: string) => {\n return this._post({\n path: this.pathRoot,\n body: {\n idToken,\n csrfToken,\n },\n });\n };\n\n\n /**\n * FIXED: Now properly returns the custom token string instead of the full API response\n * This method correctly extracts the token from the API response structure\n */\n getIdAndRefreshToken = async (idToken: string, csrfToken: string): Promise<void> => {\n await this.createSession(idToken, csrfToken);\n };\n\n /**\n * NEW: create method that calls API to create session\n * API handles everything, no return value needed\n * This method works with the existing sessionData passed to constructor\n */\n create = async (csrfToken: string): Promise<void> => {\n await this.createSession(this.token, csrfToken);\n eventBus.emit(events.SessionChanged, null);\n };\n\n /**\n * Convert session to plain object for serialization\n */\n toJSON(): SessionJson {\n return {\n status: this.status,\n token: this.token,\n claims: this.claims,\n authTime: this.authTime,\n expirationTime: this.expirationTime,\n issuedAtTime: this.issuedAtTime,\n signInProvider: this.signInProvider,\n signInSecondFactor: this.signInSecondFactor,\n user: this.user,\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,oBAAiC;AACjC,kBAA+B;AAWxB,MAAM,gBAAgB,2BAA0C;AAAA,EACrE,WAAW;AAAA,EAEX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY,aAAuC;AACjD,UAAM;AACN,SAAK,0BAA0B,WAAW;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKQ,0BAA0B,aAA6C;AAC7E,SAAK,SAAS,YAAY,UAAU;AACpC,SAAK,QAAQ,YAAY,SAAS;AAClC,SAAK,SAAS,YAAY,UAAU,CAAC;AACrC,SAAK,WAAW,YAAY,YAAY;AACxC,SAAK,iBAAiB,YAAY,kBAAkB;AACpD,SAAK,eAAe,YAAY,gBAAgB;AAChD,SAAK,iBAAiB,YAAY,kBAAkB;AACpD,SAAK,qBAAqB,YAAY,sBAAsB;AAC5D,SAAK,OAAO,YAAY;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,gBAAgB,CAAC,SAAiB,cAAsB;AAC9D,WAAO,KAAK,MAAM;AAAA,MAChB,MAAM,KAAK;AAAA,MACX,MAAM;AAAA,QACJ;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,uBAAuB,OAAO,SAAiB,cAAqC;AAClF,UAAM,KAAK,cAAc,SAAS,SAAS;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAS,OAAO,cAAqC;AACnD,UAAM,KAAK,cAAc,KAAK,OAAO,SAAS;AAC9C,2BAAS,KAAK,qBAAO,gBAAgB,IAAI;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,SAAsB;AACpB,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,gBAAgB,KAAK;AAAA,MACrB,cAAc,KAAK;AAAA,MACnB,gBAAgB,KAAK;AAAA,MACrB,oBAAoB,KAAK;AAAA,MACzB,MAAM,KAAK;AAAA,IACb;AAAA,EACF;AACF;","names":[]}
@@ -49,22 +49,25 @@ class SignIn extends import_Base.TernSecureBase {
49
49
  withEmailAndPassword = async (params) => {
50
50
  try {
51
51
  const { email, password } = params;
52
- const userCredential = await (0, import_auth.signInWithEmailAndPassword)(this.auth, email, password);
53
- await this.signInWithCredential(userCredential);
54
- const { user } = userCredential;
52
+ const { user, providerId, operationType } = await (0, import_auth.signInWithEmailAndPassword)(
53
+ this.auth,
54
+ email,
55
+ password
56
+ );
55
57
  return {
56
- success: true,
57
- message: "Authentication successful",
58
+ status: "success",
58
59
  user,
60
+ providerId,
61
+ operationType,
62
+ message: "Authentication successful",
59
63
  error: !user.emailVerified ? "REQUIRES_VERIFICATION" : "AUTHENTICATED"
60
64
  };
61
65
  } catch (error) {
62
66
  const authError = (0, import_errors.handleFirebaseAuthError)(error);
63
67
  return {
64
- success: false,
68
+ status: "error",
65
69
  message: authError.message,
66
- error: authError.code,
67
- user: null
70
+ error: authError.code
68
71
  };
69
72
  }
70
73
  };
@@ -83,7 +86,7 @@ class SignIn extends import_Base.TernSecureBase {
83
86
  if ((options == null ? void 0 : options.mode) === "redirect") {
84
87
  const redirectResult = await this.authRedirectResult();
85
88
  if (redirectResult) {
86
- if (redirectResult.success) {
89
+ if (redirectResult.status === "success") {
87
90
  console.log("Redirect after sign in");
88
91
  }
89
92
  return redirectResult;
@@ -93,16 +96,15 @@ class SignIn extends import_Base.TernSecureBase {
93
96
  } else {
94
97
  await this._signInWithPopUp(provider);
95
98
  return {
96
- success: true,
99
+ status: "success",
97
100
  message: "Sign in successful"
98
101
  };
99
102
  }
100
103
  } catch (error) {
101
104
  return {
102
- success: false,
105
+ status: "error",
103
106
  message: error.message || `Sign in with ${provider} failed`,
104
- error,
105
- user: null
107
+ error
106
108
  };
107
109
  }
108
110
  };
@@ -120,8 +122,6 @@ class SignIn extends import_Base.TernSecureBase {
120
122
  await user.reload();
121
123
  if (user.emailVerified) {
122
124
  return {
123
- success: true,
124
- message: "Email is already verified. You can sign in.",
125
125
  isVerified: true
126
126
  };
127
127
  }
@@ -132,8 +132,6 @@ class SignIn extends import_Base.TernSecureBase {
132
132
  };
133
133
  await (0, import_auth.sendEmailVerification)(user, actionCodeSettings);
134
134
  return {
135
- success: true,
136
- message: "Verification email sent. Please check your inbox.",
137
135
  isVerified: false
138
136
  };
139
137
  };
@@ -166,20 +164,21 @@ class SignIn extends import_Base.TernSecureBase {
166
164
  try {
167
165
  const result = await (0, import_auth.getRedirectResult)(this.auth);
168
166
  if (result) {
169
- const user = result.user;
167
+ const { user, providerId, operationType } = result;
170
168
  return {
171
- success: true,
172
- user
169
+ status: "success",
170
+ user,
171
+ providerId,
172
+ operationType
173
173
  };
174
174
  }
175
175
  return null;
176
176
  } catch (error) {
177
177
  const authError = (0, import_errors.handleFirebaseAuthError)(error);
178
178
  return {
179
- success: false,
179
+ status: "error",
180
180
  message: authError.message,
181
- error: authError.code,
182
- user: null
181
+ error: authError.code
183
182
  };
184
183
  }
185
184
  }
@@ -188,14 +187,13 @@ class SignIn extends import_Base.TernSecureBase {
188
187
  config.provider.setCustomParameters(config.customParameters);
189
188
  try {
190
189
  await authMethod(this.auth, config.provider);
191
- return { success: true, message: "Authentication initiated" };
190
+ return { status: "success", message: "Authentication initiated" };
192
191
  } catch (error) {
193
192
  const authError = (0, import_errors.handleFirebaseAuthError)(error);
194
193
  return {
195
- success: false,
194
+ status: "error",
196
195
  message: authError.message,
197
- error: authError.code,
198
- user: null
196
+ error: authError.code
199
197
  };
200
198
  }
201
199
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/resources/SignIn.ts"],"sourcesContent":["import { handleFirebaseAuthError } from '@tern-secure/shared/errors';\nimport type {\n ResendEmailVerification,\n SignInFormValues,\n SignInResource,\n SignInResponse,\n SignInStatus,\n TernSecureUser,\n} from '@tern-secure/types';\nimport type { Auth, UserCredential } from 'firebase/auth';\nimport {\n getRedirectResult,\n GoogleAuthProvider,\n OAuthProvider,\n sendEmailVerification,\n signInWithEmailAndPassword,\n signInWithPopup,\n signInWithRedirect,\n} from 'firebase/auth';\n\nimport { TernSecureBase } from './Base';\n\ninterface ProviderConfig {\n provider: GoogleAuthProvider | OAuthProvider;\n customParameters: Record<string, string>;\n}\n\nexport type TernRequestInit = RequestInit;\n\nexport type SignInParams = {\n idToken: string;\n csrfToken: string | undefined;\n};\n\ntype FirebaseAuthResult = UserCredential | void;\n\ntype AuthMethodFunction = (\n auth: Auth,\n provider: GoogleAuthProvider | OAuthProvider,\n) => Promise<FirebaseAuthResult>;\n\nexport class SignIn extends TernSecureBase implements SignInResource {\n pathRoot = '/sessions/createsession';\n\n status?: SignInStatus | undefined;\n private auth: Auth;\n private csrfToken: string | undefined;\n private _currentUser: TernSecureUser | null = null;\n\n constructor(auth: Auth, csrfToken: string | undefined) {\n super();\n this.auth = auth;\n this.csrfToken = csrfToken;\n }\n\n signInWithCredential = async (credential: UserCredential) => {\n const idToken = await credential.user.getIdToken();\n const params = {\n idToken: idToken,\n csrfToken: this.csrfToken,\n };\n\n return this._post({\n path: this.pathRoot,\n body: params,\n });\n };\n\n withEmailAndPassword = async (params: SignInFormValues): Promise<SignInResponse> => {\n try {\n const { email, password } = params;\n const userCredential = await signInWithEmailAndPassword(this.auth, email, password);\n\n await this.signInWithCredential(userCredential);\n\n const { user } = userCredential;\n return {\n success: true,\n message: 'Authentication successful',\n user,\n error: !user.emailVerified ? 'REQUIRES_VERIFICATION' : 'AUTHENTICATED',\n };\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n return {\n success: false,\n message: authError.message,\n error: authError.code,\n user: null,\n };\n }\n };\n\n withCredential = async (params: SignInFormValues): Promise<void> => {\n try {\n const { email, password } = params;\n const userCredential = await signInWithEmailAndPassword(this.auth, email, password);\n await this.signInWithCredential(userCredential);\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n console.error(authError);\n }\n };\n\n withSocialProvider = async (\n provider: string,\n options?: {\n mode?: 'popup' | 'redirect';\n },\n ): Promise<SignInResponse | void> => {\n try {\n if (options?.mode === 'redirect') {\n const redirectResult = await this.authRedirectResult();\n\n if (redirectResult) {\n if (redirectResult.success) {\n console.log('Redirect after sign in');\n }\n return redirectResult;\n }\n\n await this._signInWithRedirect(provider);\n return;\n } else {\n await this._signInWithPopUp(provider);\n return {\n success: true,\n message: 'Sign in successful',\n };\n }\n } catch (error: any) {\n return {\n success: false,\n message: error.message || `Sign in with ${provider} failed`,\n error,\n user: null,\n };\n }\n };\n\n completeMfaSignIn = async (_mfaToken: string, _mfaContext?: any): Promise<SignInResponse> => {\n throw new Error('Method not implemented.');\n };\n\n sendPasswordResetEmail = async (email: string): Promise<void> => {\n console.log(`Sending password reset email to ${email}`);\n };\n\n resendEmailVerification = async (): Promise<ResendEmailVerification> => {\n const user = this._currentUser;\n if (!user) {\n throw new Error('No user is currently signed in');\n }\n\n await user.reload();\n\n if (user.emailVerified) {\n return {\n success: true,\n message: 'Email is already verified. You can sign in.',\n isVerified: true,\n };\n }\n\n const actionCodeSettings = {\n url: '/sign-in', // TODO: Make this configurable\n handleCodeInApp: true,\n };\n\n await sendEmailVerification(user, actionCodeSettings);\n return {\n success: true,\n message: 'Verification email sent. Please check your inbox.',\n isVerified: false,\n };\n };\n\n private getProviderConfig(providerName: string): ProviderConfig {\n switch (providerName.toLowerCase()) {\n case 'google': {\n const googleProvider = new GoogleAuthProvider();\n return {\n provider: googleProvider,\n customParameters: {\n login_hint: 'user@example.com',\n prompt: 'select_account',\n },\n };\n }\n case 'microsoft': {\n const microsoftProvider = new OAuthProvider('microsoft.com');\n return {\n provider: microsoftProvider,\n customParameters: {\n prompt: 'consent',\n },\n };\n }\n default:\n throw new Error(`Unsupported provider: ${providerName}`);\n }\n }\n\n private async authRedirectResult(): Promise<SignInResponse | null> {\n try {\n const result = await getRedirectResult(this.auth);\n\n if (result) {\n const user = result.user;\n return {\n success: true,\n user,\n };\n }\n return null;\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n return {\n success: false,\n message: authError.message,\n error: authError.code,\n user: null,\n };\n }\n }\n\n private async executeAuthMethod(\n authMethod: AuthMethodFunction,\n providerName: string,\n ): Promise<SignInResponse> {\n const config = this.getProviderConfig(providerName);\n config.provider.setCustomParameters(config.customParameters);\n try {\n await authMethod(this.auth, config.provider);\n return { success: true, message: 'Authentication initiated' };\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n return {\n success: false,\n message: authError.message,\n error: authError.code,\n user: null,\n };\n }\n }\n\n private async _signInWithRedirect(providerName: string): Promise<SignInResponse> {\n return this.executeAuthMethod(signInWithRedirect, providerName);\n }\n\n private async _signInWithPopUp(providerName: string): Promise<SignInResponse> {\n return this.executeAuthMethod(signInWithPopup, providerName);\n }\n\n public async checkRedirectResult(): Promise<SignInResponse | null> {\n return this.authRedirectResult();\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/resources/SignIn.ts"],"sourcesContent":["import { handleFirebaseAuthError } from '@tern-secure/shared/errors';\nimport type {\n ResendEmailVerification,\n SignInFormValues,\n SignInResource,\n SignInResponse as SignInResponseFromTypes,\n SignInStatus,\n TernSecureUser,\n} from '@tern-secure/types';\nimport type { Auth, UserCredential } from 'firebase/auth';\nimport {\n getRedirectResult,\n GoogleAuthProvider,\n OAuthProvider,\n sendEmailVerification,\n signInWithEmailAndPassword,\n signInWithPopup,\n signInWithRedirect,\n} from 'firebase/auth';\n\nimport { TernSecureBase } from './Base';\n\ntype SignInResponse = SignInResponseFromTypes;\n\ninterface ProviderConfig {\n provider: GoogleAuthProvider | OAuthProvider;\n customParameters: Record<string, string>;\n}\n\nexport type TernRequestInit = RequestInit;\n\nexport type SignInParams = {\n idToken: string;\n csrfToken: string | undefined;\n};\n\ntype FirebaseAuthResult = UserCredential | void;\n\ntype AuthMethodFunction = (\n auth: Auth,\n provider: GoogleAuthProvider | OAuthProvider,\n) => Promise<FirebaseAuthResult>;\n\nexport class SignIn extends TernSecureBase implements SignInResource {\n pathRoot = '/sessions/createsession';\n\n status?: SignInStatus | undefined;\n private auth: Auth;\n private csrfToken: string | undefined;\n private _currentUser: TernSecureUser | null = null;\n\n constructor(auth: Auth, csrfToken: string | undefined) {\n super();\n this.auth = auth;\n this.csrfToken = csrfToken;\n }\n\n signInWithCredential = async (credential: UserCredential) => {\n const idToken = await credential.user.getIdToken();\n const params = {\n idToken: idToken,\n csrfToken: this.csrfToken,\n };\n\n return this._post({\n path: this.pathRoot,\n body: params,\n });\n };\n\n withEmailAndPassword = async (params: SignInFormValues): Promise<SignInResponse> => {\n try {\n const { email, password } = params;\n const { user, providerId, operationType } = await signInWithEmailAndPassword(\n this.auth,\n email,\n password,\n );\n return {\n status: 'success',\n user,\n providerId,\n operationType,\n message: 'Authentication successful',\n error: !user.emailVerified ? 'REQUIRES_VERIFICATION' : 'AUTHENTICATED',\n };\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n return {\n status: 'error',\n message: authError.message,\n error: authError.code,\n };\n }\n };\n\n withCredential = async (params: SignInFormValues): Promise<void> => {\n try {\n const { email, password } = params;\n const userCredential = await signInWithEmailAndPassword(this.auth, email, password);\n await this.signInWithCredential(userCredential);\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n console.error(authError);\n }\n };\n\n withSocialProvider = async (\n provider: string,\n options?: {\n mode?: 'popup' | 'redirect';\n },\n ): Promise<SignInResponse | void> => {\n try {\n if (options?.mode === 'redirect') {\n const redirectResult = await this.authRedirectResult();\n\n if (redirectResult) {\n if (redirectResult.status === 'success') {\n console.log('Redirect after sign in');\n }\n return redirectResult;\n }\n\n await this._signInWithRedirect(provider);\n return;\n } else {\n await this._signInWithPopUp(provider);\n return {\n status: 'success',\n message: 'Sign in successful',\n };\n }\n } catch (error: any) {\n return {\n status: 'error',\n message: error.message || `Sign in with ${provider} failed`,\n error,\n };\n }\n };\n\n completeMfaSignIn = async (_mfaToken: string, _mfaContext?: any): Promise<SignInResponse> => {\n throw new Error('Method not implemented.');\n };\n\n sendPasswordResetEmail = async (email: string): Promise<void> => {\n console.log(`Sending password reset email to ${email}`);\n };\n\n resendEmailVerification = async (): Promise<ResendEmailVerification> => {\n const user = this._currentUser;\n if (!user) {\n throw new Error('No user is currently signed in');\n }\n\n await user.reload();\n\n if (user.emailVerified) {\n return {\n isVerified: true,\n };\n }\n\n const actionCodeSettings = {\n url: '/sign-in', // TODO: Make this configurable\n handleCodeInApp: true,\n };\n\n await sendEmailVerification(user, actionCodeSettings);\n return {\n isVerified: false,\n };\n };\n\n private getProviderConfig(providerName: string): ProviderConfig {\n switch (providerName.toLowerCase()) {\n case 'google': {\n const googleProvider = new GoogleAuthProvider();\n return {\n provider: googleProvider,\n customParameters: {\n login_hint: 'user@example.com',\n prompt: 'select_account',\n },\n };\n }\n case 'microsoft': {\n const microsoftProvider = new OAuthProvider('microsoft.com');\n return {\n provider: microsoftProvider,\n customParameters: {\n prompt: 'consent',\n },\n };\n }\n default:\n throw new Error(`Unsupported provider: ${providerName}`);\n }\n }\n\n private async authRedirectResult(): Promise<SignInResponse | null> {\n try {\n const result = await getRedirectResult(this.auth);\n\n if (result) {\n const { user, providerId, operationType } = result;\n return {\n status: 'success',\n user,\n providerId,\n operationType,\n };\n }\n return null;\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n return {\n status: 'error',\n message: authError.message,\n error: authError.code,\n };\n }\n }\n\n private async executeAuthMethod(\n authMethod: AuthMethodFunction,\n providerName: string,\n ): Promise<SignInResponse> {\n const config = this.getProviderConfig(providerName);\n config.provider.setCustomParameters(config.customParameters);\n try {\n await authMethod(this.auth, config.provider);\n return { status: 'success', message: 'Authentication initiated' };\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n return {\n status: 'error',\n message: authError.message,\n error: authError.code,\n };\n }\n }\n\n private async _signInWithRedirect(providerName: string): Promise<SignInResponse> {\n return this.executeAuthMethod(signInWithRedirect, providerName);\n }\n\n private async _signInWithPopUp(providerName: string): Promise<SignInResponse> {\n return this.executeAuthMethod(signInWithPopup, providerName);\n }\n\n public async checkRedirectResult(): Promise<SignInResponse | null> {\n return this.authRedirectResult();\n }\n}\n"],"mappings":"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","names":[]}