@tern-secure/auth 1.1.0-canary.v20251023005301 → 1.1.0-canary.v20251024005655
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/instance/TernAuth.js +6 -6
- package/dist/cjs/instance/TernAuth.js.map +1 -1
- package/dist/cjs/resources/SignIn.js +7 -14
- package/dist/cjs/resources/SignIn.js.map +1 -1
- package/dist/cjs/utils/construct.js +1 -0
- package/dist/cjs/utils/construct.js.map +1 -1
- package/dist/cjs/utils/redirectUrls.js +1 -0
- package/dist/cjs/utils/redirectUrls.js.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/instance/TernAuth.js +6 -6
- package/dist/esm/instance/TernAuth.js.map +1 -1
- package/dist/esm/resources/SignIn.js +7 -14
- package/dist/esm/resources/SignIn.js.map +1 -1
- package/dist/esm/utils/construct.js +1 -0
- package/dist/esm/utils/construct.js.map +1 -1
- package/dist/esm/utils/redirectUrls.js +1 -0
- package/dist/esm/utils/redirectUrls.js.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/instance/TernAuth.d.ts +2 -2
- package/dist/types/instance/TernAuth.d.ts.map +1 -1
- package/dist/types/resources/SignIn.d.ts +2 -2
- package/dist/types/resources/SignIn.d.ts.map +1 -1
- package/dist/types/utils/construct.d.ts.map +1 -1
- package/dist/types/utils/redirectUrls.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export { TernSecureAuth } from './instance/TernAuth';\nexport type { TernAuth } from './instance/TernAuth';\nexport { TernServerAuth } from './instance/TernAuthServer';\nexport type { TernServerAuthOptions, AuthenticatedApp } from './instance/TernAuthServer';\n\nexport { CoreApiClient, coreApiClient } from './instance/coreApiClient';\nexport type { \n ApiResponse, \n ApiResponseJSON, \n RequestOptions,\n BeforeRequestHook,\n AfterResponseHook\n} from './instance/coreApiClient';\n\nexport { SignIn, TernSecureBase, buildURL } from './resources/internal';\n\nexport type {\n AuthErrorTree,\n TernSecureConfig,\n SignInFormValues,\n SignInProps,\n SignUpProps,\n SignInResponse,\n SignInForceRedirectUrl,\n SignUpForceRedirectUrl,\n ResendEmailVerification,\n TernSecureUser,\n TernSecureState\n} from '@tern-secure/types';\n\nexport { RedirectUrls } from './utils/redirectUrls';"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAA+B;AAE/B,4BAA+B;AAG/B,2BAA6C;AAS7C,sBAAiD;
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export { TernSecureAuth } from './instance/TernAuth';\nexport type { TernAuth } from './instance/TernAuth';\nexport { TernServerAuth } from './instance/TernAuthServer';\nexport type { TernServerAuthOptions, AuthenticatedApp } from './instance/TernAuthServer';\n\nexport { CoreApiClient, coreApiClient } from './instance/coreApiClient';\nexport type { \n ApiResponse, \n ApiResponseJSON, \n RequestOptions,\n BeforeRequestHook,\n AfterResponseHook\n} from './instance/coreApiClient';\n\nexport { SignIn, TernSecureBase, buildURL } from './resources/internal';\n\nexport type {\n AuthErrorTree,\n TernSecureConfig,\n SignInFormValues,\n SignInProps,\n SignUpProps,\n SignInResponse,\n SignInForceRedirectUrl,\n SignUpForceRedirectUrl,\n SignInFallbackRedirectUrl,\n ResendEmailVerification,\n TernSecureUser,\n TernSecureState\n} from '@tern-secure/types';\n\nexport { RedirectUrls } from './utils/redirectUrls';"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAA+B;AAE/B,4BAA+B;AAG/B,2BAA6C;AAS7C,sBAAiD;AAiBjD,0BAA6B;","names":[]}
|
|
@@ -40,10 +40,10 @@ function inBrowser() {
|
|
|
40
40
|
return typeof window !== "undefined";
|
|
41
41
|
}
|
|
42
42
|
class TernSecureAuth {
|
|
43
|
-
static version = "1.1.0-canary.
|
|
43
|
+
static version = "1.1.0-canary.v20251024005655";
|
|
44
44
|
static sdkMetadata = {
|
|
45
45
|
name: "@tern-secure/auth",
|
|
46
|
-
version: "1.1.0-canary.
|
|
46
|
+
version: "1.1.0-canary.v20251024005655",
|
|
47
47
|
environment: process.env.NODE_ENV || "production"
|
|
48
48
|
};
|
|
49
49
|
static instance = null;
|
|
@@ -324,7 +324,7 @@ class TernSecureAuth {
|
|
|
324
324
|
this.signedInSession = null;
|
|
325
325
|
}
|
|
326
326
|
}
|
|
327
|
-
async
|
|
327
|
+
checkRedirectResult = async () => {
|
|
328
328
|
try {
|
|
329
329
|
const result = await (0, import_auth.getRedirectResult)(this.auth);
|
|
330
330
|
if (result) {
|
|
@@ -342,9 +342,9 @@ class TernSecureAuth {
|
|
|
342
342
|
error: authError.code
|
|
343
343
|
};
|
|
344
344
|
}
|
|
345
|
-
}
|
|
345
|
+
};
|
|
346
346
|
getRedirectResult = async () => {
|
|
347
|
-
|
|
347
|
+
return this.checkRedirectResult();
|
|
348
348
|
};
|
|
349
349
|
addListener = (listener) => {
|
|
350
350
|
this.#listeners.push(listener);
|
|
@@ -544,7 +544,7 @@ class TernSecureAuth {
|
|
|
544
544
|
}
|
|
545
545
|
const emulatorUrl = host.startsWith("http") ? host : `http://${host}`;
|
|
546
546
|
try {
|
|
547
|
-
(0, import_auth.connectAuthEmulator)(this.auth, emulatorUrl, { disableWarnings:
|
|
547
|
+
(0, import_auth.connectAuthEmulator)(this.auth, emulatorUrl, { disableWarnings: false });
|
|
548
548
|
console.warn(`[TernSecure] Firebase Auth Emulator connected at ${emulatorUrl}`);
|
|
549
549
|
} catch (error) {
|
|
550
550
|
console.error("[TernSecure] Error connecting to Firebase Auth Emulator:", error);
|
|
@@ -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 CreateActiveSession,\n DomainOrProxyUrl,\n InstanceType,\n ListenerCallback,\n NavigateOptions,\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 browserPopupRedirectResolver,\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 { ALLOWED_PROTOCOLS, buildURL, stripOrigin, windowNavigate } from '../utils/';\nimport { RedirectUrls } from '../utils/redirectUrls';\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 | null | undefined;\n signUp!: SignUpResource | null | undefined;\n session!: SessionResource | null | undefined;\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 = async (options?: TernSecureAuthOptions): Promise<void> => {\n void this.#initialize(options || {});\n };\n\n public static create(options: TernSecureAuthOptions): TernSecureAuth {\n const instance = this.getOrCreateInstance();\n void instance.initialize(options);\n return instance;\n }\n\n #initialize = (options: TernSecureAuthOptions): void => {\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 popupRedirectResolver: browserPopupRedirectResolver,\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 * 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 * @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('[ternauth] Error during client auth request initialization:', error);\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 \n await this.navigate(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\n if (redirectUrl) {\n await this.navigate(this.constructUrlWithAuthRedirect(redirectUrl));\n }\n\n this.#setCreatedActiveSession(session);\n this.#emit();\n } catch (error) {\n console.error('[TernSecureAuth] Error creating active session:', error);\n }\n };\n\n public navigate = async (to: string | undefined, options?: NavigateOptions): Promise<unknown> => {\n if (!to || !inBrowser()) {\n return;\n }\n\n let toURL = new URL(to, window.location.href);\n\n if (!this.#allowedRedirectProtocols.includes(toURL.protocol)) {\n console.warn(\n `TernSecureAuth: \"${toURL.protocol}\" is not a valid protocol. Redirecting to \"/\" instead. If you think this is a mistake, please open an issue.`,\n );\n toURL = new URL('/', window.location.href);\n }\n\n const customNavigate =\n options?.replace && this.#options.routerReplace\n ? this.#options.routerReplace\n : this.#options.routerPush;\n\n if ((toURL.origin !== 'null' && toURL.origin !== window.location.origin) || !customNavigate) {\n windowNavigate(toURL);\n return;\n }\n\n const metadata = {\n ...(options?.metadata ? { __internal_metadata: options?.metadata } : {}),\n windowNavigate,\n };\n\n // React router only wants the path, search or hash portion.\n return await customNavigate(stripOrigin(toURL), metadata);\n };\n\n public constructUrlWithAuthRedirect = (to: string): string => {\n if (this.#instanceType === 'production') {\n return to;\n }\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 const redirectUrls = new RedirectUrls(this.#options, options).toSearchParams();\n const constructedUrl = buildURL(\n {\n base,\n hashSearchParams: [redirectUrls],\n },\n {\n stringify: true,\n skipOrigin: false,\n },\n );\n return this.constructUrlWithAuthRedirect(constructedUrl);\n };\n\n #constructAfterSignInUrl = (): string => {\n return this.constructUrlWithAuthRedirect(new RedirectUrls(this.#options).getAfterSignInUrl());\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 return this.navigate(this.constructSignInUrl(options));\n }\n return;\n };\n\n public redirectToSignUp = async (options?: SignUpRedirectOptions): Promise<unknown> => {\n if (inBrowser()) {\n return this.navigate(this.constructSignUpUrl());\n }\n return;\n };\n\n public redirectAfterSignIn = async (): Promise<unknown> => {\n if (inBrowser()) {\n return this.navigate(this.#constructAfterSignInUrl());\n }\n return;\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', {\n ...options,\n signInForceRedirectUrl: options?.signInForceRedirectUrl || window.location.href,\n });\n };\n\n public constructSignUpUrl = (options?: SignUpRedirectOptions): string => {\n return this.#buildUrl('signUpUrl', {\n ...options,\n signUpForceRedirectUrl: options?.signUpForceRedirectUrl || window.location.href,\n });\n };\n\n get #allowedRedirectProtocols() {\n let allowedProtocols = ALLOWED_PROTOCOLS;\n\n if (this.#options.allowedRedirectProtocols) {\n allowedProtocols = allowedProtocols.concat(this.#options.allowedRedirectProtocols);\n }\n\n return allowedProtocols;\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":"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","names":["import_utils"]}
|
|
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 NavigateOptions,\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 browserPopupRedirectResolver,\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 { ALLOWED_PROTOCOLS, buildURL, stripOrigin, windowNavigate } from '../utils/';\nimport { RedirectUrls } from '../utils/redirectUrls';\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 | null | undefined;\n signUp!: SignUpResource | null | undefined;\n session!: SessionResource | null | undefined;\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 = async (options?: TernSecureAuthOptions): Promise<void> => {\n void this.#initialize(options || {});\n };\n\n public static create(options: TernSecureAuthOptions): TernSecureAuth {\n const instance = this.getOrCreateInstance();\n void instance.initialize(options);\n return instance;\n }\n\n #initialize = (options: TernSecureAuthOptions): void => {\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 popupRedirectResolver: browserPopupRedirectResolver,\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 * 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 * @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('[ternauth] Error during client auth request initialization:', error);\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\n await this.navigate(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 private checkRedirectResult = async (): 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 return this.checkRedirectResult();\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\n if (redirectUrl) {\n await this.navigate(this.constructUrlWithAuthRedirect(redirectUrl));\n }\n\n this.#setCreatedActiveSession(session);\n this.#emit();\n } catch (error) {\n console.error('[TernSecureAuth] Error creating active session:', error);\n }\n };\n\n public navigate = async (to: string | undefined, options?: NavigateOptions): Promise<unknown> => {\n if (!to || !inBrowser()) {\n return;\n }\n\n let toURL = new URL(to, window.location.href);\n\n if (!this.#allowedRedirectProtocols.includes(toURL.protocol)) {\n console.warn(\n `TernSecureAuth: \"${toURL.protocol}\" is not a valid protocol. Redirecting to \"/\" instead. If you think this is a mistake, please open an issue.`,\n );\n toURL = new URL('/', window.location.href);\n }\n\n const customNavigate =\n options?.replace && this.#options.routerReplace\n ? this.#options.routerReplace\n : this.#options.routerPush;\n\n if ((toURL.origin !== 'null' && toURL.origin !== window.location.origin) || !customNavigate) {\n windowNavigate(toURL);\n return;\n }\n\n const metadata = {\n ...(options?.metadata ? { __internal_metadata: options?.metadata } : {}),\n windowNavigate,\n };\n\n // React router only wants the path, search or hash portion.\n return await customNavigate(stripOrigin(toURL), metadata);\n };\n\n public constructUrlWithAuthRedirect = (to: string): string => {\n if (this.#instanceType === 'production') {\n return to;\n }\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 const redirectUrls = new RedirectUrls(this.#options, options).toSearchParams();\n const constructedUrl = buildURL(\n {\n base,\n hashSearchParams: [redirectUrls],\n },\n {\n stringify: true,\n skipOrigin: false,\n },\n );\n return this.constructUrlWithAuthRedirect(constructedUrl);\n };\n\n #constructAfterSignInUrl = (): string => {\n return this.constructUrlWithAuthRedirect(new RedirectUrls(this.#options).getAfterSignInUrl());\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 return this.navigate(this.constructSignInUrl(options));\n }\n return;\n };\n\n public redirectToSignUp = async (options?: SignUpRedirectOptions): Promise<unknown> => {\n if (inBrowser()) {\n return this.navigate(this.constructSignUpUrl());\n }\n return;\n };\n\n public redirectAfterSignIn = async (): Promise<unknown> => {\n if (inBrowser()) {\n return this.navigate(this.#constructAfterSignInUrl());\n }\n return;\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', {\n ...options,\n signInForceRedirectUrl: options?.signInForceRedirectUrl || window.location.href,\n });\n };\n\n public constructSignUpUrl = (options?: SignUpRedirectOptions): string => {\n return this.#buildUrl('signUpUrl', {\n ...options,\n signUpForceRedirectUrl: options?.signUpForceRedirectUrl || window.location.href,\n });\n };\n\n get #allowedRedirectProtocols() {\n let allowedProtocols = ALLOWED_PROTOCOLS;\n\n if (this.#options.allowedRedirectProtocols) {\n allowedProtocols = allowedProtocols.concat(this.#options.allowedRedirectProtocols);\n }\n\n return allowedProtocols;\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: false });\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;AA4BhC,iBAAuC;AAEvC,kBAWO;AACP,2BAAiC;AAEjC,qBAAgE;AAChE,sBAA2E;AAC3E,IAAAA,gBAAyE;AACzE,0BAA6B;AAC7B,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;AA9ItD;AA+II,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,aAAa,OAAO,YAAmD;AACrE,SAAK,KAAK,YAAY,WAAW,CAAC,CAAC;AAAA,EACrC;AAAA,EAEA,OAAc,OAAO,SAAgD;AACnE,UAAM,WAAW,KAAK,oBAAoB;AAC1C,SAAK,SAAS,WAAW,OAAO;AAChC,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,CAAC,YAAyC;AACtD,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;AAAA,IAGtD,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,MACA,uBAAuB;AAAA,IACzB,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,EAKA,aAAa,MAAM;AAlSrB;AAmSI,UAAM,mBAAkB,UAAK,uBAAL,mBAAyB;AACjD,UAAM,gBAAY,sCAAoB,mBAAmB,IAAI;AAC7D,SAAK,OAAO;AACZ,SAAK,MAAM;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,wBAAwB,MAAM;AA5ShC;AA6SI,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,MAAM,+DAA+D,KAAK;AAClF,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;AAEA,UAAM,KAAK,SAAS,WAAW;AAE/B,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,EAEQ,sBAAsB,YAA4C;AACxE,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,WAAO,KAAK,oBAAoB;AAAA,EAClC;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;AAE7C,UAAI,aAAa;AACf,cAAM,KAAK,SAAS,KAAK,6BAA6B,WAAW,CAAC;AAAA,MACpE;AAEA,WAAK,yBAAyB,OAAO;AACrC,WAAK,MAAM;AAAA,IACb,SAAS,OAAO;AACd,cAAQ,MAAM,mDAAmD,KAAK;AAAA,IACxE;AAAA,EACF;AAAA,EAEO,WAAW,OAAO,IAAwB,YAAgD;AAC/F,QAAI,CAAC,MAAM,CAAC,UAAU,GAAG;AACvB;AAAA,IACF;AAEA,QAAI,QAAQ,IAAI,IAAI,IAAI,OAAO,SAAS,IAAI;AAE5C,QAAI,CAAC,KAAK,0BAA0B,SAAS,MAAM,QAAQ,GAAG;AAC5D,cAAQ;AAAA,QACN,oBAAoB,MAAM,QAAQ;AAAA,MACpC;AACA,cAAQ,IAAI,IAAI,KAAK,OAAO,SAAS,IAAI;AAAA,IAC3C;AAEA,UAAM,kBACJ,mCAAS,YAAW,KAAK,SAAS,gBAC9B,KAAK,SAAS,gBACd,KAAK,SAAS;AAEpB,QAAK,MAAM,WAAW,UAAU,MAAM,WAAW,OAAO,SAAS,UAAW,CAAC,gBAAgB;AAC3F,wCAAe,KAAK;AACpB;AAAA,IACF;AAEA,UAAM,WAAW;AAAA,MACf,IAAI,mCAAS,YAAW,EAAE,qBAAqB,mCAAS,SAAS,IAAI,CAAC;AAAA,MACtE;AAAA,IACF;AAGA,WAAO,MAAM,mBAAe,2BAAY,KAAK,GAAG,QAAQ;AAAA,EAC1D;AAAA,EAEO,+BAA+B,CAAC,OAAuB;AAC5D,QAAI,KAAK,kBAAkB,cAAc;AACvC,aAAO;AAAA,IACT;AACA,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;AAChF,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,UAAM,eAAe,IAAI,iCAAa,KAAK,UAAU,OAAO,EAAE,eAAe;AAC7E,UAAM,qBAAiB;AAAA,MACrB;AAAA,QACE;AAAA,QACA,kBAAkB,CAAC,YAAY;AAAA,MACjC;AAAA,MACA;AAAA,QACE,WAAW;AAAA,QACX,YAAY;AAAA,MACd;AAAA,IACF;AACA,WAAO,KAAK,6BAA6B,cAAc;AAAA,EACzD;AAAA,EAEA,2BAA2B,MAAc;AACvC,WAAO,KAAK,6BAA6B,IAAI,iCAAa,KAAK,QAAQ,EAAE,kBAAkB,CAAC;AAAA,EAC9F;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,aAAO,KAAK,SAAS,KAAK,mBAAmB,OAAO,CAAC;AAAA,IACvD;AACA;AAAA,EACF;AAAA,EAEO,mBAAmB,OAAO,YAAsD;AACrF,QAAI,UAAU,GAAG;AACf,aAAO,KAAK,SAAS,KAAK,mBAAmB,CAAC;AAAA,IAChD;AACA;AAAA,EACF;AAAA,EAEO,sBAAsB,YAA8B;AACzD,QAAI,UAAU,GAAG;AACf,aAAO,KAAK,SAAS,KAAK,yBAAyB,CAAC;AAAA,IACtD;AACA;AAAA,EACF;AAAA,EAEA,sBAAsB,MAAY;AAChC,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AAAA,EAEO,qBAAqB,CAAC,YAA4C;AACvE,WAAO,KAAK,UAAU,aAAa;AAAA,MACjC,GAAG;AAAA,MACH,yBAAwB,mCAAS,2BAA0B,OAAO,SAAS;AAAA,IAC7E,CAAC;AAAA,EACH;AAAA,EAEO,qBAAqB,CAAC,YAA4C;AACvE,WAAO,KAAK,UAAU,aAAa;AAAA,MACjC,GAAG;AAAA,MACH,yBAAwB,mCAAS,2BAA0B,OAAO,SAAS;AAAA,IAC7E,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,4BAA4B;AAC9B,QAAI,mBAAmB;AAEvB,QAAI,KAAK,SAAS,0BAA0B;AAC1C,yBAAmB,iBAAiB,OAAO,KAAK,SAAS,wBAAwB;AAAA,IACnF;AAEA,WAAO;AAAA,EACT;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,MAAM,CAAC;AACtE,cAAQ,KAAK,oDAAoD,WAAW,EAAE;AAAA,IAChF,SAAS,OAAO;AACd,cAAQ,MAAM,4DAA4D,KAAK;AAAA,IACjF;AAAA,EACF;AACF;","names":["import_utils"]}
|
|
@@ -26,7 +26,7 @@ var import_auth = require("firebase/auth");
|
|
|
26
26
|
var import_Base = require("./Base");
|
|
27
27
|
class SignIn extends import_Base.TernSecureBase {
|
|
28
28
|
pathRoot = "/sessions/createsession";
|
|
29
|
-
status;
|
|
29
|
+
status = null;
|
|
30
30
|
auth;
|
|
31
31
|
csrfToken;
|
|
32
32
|
_currentUser = null;
|
|
@@ -89,8 +89,7 @@ class SignIn extends import_Base.TernSecureBase {
|
|
|
89
89
|
if (redirectResult) {
|
|
90
90
|
return redirectResult;
|
|
91
91
|
}
|
|
92
|
-
await this._signInWithRedirect(provider, options);
|
|
93
|
-
return;
|
|
92
|
+
return await this._signInWithRedirect(provider, options);
|
|
94
93
|
} else {
|
|
95
94
|
return await this._signInWithPopUp(provider, options);
|
|
96
95
|
}
|
|
@@ -223,19 +222,13 @@ class SignIn extends import_Base.TernSecureBase {
|
|
|
223
222
|
try {
|
|
224
223
|
const config = this.getProviderConfig(providerName);
|
|
225
224
|
this.configureProvider(config.provider, options);
|
|
226
|
-
const
|
|
227
|
-
if (credential) {
|
|
228
|
-
return {
|
|
229
|
-
status: "success",
|
|
230
|
-
message: "Authentication successful",
|
|
231
|
-
user: credential.user,
|
|
232
|
-
providerId: credential.providerId,
|
|
233
|
-
operationType: credential.operationType
|
|
234
|
-
};
|
|
235
|
-
}
|
|
225
|
+
const { user, providerId, operationType } = await authMethod(this.auth, config.provider);
|
|
236
226
|
return {
|
|
237
227
|
status: "success",
|
|
238
|
-
message: "
|
|
228
|
+
message: "Authentication successful",
|
|
229
|
+
user,
|
|
230
|
+
providerId,
|
|
231
|
+
operationType
|
|
239
232
|
};
|
|
240
233
|
} catch (error) {
|
|
241
234
|
const authError = (0, import_errors.handleFirebaseAuthError)(error);
|
|
@@ -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 as SignInResponseFromTypes,\n SignInStatus,\n SocialProviderOptions,\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\n/**\n * Supported OAuth providers\n */\nexport type SupportedProvider =\n | 'google'\n | 'apple'\n | 'microsoft'\n | 'github'\n | 'twitter'\n | 'facebook'\n | string; // Allow custom providers like 'custom.provider.com'\n\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: SupportedProvider,\n options: SocialProviderOptions = {},\n ): Promise<SignInResponse | void> => {\n try {\n const { mode = 'popup' } = options;\n if (mode === 'redirect') {\n const redirectResult = await this.authRedirectResult();\n\n if (redirectResult) {\n return redirectResult;\n }\n\n await this._signInWithRedirect(provider, options);\n return;\n } else {\n return await this._signInWithPopUp(provider, options);\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: SupportedProvider): ProviderConfig {\n switch (providerName.toLowerCase()) {\n case 'google': {\n const googleProvider = new GoogleAuthProvider();\n return { provider: googleProvider };\n }\n case 'apple': {\n const appleProvider = new OAuthProvider('apple.com');\n return { provider: appleProvider };\n }\n case 'microsoft': {\n const microsoftProvider = new OAuthProvider('microsoft.com');\n return { provider: microsoftProvider };\n }\n case 'github': {\n const githubProvider = new OAuthProvider('github.com');\n return { provider: githubProvider };\n }\n case 'twitter': {\n const twitterProvider = new OAuthProvider('twitter.com');\n return { provider: twitterProvider };\n }\n case 'facebook': {\n const facebookProvider = new OAuthProvider('facebook.com');\n return { provider: facebookProvider };\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 /**\n * Sets custom OAuth parameters on the provider if provided by consumer\n * @param provider - Firebase auth provider instance\n * @param customParameters - Consumer-provided OAuth parameters\n */\n private setProviderCustomParameters(\n provider: GoogleAuthProvider | OAuthProvider,\n customParameters?: Record<string, string>,\n ): void {\n if (!customParameters || Object.keys(customParameters).length === 0) {\n return;\n }\n\n provider.setCustomParameters(customParameters);\n }\n\n /**\n * Adds OAuth scopes to the provider if provided by consumer\n * Handles provider-specific scope setting logic\n * @param provider - Firebase auth provider instance\n * @param scopes - Array of OAuth scopes to request\n */\n private setProviderScopes(provider: GoogleAuthProvider | OAuthProvider, scopes?: string[]): void {\n if (!scopes || scopes.length === 0) {\n return;\n }\n\n if (provider instanceof GoogleAuthProvider) {\n // Google provider supports individual scope addition\n scopes.forEach(scope => {\n (provider as GoogleAuthProvider).addScope(scope);\n });\n } else if (provider instanceof OAuthProvider) {\n // OAuth providers expect space-separated scope string\n (provider as OAuthProvider).addScope(scopes.join(' '));\n }\n }\n\n /**\n * Configures OAuth provider with consumer-provided options\n * @param provider - Firebase auth provider instance\n * @param options - Consumer options containing custom parameters and scopes\n */\n private configureProvider(\n provider: GoogleAuthProvider | OAuthProvider,\n options: SocialProviderOptions,\n ): void {\n this.setProviderCustomParameters(provider, options.customParameters);\n this.setProviderScopes(provider, options.scopes);\n }\n\n private executeAuthMethod = async (\n authMethod: AuthMethodFunction,\n providerName: SupportedProvider,\n options: SocialProviderOptions = {},\n ): Promise<SignInResponse> => {\n try {\n const config = this.getProviderConfig(providerName);\n\n this.configureProvider(config.provider, options);\n\n const credential = await authMethod(this.auth, config.provider);\n\n if (credential) {\n return {\n status: 'success',\n message: 'Authentication successful',\n user: credential.user,\n providerId: credential.providerId,\n operationType: credential.operationType,\n };\n }\n\n return {\n status: 'success',\n message: 'Redirect initiated',\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 private async _signInWithRedirect(\n providerName: SupportedProvider,\n options: SocialProviderOptions = {},\n ): Promise<SignInResponse> {\n return this.executeAuthMethod(signInWithRedirect, providerName, options);\n }\n\n private async _signInWithPopUp(\n providerName: SupportedProvider,\n options: SocialProviderOptions = {},\n ): Promise<SignInResponse> {\n return this.executeAuthMethod(signInWithPopup, providerName, options);\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 SocialProviderOptions,\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;\n\ntype AuthMethodFunction = (\n auth: Auth,\n provider: GoogleAuthProvider | OAuthProvider,\n) => Promise<FirebaseAuthResult>;\n\n/**\n * Supported OAuth providers\n */\nexport type SupportedProvider =\n | 'google'\n | 'apple'\n | 'microsoft'\n | 'github'\n | 'twitter'\n | 'facebook'\n | string; // Allow custom providers like 'custom.provider.com'\n\nexport class SignIn extends TernSecureBase implements SignInResource {\n pathRoot = '/sessions/createsession';\n\n status: SignInStatus | null = null;\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: SupportedProvider,\n options: SocialProviderOptions = {},\n ): Promise<SignInResponse> => {\n try {\n const { mode = 'popup' } = options;\n if (mode === 'redirect') {\n const redirectResult = await this.authRedirectResult();\n\n if (redirectResult) {\n return redirectResult;\n }\n\n return await this._signInWithRedirect(provider, options);\n } else {\n return await this._signInWithPopUp(provider, options);\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: SupportedProvider): ProviderConfig {\n switch (providerName.toLowerCase()) {\n case 'google': {\n const googleProvider = new GoogleAuthProvider();\n return { provider: googleProvider };\n }\n case 'apple': {\n const appleProvider = new OAuthProvider('apple.com');\n return { provider: appleProvider };\n }\n case 'microsoft': {\n const microsoftProvider = new OAuthProvider('microsoft.com');\n return { provider: microsoftProvider };\n }\n case 'github': {\n const githubProvider = new OAuthProvider('github.com');\n return { provider: githubProvider };\n }\n case 'twitter': {\n const twitterProvider = new OAuthProvider('twitter.com');\n return { provider: twitterProvider };\n }\n case 'facebook': {\n const facebookProvider = new OAuthProvider('facebook.com');\n return { provider: facebookProvider };\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 /**\n * Sets custom OAuth parameters on the provider if provided by consumer\n * @param provider - Firebase auth provider instance\n * @param customParameters - Consumer-provided OAuth parameters\n */\n private setProviderCustomParameters(\n provider: GoogleAuthProvider | OAuthProvider,\n customParameters?: Record<string, string>,\n ): void {\n if (!customParameters || Object.keys(customParameters).length === 0) {\n return;\n }\n\n provider.setCustomParameters(customParameters);\n }\n\n /**\n * Adds OAuth scopes to the provider if provided by consumer\n * Handles provider-specific scope setting logic\n * @param provider - Firebase auth provider instance\n * @param scopes - Array of OAuth scopes to request\n */\n private setProviderScopes(provider: GoogleAuthProvider | OAuthProvider, scopes?: string[]): void {\n if (!scopes || scopes.length === 0) {\n return;\n }\n\n if (provider instanceof GoogleAuthProvider) {\n // Google provider supports individual scope addition\n scopes.forEach(scope => {\n (provider as GoogleAuthProvider).addScope(scope);\n });\n } else if (provider instanceof OAuthProvider) {\n // OAuth providers expect space-separated scope string\n (provider as OAuthProvider).addScope(scopes.join(' '));\n }\n }\n\n /**\n * Configures OAuth provider with consumer-provided options\n * @param provider - Firebase auth provider instance\n * @param options - Consumer options containing custom parameters and scopes\n */\n private configureProvider(\n provider: GoogleAuthProvider | OAuthProvider,\n options: SocialProviderOptions,\n ): void {\n this.setProviderCustomParameters(provider, options.customParameters);\n this.setProviderScopes(provider, options.scopes);\n }\n\n private executeAuthMethod = async (\n authMethod: AuthMethodFunction,\n providerName: SupportedProvider,\n options: SocialProviderOptions = {},\n ): Promise<SignInResponse> => {\n try {\n const config = this.getProviderConfig(providerName);\n\n this.configureProvider(config.provider, options);\n\n const { user, providerId, operationType } = await authMethod(this.auth, config.provider);\n\n return {\n status: 'success',\n message: 'Authentication successful',\n user,\n providerId,\n operationType,\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 private async _signInWithRedirect(\n providerName: SupportedProvider,\n options: SocialProviderOptions = {},\n ): Promise<SignInResponse> {\n return this.executeAuthMethod(signInWithRedirect, providerName, options);\n }\n\n private async _signInWithPopUp(\n providerName: SupportedProvider,\n options: SocialProviderOptions = {},\n ): Promise<SignInResponse> {\n return this.executeAuthMethod(signInWithPopup, providerName, options);\n }\n\n public async checkRedirectResult(): Promise<SignInResponse | null> {\n return this.authRedirectResult();\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -213,6 +213,7 @@ function hasBannedProtocol(val) {
|
|
|
213
213
|
return BANNED_URI_PROTOCOLS.some((bp) => bp === protocol);
|
|
214
214
|
}
|
|
215
215
|
const isAllowedRedirect = (allowedRedirectOrigins, currentOrigin) => (_url) => {
|
|
216
|
+
if (!currentOrigin) return true;
|
|
216
217
|
let url = _url;
|
|
217
218
|
if (typeof url === "string") {
|
|
218
219
|
url = relativeToAbsoluteUrl(url, currentOrigin);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/construct.ts"],"sourcesContent":["import { camelToSnake } from '@tern-secure/shared/caseUtils';\nimport { globs } from '@tern-secure/shared/globs';\nimport { logger } from '@tern-secure/shared/logger';\n\nimport { joinPaths } from './path';\nimport { getQueryParams } from './querystring';\n\nconst DUMMY_URL_BASE = 'http://ternsecure-dummy';\n\nconst BANNED_URI_PROTOCOLS = ['javascript:'] as const;\n\nexport type constructUrlWithRedirectProps = {\n signInUrl: string;\n signInPathParam?: string;\n currentPath: string;\n signUpUrl?: string;\n signUpPathParam?: string;\n};\n\ninterface BuildURLParams extends Partial<URL> {\n base?: string;\n hashPath?: string;\n hashSearch?: string;\n hashSearchParams?:\n | URLSearchParams\n | Record<string, string>\n | Array<URLSearchParams | Record<string, string>>;\n}\n\ninterface BuildURLOptions<T> {\n skipOrigin?: boolean;\n stringify?: T;\n}\n\n/**\n *\n * buildURL(params: URLParams, options: BuildURLOptions): string\n *\n * Builds a URL safely by using the native URL() constructor. It can\n * also build a secondary path and search URL that lives inside the hash\n * of the main URL. For example:\n *\n * https://foo.com/bar?qux=42#/hash-bar?hash-qux=42\n *\n * References:\n * https://developer.mozilla.org/en-US/docs/Web/API/URL\n *\n * @param {BuildURLParams} params\n * @param {BuildURLOptions} options\n * @returns {URL | string} Returns the URL href\n */\nexport function buildURL<B extends boolean>(\n params: BuildURLParams,\n options?: BuildURLOptions<B>,\n): B extends true ? string : URL;\n\nexport function buildURL(\n params: BuildURLParams,\n options: BuildURLOptions<boolean> = {},\n): URL | string {\n const { base, hashPath, hashSearch, searchParams, hashSearchParams, ...rest } = params;\n\n let baseFallback = '';\n if (typeof window !== 'undefined' && !!window.location) {\n baseFallback = window.location.href;\n } else {\n baseFallback = 'http://react-native-fake-base-url';\n }\n\n const url = new URL(base || '', baseFallback);\n\n // Handle search parameters\n // params.searchParams comes from Partial<URL>, so it's URLSearchParams | undefined\n if (searchParams instanceof URLSearchParams) {\n searchParams.forEach((value, key) => {\n if (value !== null && value !== undefined) {\n url.searchParams.set(camelToSnake(key), value);\n }\n });\n }\n\n Object.assign(url, rest);\n\n // Handle hash-related parameters\n if (hashPath || hashSearch || hashSearchParams) {\n const dummyUrlForHash = new URL(DUMMY_URL_BASE + url.hash.substring(1));\n\n dummyUrlForHash.pathname = joinPaths(dummyUrlForHash.pathname, hashPath || '');\n\n const searchParamsFromHashSearchString = getQueryParams(hashSearch || '');\n\n for (const [key, val] of Object.entries(searchParamsFromHashSearchString)) {\n dummyUrlForHash.searchParams.append(key, val);\n }\n\n if (hashSearchParams) {\n const paramsArr = Array.isArray(hashSearchParams) ? hashSearchParams : [hashSearchParams];\n for (const _params of paramsArr) {\n if (!(_params instanceof URLSearchParams) && typeof _params !== 'object') {\n continue;\n }\n const params = new URLSearchParams(_params);\n params.forEach((value, key) => {\n if (value !== null && value !== undefined) {\n dummyUrlForHash.searchParams.set(camelToSnake(key), value);\n }\n });\n }\n }\n\n const newHash = dummyUrlForHash.href.replace(DUMMY_URL_BASE, '');\n if (newHash !== '/') {\n // Assign them to the hash of the main url\n url.hash = newHash;\n }\n }\n\n const { stringify, skipOrigin } = options;\n if (stringify) {\n return skipOrigin ? url.href.replace(url.origin, '') : url.href;\n }\n return url;\n}\n\n/**\n * Constructs a full URL with the current origin\n * @param path - The path to construct the URL for\n * @returns The full URL with origin\n */\nexport const constructFullUrl = (path: string) => {\n if (typeof window === 'undefined') return path;\n const baseUrl = window.location.origin;\n if (path.startsWith('http')) {\n return path;\n }\n return `${baseUrl}${path.startsWith('/') ? path : `/${path}`}`;\n};\n\n/**\n * Checks if the current URL has a redirect loop\n * @param currentPath - The current pathname\n * @param redirectPath - The path we're trying to redirect to\n * @returns boolean indicating if there's a redirect loop\n */\nexport const hasRedirectLoop = (currentPath: string, redirectPath: string): boolean => {\n if (!currentPath || !redirectPath) return false;\n\n // Remove any query parameters for comparison\n const cleanCurrentPath = currentPath.split('?')[0];\n const cleanRedirectPath = redirectPath.split('?')[0];\n\n return cleanCurrentPath === cleanRedirectPath;\n};\n\nexport const urlWithRedirect = (options: constructUrlWithRedirectProps): string => {\n const {\n signInUrl,\n signInPathParam = '/sign-in',\n currentPath,\n signUpUrl,\n signUpPathParam = '/sign-up',\n } = options;\n\n const baseUrl = window.location.origin;\n\n if (typeof window === 'undefined') {\n return signInUrl;\n }\n\n const url = new URL(signInUrl, baseUrl);\n\n if (!currentPath.includes(signInPathParam) && !currentPath.includes(signUpPathParam)) {\n url.searchParams.set('redirect', currentPath);\n }\n\n return url.toString();\n};\n\n/**\n * Stores the current path before signing out\n */\nexport const storePreviousPath = (path: string): void => {\n if (typeof window !== 'undefined') {\n sessionStorage.setItem('previousPath', path);\n }\n};\n\n/**\n * Gets the stored previous path\n */\nexport const getPreviousPath = (): string | null => {\n if (typeof window !== 'undefined') {\n return sessionStorage.getItem('previousPath');\n }\n return null;\n};\n\n/**\n * Gets a validated redirect URL ensuring it's from the same origin\n * @param redirectUrl - The URL to validate\n * @param searchParams - The search parameters to check for redirect\n * @returns A validated redirect URL\n */\nexport const getValidRedirectUrl = (\n searchParams: URLSearchParams,\n configuredRedirect?: string,\n): string => {\n // Check URL search param first (highest priority)\n const urlRedirect = searchParams.get('redirect');\n if (urlRedirect) {\n return validateUrl(urlRedirect);\n }\n\n // Then check configured redirect (for first visits)\n if (configuredRedirect) {\n return validateUrl(configuredRedirect);\n }\n\n // Default fallback\n return '/';\n};\n\n/**\n * Validates and sanitizes URLs\n */\nconst validateUrl = (url: string): string => {\n try {\n // For absolute URLs\n if (url.startsWith('http')) {\n const urlObj = new URL(url);\n if (typeof window !== 'undefined' && urlObj.origin !== window.location.origin) {\n return '/';\n }\n }\n\n // For relative URLs\n return '/';\n } catch {\n return '/';\n }\n};\n\nexport function toURL(url: string | URL): URL {\n return new URL(url.toString(), window.location.origin);\n}\n\n/**\n *\n * stripOrigin(url: URL | string): string\n *\n * Strips the origin part of a URL and preserves path, search and hash is applicable\n *\n * References:\n * https://developer.mozilla.org/en-US/docs/Web/API/URL\n *\n * @param {URL | string} url\n * @returns {string} Returns the URL href without the origin\n */\nexport function stripOrigin(url: URL | string): string {\n url = toURL(url);\n return url.href.replace(url.origin, '');\n}\n\n/**\n * trimTrailingSlash(path: string): string\n *\n * Strips the trailing slashes from a string\n *\n * @returns {string} Returns the string without trailing slashes\n * @param path\n */\nexport const trimTrailingSlash = (path: string): string => {\n return (path || '').replace(/\\/+$/, '');\n};\n\nexport function isValidUrl(val: unknown): val is string {\n if (!val) {\n return false;\n }\n\n try {\n new URL(val as string);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function relativeToAbsoluteUrl(url: string, origin: string | URL): URL {\n try {\n return new URL(url);\n } catch {\n return new URL(url, origin);\n }\n}\n\n// Regular expression to detect disallowed patterns\nconst disallowedPatterns = [\n /\\0/, // Null bytes\n /^\\/\\//, // Protocol-relative\n // eslint-disable-next-line no-control-regex\n /[\\x00-\\x1F]/, // Control characters\n];\n\n/**\n * Check for potentially problematic URLs that could have been crafted to intentionally bypass the origin check. Note that the URLs passed to this\n * function are assumed to be from an \"allowed origin\", so we are not executing origin-specific checks here.\n */\nexport function isProblematicUrl(url: URL): boolean {\n if (hasBannedProtocol(url)) {\n return true;\n }\n // Check against disallowed patterns\n for (const pattern of disallowedPatterns) {\n if (pattern.test(url.pathname)) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function hasBannedProtocol(val: string | URL) {\n if (!isValidUrl(val)) {\n return false;\n }\n const protocol = new URL(val).protocol;\n return BANNED_URI_PROTOCOLS.some(bp => bp === protocol);\n}\n\nexport const isAllowedRedirect =\n (allowedRedirectOrigins: Array<string | RegExp> | undefined, currentOrigin: string) =>\n (_url: URL | string) => {\n let url = _url;\n if (typeof url === 'string') {\n url = relativeToAbsoluteUrl(url, currentOrigin);\n }\n\n if (!allowedRedirectOrigins) {\n return true;\n }\n\n const isSameOrigin = currentOrigin === url.origin;\n\n const isAllowed =\n !isProblematicUrl(url) &&\n (isSameOrigin ||\n allowedRedirectOrigins\n .map(origin =>\n typeof origin === 'string' ? globs.toRegexp(trimTrailingSlash(origin)) : origin,\n )\n .some(origin => origin.test(trimTrailingSlash(url.origin))));\n\n if (!isAllowed) {\n logger.warnOnce(\n `Clerk: Redirect URL ${url} is not on one of the allowedRedirectOrigins, falling back to the default redirect URL.`,\n );\n }\n return isAllowed;\n };\n"],"mappings":"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","names":["params"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/construct.ts"],"sourcesContent":["import { camelToSnake } from '@tern-secure/shared/caseUtils';\nimport { globs } from '@tern-secure/shared/globs';\nimport { logger } from '@tern-secure/shared/logger';\n\nimport { joinPaths } from './path';\nimport { getQueryParams } from './querystring';\n\nconst DUMMY_URL_BASE = 'http://ternsecure-dummy';\n\nconst BANNED_URI_PROTOCOLS = ['javascript:'] as const;\n\nexport type constructUrlWithRedirectProps = {\n signInUrl: string;\n signInPathParam?: string;\n currentPath: string;\n signUpUrl?: string;\n signUpPathParam?: string;\n};\n\ninterface BuildURLParams extends Partial<URL> {\n base?: string;\n hashPath?: string;\n hashSearch?: string;\n hashSearchParams?:\n | URLSearchParams\n | Record<string, string>\n | Array<URLSearchParams | Record<string, string>>;\n}\n\ninterface BuildURLOptions<T> {\n skipOrigin?: boolean;\n stringify?: T;\n}\n\n/**\n *\n * buildURL(params: URLParams, options: BuildURLOptions): string\n *\n * Builds a URL safely by using the native URL() constructor. It can\n * also build a secondary path and search URL that lives inside the hash\n * of the main URL. For example:\n *\n * https://foo.com/bar?qux=42#/hash-bar?hash-qux=42\n *\n * References:\n * https://developer.mozilla.org/en-US/docs/Web/API/URL\n *\n * @param {BuildURLParams} params\n * @param {BuildURLOptions} options\n * @returns {URL | string} Returns the URL href\n */\nexport function buildURL<B extends boolean>(\n params: BuildURLParams,\n options?: BuildURLOptions<B>,\n): B extends true ? string : URL;\n\nexport function buildURL(\n params: BuildURLParams,\n options: BuildURLOptions<boolean> = {},\n): URL | string {\n const { base, hashPath, hashSearch, searchParams, hashSearchParams, ...rest } = params;\n\n let baseFallback = '';\n if (typeof window !== 'undefined' && !!window.location) {\n baseFallback = window.location.href;\n } else {\n baseFallback = 'http://react-native-fake-base-url';\n }\n\n const url = new URL(base || '', baseFallback);\n\n // Handle search parameters\n // params.searchParams comes from Partial<URL>, so it's URLSearchParams | undefined\n if (searchParams instanceof URLSearchParams) {\n searchParams.forEach((value, key) => {\n if (value !== null && value !== undefined) {\n url.searchParams.set(camelToSnake(key), value);\n }\n });\n }\n\n Object.assign(url, rest);\n\n // Handle hash-related parameters\n if (hashPath || hashSearch || hashSearchParams) {\n const dummyUrlForHash = new URL(DUMMY_URL_BASE + url.hash.substring(1));\n\n dummyUrlForHash.pathname = joinPaths(dummyUrlForHash.pathname, hashPath || '');\n\n const searchParamsFromHashSearchString = getQueryParams(hashSearch || '');\n\n for (const [key, val] of Object.entries(searchParamsFromHashSearchString)) {\n dummyUrlForHash.searchParams.append(key, val);\n }\n\n if (hashSearchParams) {\n const paramsArr = Array.isArray(hashSearchParams) ? hashSearchParams : [hashSearchParams];\n for (const _params of paramsArr) {\n if (!(_params instanceof URLSearchParams) && typeof _params !== 'object') {\n continue;\n }\n const params = new URLSearchParams(_params);\n params.forEach((value, key) => {\n if (value !== null && value !== undefined) {\n dummyUrlForHash.searchParams.set(camelToSnake(key), value);\n }\n });\n }\n }\n\n const newHash = dummyUrlForHash.href.replace(DUMMY_URL_BASE, '');\n if (newHash !== '/') {\n // Assign them to the hash of the main url\n url.hash = newHash;\n }\n }\n\n const { stringify, skipOrigin } = options;\n if (stringify) {\n return skipOrigin ? url.href.replace(url.origin, '') : url.href;\n }\n return url;\n}\n\n/**\n * Constructs a full URL with the current origin\n * @param path - The path to construct the URL for\n * @returns The full URL with origin\n */\nexport const constructFullUrl = (path: string) => {\n if (typeof window === 'undefined') return path;\n const baseUrl = window.location.origin;\n if (path.startsWith('http')) {\n return path;\n }\n return `${baseUrl}${path.startsWith('/') ? path : `/${path}`}`;\n};\n\n/**\n * Checks if the current URL has a redirect loop\n * @param currentPath - The current pathname\n * @param redirectPath - The path we're trying to redirect to\n * @returns boolean indicating if there's a redirect loop\n */\nexport const hasRedirectLoop = (currentPath: string, redirectPath: string): boolean => {\n if (!currentPath || !redirectPath) return false;\n\n // Remove any query parameters for comparison\n const cleanCurrentPath = currentPath.split('?')[0];\n const cleanRedirectPath = redirectPath.split('?')[0];\n\n return cleanCurrentPath === cleanRedirectPath;\n};\n\nexport const urlWithRedirect = (options: constructUrlWithRedirectProps): string => {\n const {\n signInUrl,\n signInPathParam = '/sign-in',\n currentPath,\n signUpUrl,\n signUpPathParam = '/sign-up',\n } = options;\n\n const baseUrl = window.location.origin;\n\n if (typeof window === 'undefined') {\n return signInUrl;\n }\n\n const url = new URL(signInUrl, baseUrl);\n\n if (!currentPath.includes(signInPathParam) && !currentPath.includes(signUpPathParam)) {\n url.searchParams.set('redirect', currentPath);\n }\n\n return url.toString();\n};\n\n/**\n * Stores the current path before signing out\n */\nexport const storePreviousPath = (path: string): void => {\n if (typeof window !== 'undefined') {\n sessionStorage.setItem('previousPath', path);\n }\n};\n\n/**\n * Gets the stored previous path\n */\nexport const getPreviousPath = (): string | null => {\n if (typeof window !== 'undefined') {\n return sessionStorage.getItem('previousPath');\n }\n return null;\n};\n\n/**\n * Gets a validated redirect URL ensuring it's from the same origin\n * @param redirectUrl - The URL to validate\n * @param searchParams - The search parameters to check for redirect\n * @returns A validated redirect URL\n */\nexport const getValidRedirectUrl = (\n searchParams: URLSearchParams,\n configuredRedirect?: string,\n): string => {\n // Check URL search param first (highest priority)\n const urlRedirect = searchParams.get('redirect');\n if (urlRedirect) {\n return validateUrl(urlRedirect);\n }\n\n // Then check configured redirect (for first visits)\n if (configuredRedirect) {\n return validateUrl(configuredRedirect);\n }\n\n // Default fallback\n return '/';\n};\n\n/**\n * Validates and sanitizes URLs\n */\nconst validateUrl = (url: string): string => {\n try {\n // For absolute URLs\n if (url.startsWith('http')) {\n const urlObj = new URL(url);\n if (typeof window !== 'undefined' && urlObj.origin !== window.location.origin) {\n return '/';\n }\n }\n\n // For relative URLs\n return '/';\n } catch {\n return '/';\n }\n};\n\nexport function toURL(url: string | URL): URL {\n return new URL(url.toString(), window.location.origin);\n}\n\n/**\n *\n * stripOrigin(url: URL | string): string\n *\n * Strips the origin part of a URL and preserves path, search and hash is applicable\n *\n * References:\n * https://developer.mozilla.org/en-US/docs/Web/API/URL\n *\n * @param {URL | string} url\n * @returns {string} Returns the URL href without the origin\n */\nexport function stripOrigin(url: URL | string): string {\n url = toURL(url);\n return url.href.replace(url.origin, '');\n}\n\n/**\n * trimTrailingSlash(path: string): string\n *\n * Strips the trailing slashes from a string\n *\n * @returns {string} Returns the string without trailing slashes\n * @param path\n */\nexport const trimTrailingSlash = (path: string): string => {\n return (path || '').replace(/\\/+$/, '');\n};\n\nexport function isValidUrl(val: unknown): val is string {\n if (!val) {\n return false;\n }\n\n try {\n new URL(val as string);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function relativeToAbsoluteUrl(url: string, origin: string | URL): URL {\n try {\n return new URL(url);\n } catch {\n return new URL(url, origin);\n }\n}\n\n// Regular expression to detect disallowed patterns\nconst disallowedPatterns = [\n /\\0/, // Null bytes\n /^\\/\\//, // Protocol-relative\n // eslint-disable-next-line no-control-regex\n /[\\x00-\\x1F]/, // Control characters\n];\n\n/**\n * Check for potentially problematic URLs that could have been crafted to intentionally bypass the origin check. Note that the URLs passed to this\n * function are assumed to be from an \"allowed origin\", so we are not executing origin-specific checks here.\n */\nexport function isProblematicUrl(url: URL): boolean {\n if (hasBannedProtocol(url)) {\n return true;\n }\n // Check against disallowed patterns\n for (const pattern of disallowedPatterns) {\n if (pattern.test(url.pathname)) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function hasBannedProtocol(val: string | URL) {\n if (!isValidUrl(val)) {\n return false;\n }\n const protocol = new URL(val).protocol;\n return BANNED_URI_PROTOCOLS.some(bp => bp === protocol);\n}\n\nexport const isAllowedRedirect =\n (allowedRedirectOrigins: Array<string | RegExp> | undefined, currentOrigin: string) =>\n (_url: URL | string) => {\n // On server-side (no origin), allow all redirects\n // They will be validated on client-side\n if (!currentOrigin) return true;\n\n let url = _url;\n if (typeof url === 'string') {\n url = relativeToAbsoluteUrl(url, currentOrigin);\n }\n\n if (!allowedRedirectOrigins) {\n return true;\n }\n\n const isSameOrigin = currentOrigin === url.origin;\n\n const isAllowed =\n !isProblematicUrl(url) &&\n (isSameOrigin ||\n allowedRedirectOrigins\n .map(origin =>\n typeof origin === 'string' ? globs.toRegexp(trimTrailingSlash(origin)) : origin,\n )\n .some(origin => origin.test(trimTrailingSlash(url.origin))));\n\n if (!isAllowed) {\n logger.warnOnce(\n `Clerk: Redirect URL ${url} is not on one of the allowedRedirectOrigins, falling back to the default redirect URL.`,\n );\n }\n return isAllowed;\n };\n"],"mappings":"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","names":["params"]}
|
|
@@ -140,6 +140,7 @@ class RedirectUrls {
|
|
|
140
140
|
}
|
|
141
141
|
#toAbsoluteUrls(obj) {
|
|
142
142
|
const origin = typeof window !== "undefined" ? window.location.origin : "";
|
|
143
|
+
if (!origin) return obj;
|
|
143
144
|
return (0, import_object.applyFunctionToObj)(obj, (url) => (0, import_construct.relativeToAbsoluteUrl)(url, origin));
|
|
144
145
|
}
|
|
145
146
|
#filterRedirects = (obj) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/redirectUrls.ts"],"sourcesContent":["import { camelToSnake } from '@tern-secure/shared/caseUtils';\nimport { applyFunctionToObj, filterProps, removeUndefined } from '@tern-secure/shared/object';\nimport type { RedirectOptions, TernSecureAuthOptions } from '@tern-secure/types';\n\nimport { isAllowedRedirect, relativeToAbsoluteUrl } from './construct';\n\n/**\n * RedirectUrls class handles all redirect URL construction logic\n * for sign-in, sign-up, and post-authentication flows.\n *\n * This class centralizes the redirect logic previously scattered across\n * multiple methods, making it reusable and maintainable.\n */\nexport class RedirectUrls {\n private static keys: (keyof RedirectOptions)[] = [\n 'signInForceRedirectUrl',\n 'signInFallbackRedirectUrl',\n 'signUpForceRedirectUrl',\n 'signUpFallbackRedirectUrl',\n 'afterSignInUrl',\n 'afterSignUpUrl',\n 'redirectUrl',\n ];\n\n private static preserved = ['redirectUrl'];\n\n private readonly options: TernSecureAuthOptions;\n private readonly fromOptions: RedirectOptions;\n private readonly fromProps: RedirectOptions;\n private readonly fromSearchParams: RedirectOptions & { redirectUrl?: string | null };\n\n constructor(options: TernSecureAuthOptions, props: RedirectOptions = {}, searchParams: any = {}) {\n this.options = options;\n this.fromOptions = this.#parse(options || {});\n this.fromProps = this.#parse(props || {});\n this.fromSearchParams = this.#parseSearchParams(searchParams || {});\n }\n\n getAfterSignInUrl() {\n return this.#getRedirectUrl('signIn');\n }\n\n getAfterSignUpUrl() {\n return this.#getRedirectUrl('signUp');\n }\n\n getPreservedSearchParams() {\n return this.#toSearchParams(this.#flattenPreserved());\n }\n\n toSearchParams() {\n return this.#toSearchParams(this.#flattenAll());\n }\n\n #toSearchParams(obj: Record<string, string | undefined | null>): URLSearchParams {\n const camelCased = Object.fromEntries(\n Object.entries(obj).map(([key, value]) => [camelToSnake(key), value]),\n );\n return new URLSearchParams(removeUndefined(camelCased) as Record<string, string>);\n }\n\n #flattenPreserved() {\n return Object.fromEntries(\n Object.entries({ ...this.fromSearchParams }).filter(([key]) =>\n RedirectUrls.preserved.includes(key),\n ),\n );\n }\n\n #flattenAll() {\n const signUpForceRedirectUrl =\n this.fromSearchParams.signUpForceRedirectUrl ||\n this.fromProps.signUpForceRedirectUrl ||\n this.fromOptions.signUpForceRedirectUrl;\n const signUpFallbackRedirectUrl =\n this.fromSearchParams.signUpFallbackRedirectUrl ||\n this.fromProps.signUpFallbackRedirectUrl ||\n this.fromOptions.signUpFallbackRedirectUrl;\n const signInForceRedirectUrl =\n this.fromSearchParams.signInForceRedirectUrl ||\n this.fromProps.signInForceRedirectUrl ||\n this.fromOptions.signInForceRedirectUrl;\n const signInFallbackRedirectUrl =\n this.fromSearchParams.signInFallbackRedirectUrl ||\n this.fromProps.signInFallbackRedirectUrl ||\n this.fromOptions.signInFallbackRedirectUrl;\n const afterSignInUrl =\n this.fromSearchParams.afterSignInUrl ||\n this.fromProps.afterSignInUrl ||\n this.fromOptions.afterSignInUrl;\n const afterSignUpUrl =\n this.fromSearchParams.afterSignUpUrl ||\n this.fromProps.afterSignUpUrl ||\n this.fromOptions.afterSignUpUrl;\n const redirectUrl =\n this.fromSearchParams.redirectUrl ||\n this.fromProps.redirectUrl ||\n this.fromOptions.redirectUrl;\n\n const res: RedirectOptions = {\n signUpForceRedirectUrl,\n signUpFallbackRedirectUrl,\n signInForceRedirectUrl,\n signInFallbackRedirectUrl,\n afterSignInUrl,\n afterSignUpUrl,\n redirectUrl,\n };\n return res;\n }\n\n #getRedirectUrl(prefix: 'signIn' | 'signUp') {\n const forceKey = `${prefix}ForceRedirectUrl` as const;\n const fallbackKey = `${prefix}FallbackRedirectUrl` as const;\n\n let newKeyInUse: string | undefined;\n\n let result;\n // Prioritize forceRedirectUrl\n result =\n this.fromSearchParams[forceKey] || this.fromProps[forceKey] || this.fromOptions[forceKey];\n if (result) {\n newKeyInUse = forceKey;\n }\n\n // Try to get redirect_url, only allowed as a search param\n result ||= this.fromSearchParams.redirectUrl;\n if (result) {\n newKeyInUse = 'redirectUrl';\n }\n\n // Otherwise, fallback to fallbackRedirectUrl\n result ||=\n this.fromSearchParams[fallbackKey] ||\n this.fromProps[fallbackKey] ||\n this.fromOptions[fallbackKey];\n if (result) {\n newKeyInUse = fallbackKey;\n }\n\n if (!result) {\n if (typeof window === 'undefined') {\n return '/';\n }\n return window.location.href;\n }\n return result || '/';\n }\n\n #parse(obj: unknown) {\n const res = {} as RedirectOptions;\n RedirectUrls.keys.forEach(key => {\n // @ts-expect-error\n res[key] = obj[key];\n });\n\n //const absoluteUrls = this.#toAbsoluteUrls(filterProps(res, Boolean));\n //const filtered = this.#filterRedirects(absoluteUrls);\n //return applyFunctionToObj(filtered, val => val.toString());\n\n return applyFunctionToObj(\n this.#filterRedirects(this.#toAbsoluteUrls(filterProps(res, Boolean))),\n val => val.toString(),\n );\n }\n\n #parseSearchParams(obj: any) {\n const res = {} as typeof this.fromSearchParams;\n RedirectUrls.keys.forEach(key => {\n if (obj instanceof URLSearchParams) {\n res[key] = obj.get(camelToSnake(key));\n } else {\n res[key] = obj[camelToSnake(key)];\n }\n });\n\n return applyFunctionToObj(\n this.#filterRedirects(this.#toAbsoluteUrls(filterProps(res, Boolean))),\n val => val.toString(),\n );\n }\n\n #toAbsoluteUrls(obj: RedirectOptions) {\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n return applyFunctionToObj(obj, (url: string) => relativeToAbsoluteUrl(url, origin));\n }\n\n #filterRedirects = (obj: RedirectOptions) => {\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n return filterProps(obj, isAllowedRedirect(this.options?.allowedRedirectOrigins, origin));\n };\n}\n"],"mappings":"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
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/redirectUrls.ts"],"sourcesContent":["import { camelToSnake } from '@tern-secure/shared/caseUtils';\nimport { applyFunctionToObj, filterProps, removeUndefined } from '@tern-secure/shared/object';\nimport type { RedirectOptions, TernSecureAuthOptions } from '@tern-secure/types';\n\nimport { isAllowedRedirect, relativeToAbsoluteUrl } from './construct';\n\n/**\n * RedirectUrls class handles all redirect URL construction logic\n * for sign-in, sign-up, and post-authentication flows.\n *\n * This class centralizes the redirect logic previously scattered across\n * multiple methods, making it reusable and maintainable.\n */\nexport class RedirectUrls {\n private static keys: (keyof RedirectOptions)[] = [\n 'signInForceRedirectUrl',\n 'signInFallbackRedirectUrl',\n 'signUpForceRedirectUrl',\n 'signUpFallbackRedirectUrl',\n 'afterSignInUrl',\n 'afterSignUpUrl',\n 'redirectUrl',\n ];\n\n private static preserved = ['redirectUrl'];\n\n private readonly options: TernSecureAuthOptions;\n private readonly fromOptions: RedirectOptions;\n private readonly fromProps: RedirectOptions;\n private readonly fromSearchParams: RedirectOptions & { redirectUrl?: string | null };\n\n constructor(options: TernSecureAuthOptions, props: RedirectOptions = {}, searchParams: any = {}) {\n this.options = options;\n this.fromOptions = this.#parse(options || {});\n this.fromProps = this.#parse(props || {});\n this.fromSearchParams = this.#parseSearchParams(searchParams || {});\n }\n\n getAfterSignInUrl() {\n return this.#getRedirectUrl('signIn');\n }\n\n getAfterSignUpUrl() {\n return this.#getRedirectUrl('signUp');\n }\n\n getPreservedSearchParams() {\n return this.#toSearchParams(this.#flattenPreserved());\n }\n\n toSearchParams() {\n return this.#toSearchParams(this.#flattenAll());\n }\n\n #toSearchParams(obj: Record<string, string | undefined | null>): URLSearchParams {\n const camelCased = Object.fromEntries(\n Object.entries(obj).map(([key, value]) => [camelToSnake(key), value]),\n );\n return new URLSearchParams(removeUndefined(camelCased) as Record<string, string>);\n }\n\n #flattenPreserved() {\n return Object.fromEntries(\n Object.entries({ ...this.fromSearchParams }).filter(([key]) =>\n RedirectUrls.preserved.includes(key),\n ),\n );\n }\n\n #flattenAll() {\n const signUpForceRedirectUrl =\n this.fromSearchParams.signUpForceRedirectUrl ||\n this.fromProps.signUpForceRedirectUrl ||\n this.fromOptions.signUpForceRedirectUrl;\n const signUpFallbackRedirectUrl =\n this.fromSearchParams.signUpFallbackRedirectUrl ||\n this.fromProps.signUpFallbackRedirectUrl ||\n this.fromOptions.signUpFallbackRedirectUrl;\n const signInForceRedirectUrl =\n this.fromSearchParams.signInForceRedirectUrl ||\n this.fromProps.signInForceRedirectUrl ||\n this.fromOptions.signInForceRedirectUrl;\n const signInFallbackRedirectUrl =\n this.fromSearchParams.signInFallbackRedirectUrl ||\n this.fromProps.signInFallbackRedirectUrl ||\n this.fromOptions.signInFallbackRedirectUrl;\n const afterSignInUrl =\n this.fromSearchParams.afterSignInUrl ||\n this.fromProps.afterSignInUrl ||\n this.fromOptions.afterSignInUrl;\n const afterSignUpUrl =\n this.fromSearchParams.afterSignUpUrl ||\n this.fromProps.afterSignUpUrl ||\n this.fromOptions.afterSignUpUrl;\n const redirectUrl =\n this.fromSearchParams.redirectUrl ||\n this.fromProps.redirectUrl ||\n this.fromOptions.redirectUrl;\n\n const res: RedirectOptions = {\n signUpForceRedirectUrl,\n signUpFallbackRedirectUrl,\n signInForceRedirectUrl,\n signInFallbackRedirectUrl,\n afterSignInUrl,\n afterSignUpUrl,\n redirectUrl,\n };\n return res;\n }\n\n #getRedirectUrl(prefix: 'signIn' | 'signUp') {\n const forceKey = `${prefix}ForceRedirectUrl` as const;\n const fallbackKey = `${prefix}FallbackRedirectUrl` as const;\n\n let newKeyInUse: string | undefined;\n\n let result;\n // Prioritize forceRedirectUrl\n result =\n this.fromSearchParams[forceKey] || this.fromProps[forceKey] || this.fromOptions[forceKey];\n if (result) {\n newKeyInUse = forceKey;\n }\n\n // Try to get redirect_url, only allowed as a search param\n result ||= this.fromSearchParams.redirectUrl;\n if (result) {\n newKeyInUse = 'redirectUrl';\n }\n\n // Otherwise, fallback to fallbackRedirectUrl\n result ||=\n this.fromSearchParams[fallbackKey] ||\n this.fromProps[fallbackKey] ||\n this.fromOptions[fallbackKey];\n if (result) {\n newKeyInUse = fallbackKey;\n }\n\n if (!result) {\n if (typeof window === 'undefined') {\n return '/';\n }\n return window.location.href;\n }\n return result || '/';\n }\n\n #parse(obj: unknown) {\n const res = {} as RedirectOptions;\n RedirectUrls.keys.forEach(key => {\n // @ts-expect-error\n res[key] = obj[key];\n });\n\n //const absoluteUrls = this.#toAbsoluteUrls(filterProps(res, Boolean));\n //const filtered = this.#filterRedirects(absoluteUrls);\n //return applyFunctionToObj(filtered, val => val.toString());\n\n return applyFunctionToObj(\n this.#filterRedirects(this.#toAbsoluteUrls(filterProps(res, Boolean))),\n val => val.toString(),\n );\n }\n\n #parseSearchParams(obj: any) {\n const res = {} as typeof this.fromSearchParams;\n RedirectUrls.keys.forEach(key => {\n if (obj instanceof URLSearchParams) {\n res[key] = obj.get(camelToSnake(key));\n } else {\n res[key] = obj[camelToSnake(key)];\n }\n });\n\n return applyFunctionToObj(\n this.#filterRedirects(this.#toAbsoluteUrls(filterProps(res, Boolean))),\n val => val.toString(),\n );\n }\n\n #toAbsoluteUrls(obj: RedirectOptions) {\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n // If no origin (server-side), return URLs as-is without conversion\n // They will be properly converted on the client-side\n if (!origin) return obj;\n\n return applyFunctionToObj(obj, (url: string) => relativeToAbsoluteUrl(url, origin));\n }\n\n #filterRedirects = (obj: RedirectOptions) => {\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n return filterProps(obj, isAllowedRedirect(this.options?.allowedRedirectOrigins, origin));\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export { TernSecureAuth } from './instance/TernAuth';\nexport type { TernAuth } from './instance/TernAuth';\nexport { TernServerAuth } from './instance/TernAuthServer';\nexport type { TernServerAuthOptions, AuthenticatedApp } from './instance/TernAuthServer';\n\nexport { CoreApiClient, coreApiClient } from './instance/coreApiClient';\nexport type { \n ApiResponse, \n ApiResponseJSON, \n RequestOptions,\n BeforeRequestHook,\n AfterResponseHook\n} from './instance/coreApiClient';\n\nexport { SignIn, TernSecureBase, buildURL } from './resources/internal';\n\nexport type {\n AuthErrorTree,\n TernSecureConfig,\n SignInFormValues,\n SignInProps,\n SignUpProps,\n SignInResponse,\n SignInForceRedirectUrl,\n SignUpForceRedirectUrl,\n ResendEmailVerification,\n TernSecureUser,\n TernSecureState\n} from '@tern-secure/types';\n\nexport { RedirectUrls } from './utils/redirectUrls';"],"mappings":"AAAA,SAAS,sBAAsB;AAE/B,SAAS,sBAAsB;AAG/B,SAAS,eAAe,qBAAqB;AAS7C,SAAS,QAAQ,gBAAgB,gBAAgB;
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export { TernSecureAuth } from './instance/TernAuth';\nexport type { TernAuth } from './instance/TernAuth';\nexport { TernServerAuth } from './instance/TernAuthServer';\nexport type { TernServerAuthOptions, AuthenticatedApp } from './instance/TernAuthServer';\n\nexport { CoreApiClient, coreApiClient } from './instance/coreApiClient';\nexport type { \n ApiResponse, \n ApiResponseJSON, \n RequestOptions,\n BeforeRequestHook,\n AfterResponseHook\n} from './instance/coreApiClient';\n\nexport { SignIn, TernSecureBase, buildURL } from './resources/internal';\n\nexport type {\n AuthErrorTree,\n TernSecureConfig,\n SignInFormValues,\n SignInProps,\n SignUpProps,\n SignInResponse,\n SignInForceRedirectUrl,\n SignUpForceRedirectUrl,\n SignInFallbackRedirectUrl,\n ResendEmailVerification,\n TernSecureUser,\n TernSecureState\n} from '@tern-secure/types';\n\nexport { RedirectUrls } from './utils/redirectUrls';"],"mappings":"AAAA,SAAS,sBAAsB;AAE/B,SAAS,sBAAsB;AAG/B,SAAS,eAAe,qBAAqB;AAS7C,SAAS,QAAQ,gBAAgB,gBAAgB;AAiBjD,SAAS,oBAAoB;","names":[]}
|
|
@@ -27,10 +27,10 @@ function inBrowser() {
|
|
|
27
27
|
return typeof window !== "undefined";
|
|
28
28
|
}
|
|
29
29
|
class TernSecureAuth {
|
|
30
|
-
static version = "1.1.0-canary.
|
|
30
|
+
static version = "1.1.0-canary.v20251024005655";
|
|
31
31
|
static sdkMetadata = {
|
|
32
32
|
name: "@tern-secure/auth",
|
|
33
|
-
version: "1.1.0-canary.
|
|
33
|
+
version: "1.1.0-canary.v20251024005655",
|
|
34
34
|
environment: process.env.NODE_ENV || "production"
|
|
35
35
|
};
|
|
36
36
|
static instance = null;
|
|
@@ -311,7 +311,7 @@ class TernSecureAuth {
|
|
|
311
311
|
this.signedInSession = null;
|
|
312
312
|
}
|
|
313
313
|
}
|
|
314
|
-
async
|
|
314
|
+
checkRedirectResult = async () => {
|
|
315
315
|
try {
|
|
316
316
|
const result = await getRedirectResult(this.auth);
|
|
317
317
|
if (result) {
|
|
@@ -329,9 +329,9 @@ class TernSecureAuth {
|
|
|
329
329
|
error: authError.code
|
|
330
330
|
};
|
|
331
331
|
}
|
|
332
|
-
}
|
|
332
|
+
};
|
|
333
333
|
getRedirectResult = async () => {
|
|
334
|
-
|
|
334
|
+
return this.checkRedirectResult();
|
|
335
335
|
};
|
|
336
336
|
addListener = (listener) => {
|
|
337
337
|
this.#listeners.push(listener);
|
|
@@ -531,7 +531,7 @@ class TernSecureAuth {
|
|
|
531
531
|
}
|
|
532
532
|
const emulatorUrl = host.startsWith("http") ? host : `http://${host}`;
|
|
533
533
|
try {
|
|
534
|
-
connectAuthEmulator(this.auth, emulatorUrl, { disableWarnings:
|
|
534
|
+
connectAuthEmulator(this.auth, emulatorUrl, { disableWarnings: false });
|
|
535
535
|
console.warn(`[TernSecure] Firebase Auth Emulator connected at ${emulatorUrl}`);
|
|
536
536
|
} catch (error) {
|
|
537
537
|
console.error("[TernSecure] Error connecting to Firebase Auth Emulator:", error);
|
|
@@ -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 CreateActiveSession,\n DomainOrProxyUrl,\n InstanceType,\n ListenerCallback,\n NavigateOptions,\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 browserPopupRedirectResolver,\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 { ALLOWED_PROTOCOLS, buildURL, stripOrigin, windowNavigate } from '../utils/';\nimport { RedirectUrls } from '../utils/redirectUrls';\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 | null | undefined;\n signUp!: SignUpResource | null | undefined;\n session!: SessionResource | null | undefined;\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 = async (options?: TernSecureAuthOptions): Promise<void> => {\n void this.#initialize(options || {});\n };\n\n public static create(options: TernSecureAuthOptions): TernSecureAuth {\n const instance = this.getOrCreateInstance();\n void instance.initialize(options);\n return instance;\n }\n\n #initialize = (options: TernSecureAuthOptions): void => {\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 popupRedirectResolver: browserPopupRedirectResolver,\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 * 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 * @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('[ternauth] Error during client auth request initialization:', error);\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 \n await this.navigate(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\n if (redirectUrl) {\n await this.navigate(this.constructUrlWithAuthRedirect(redirectUrl));\n }\n\n this.#setCreatedActiveSession(session);\n this.#emit();\n } catch (error) {\n console.error('[TernSecureAuth] Error creating active session:', error);\n }\n };\n\n public navigate = async (to: string | undefined, options?: NavigateOptions): Promise<unknown> => {\n if (!to || !inBrowser()) {\n return;\n }\n\n let toURL = new URL(to, window.location.href);\n\n if (!this.#allowedRedirectProtocols.includes(toURL.protocol)) {\n console.warn(\n `TernSecureAuth: \"${toURL.protocol}\" is not a valid protocol. Redirecting to \"/\" instead. If you think this is a mistake, please open an issue.`,\n );\n toURL = new URL('/', window.location.href);\n }\n\n const customNavigate =\n options?.replace && this.#options.routerReplace\n ? this.#options.routerReplace\n : this.#options.routerPush;\n\n if ((toURL.origin !== 'null' && toURL.origin !== window.location.origin) || !customNavigate) {\n windowNavigate(toURL);\n return;\n }\n\n const metadata = {\n ...(options?.metadata ? { __internal_metadata: options?.metadata } : {}),\n windowNavigate,\n };\n\n // React router only wants the path, search or hash portion.\n return await customNavigate(stripOrigin(toURL), metadata);\n };\n\n public constructUrlWithAuthRedirect = (to: string): string => {\n if (this.#instanceType === 'production') {\n return to;\n }\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 const redirectUrls = new RedirectUrls(this.#options, options).toSearchParams();\n const constructedUrl = buildURL(\n {\n base,\n hashSearchParams: [redirectUrls],\n },\n {\n stringify: true,\n skipOrigin: false,\n },\n );\n return this.constructUrlWithAuthRedirect(constructedUrl);\n };\n\n #constructAfterSignInUrl = (): string => {\n return this.constructUrlWithAuthRedirect(new RedirectUrls(this.#options).getAfterSignInUrl());\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 return this.navigate(this.constructSignInUrl(options));\n }\n return;\n };\n\n public redirectToSignUp = async (options?: SignUpRedirectOptions): Promise<unknown> => {\n if (inBrowser()) {\n return this.navigate(this.constructSignUpUrl());\n }\n return;\n };\n\n public redirectAfterSignIn = async (): Promise<unknown> => {\n if (inBrowser()) {\n return this.navigate(this.#constructAfterSignInUrl());\n }\n return;\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', {\n ...options,\n signInForceRedirectUrl: options?.signInForceRedirectUrl || window.location.href,\n });\n };\n\n public constructSignUpUrl = (options?: SignUpRedirectOptions): string => {\n return this.#buildUrl('signUpUrl', {\n ...options,\n signUpForceRedirectUrl: options?.signUpForceRedirectUrl || window.location.href,\n });\n };\n\n get #allowedRedirectProtocols() {\n let allowedProtocols = ALLOWED_PROTOCOLS;\n\n if (this.#options.allowedRedirectProtocols) {\n allowedProtocols = allowedProtocols.concat(this.#options.allowedRedirectProtocols);\n }\n\n return allowedProtocols;\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,SAAS,+BAA+B;AACxC,SAAS,wBAAwB,kBAAkB;AACnD,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AA4BhC,SAAS,SAAS,qBAAqB;AAEvC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,wBAAwB;AAEjC,SAAiC,+BAA+B;AAChE,SAAS,mBAAmB,SAAS,QAAQ,QAAQ,sBAAsB;AAC3E,SAAS,mBAAmB,UAAU,aAAa,sBAAsB;AACzE,SAAS,oBAAoB;AAC7B,SAAyB,2BAA2B;AACpD,SAAS,UAAU,cAAc;AACjC,SAAS,2BAA2B;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,kBAAkB,uBAAuB;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,uBAAuB;AAAA,QAC3B,gBAAgB,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;AA9ItD;AA+II,SAAK,WAAU,wCAAS,qBAAT,mBAA2B;AAC1C,SAAK,WAAU,mCAAS,WAAU;AAClC,SAAK,gBAAiB,QAAQ,IAAI,YAA6B;AAE/D,SAAK,aAAa,oBAAoB;AAAA,MACpC,QAAQ,KAAK;AAAA,MACb,QAAQ,mCAAS;AAAA,MACjB,cAAc,KAAK;AAAA,IACrB,CAAC;AAED,SAAK,gBAAgB,KAAK,WAAW,QAAQ,SAAS;AACtD,mBAAe,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,aAAa,OAAO,YAAmD;AACrE,SAAK,KAAK,YAAY,WAAW,CAAC,CAAC;AAAA,EACrC;AAAA,EAEA,OAAc,OAAO,SAAgD;AACnE,UAAM,WAAW,KAAK,oBAAoB;AAC1C,SAAK,SAAS,WAAW,OAAO;AAChC,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,CAAC,YAAyC;AACtD,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,kBAAkB;AAChD,WAAK,YAAY,KAAK,mBAAmB,aAAa;AAEtD,WAAK,qBAAqB,wBAAwB;AAElD,WAAK,SAAS,IAAI,OAAO,KAAK,MAAM,KAAK,SAAS;AAClD,WAAK,SAAS,IAAI,OAAO,KAAK,IAAI;AAElC,eAAS,GAAG,OAAO,gBAAgB,MAAM;AACvC,aAAK,yBAAyB,KAAK,QAAQ,IAAI;AAC/C,aAAK,MAAM;AAAA,MACb,CAAC;AAED,WAAK,WAAW,OAAO;AACvB,WAAK,gBAAgB,KAAK,WAAW,QAAQ,OAAO;AAAA,IAGtD,SAAS,OAAO;AACd,WAAK,QAAQ;AACb,WAAK,WAAW,OAAO;AACvB,WAAK,gBAAgB,KAAK,WAAW,QAAQ,OAAO;AACpD,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,sBAAsB,QAA0B;AACtD,UAAM,UAAU,OAAO,WAAW;AAClC,SAAK,oBAAoB,QAAQ,EAAE,WAAW,IAAI,cAAc,QAAQ,OAAO,IAAI,QAAQ,EAAE,CAAC;AAE9F,UAAM,cAAc,KAAK,gBAAgB;AACzC,UAAM,OAAO,eAAe,KAAK,mBAAmB;AAAA,MAClD;AAAA,MACA,uBAAuB;AAAA,IACzB,CAAC;AAED,SAAK,OAAO;AAEZ,QAAI,OAAO,UAAU;AACnB,WAAK,KAAK,WAAW,OAAO;AAAA,IAC9B;AAEA,SAAK,mBAAmB;AAExB,qBAAiB,KAAK,iBAAiB;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,MAAM;AAlSrB;AAmSI,UAAM,mBAAkB,UAAK,uBAAL,mBAAyB;AACjD,UAAM,YAAY,oBAAoB,mBAAmB,IAAI;AAC7D,SAAK,OAAO;AACZ,SAAK,MAAM;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,wBAAwB,MAAM;AA5ShC;AA6SI,eAAK,uBAAL,mBACI,uBACD,KAAK,qBAAmB;AACvB,YAAM,EAAE,MAAM,IAAI;AAClB,YAAM,YAAY,oBAAoB,SAAS,IAAI;AACnD,WAAK,OAAO;AACZ,WAAK,MAAM;AAAA,IACb,GACC,MAAM,WAAS;AACd,cAAQ,MAAM,+DAA+D,KAAK;AAClF,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;AAEA,UAAM,KAAK,SAAS,WAAW;AAE/B,aAAS,KAAK,OAAO,aAAa,IAAI;AACtC,aAAS,KAAK,OAAO,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,WAAO,mBAAmB,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,WAAO,iBAAiB,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,WAAO,WAAW,KAAK,KAAK,WAAW;AAAA,EACzC;AAAA,EAEO,mBAAmB,UAAyC;AACjE,WAAO,mBAAmB,KAAK,MAAM,QAAQ;AAAA,EAC/C;AAAA,EAEO,iBAAiB,UAAyC;AAC/D,WAAO,iBAAiB,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,MAAM,kBAAkB,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,YAAY,wBAAwB,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,QAAQ,aAAa;AAC7C,YAAM,YAAY,OAAO,KAAK,aAAa,EAAE;AAE7C,UAAI,aAAa;AACf,cAAM,KAAK,SAAS,KAAK,6BAA6B,WAAW,CAAC;AAAA,MACpE;AAEA,WAAK,yBAAyB,OAAO;AACrC,WAAK,MAAM;AAAA,IACb,SAAS,OAAO;AACd,cAAQ,MAAM,mDAAmD,KAAK;AAAA,IACxE;AAAA,EACF;AAAA,EAEO,WAAW,OAAO,IAAwB,YAAgD;AAC/F,QAAI,CAAC,MAAM,CAAC,UAAU,GAAG;AACvB;AAAA,IACF;AAEA,QAAI,QAAQ,IAAI,IAAI,IAAI,OAAO,SAAS,IAAI;AAE5C,QAAI,CAAC,KAAK,0BAA0B,SAAS,MAAM,QAAQ,GAAG;AAC5D,cAAQ;AAAA,QACN,oBAAoB,MAAM,QAAQ;AAAA,MACpC;AACA,cAAQ,IAAI,IAAI,KAAK,OAAO,SAAS,IAAI;AAAA,IAC3C;AAEA,UAAM,kBACJ,mCAAS,YAAW,KAAK,SAAS,gBAC9B,KAAK,SAAS,gBACd,KAAK,SAAS;AAEpB,QAAK,MAAM,WAAW,UAAU,MAAM,WAAW,OAAO,SAAS,UAAW,CAAC,gBAAgB;AAC3F,qBAAe,KAAK;AACpB;AAAA,IACF;AAEA,UAAM,WAAW;AAAA,MACf,IAAI,mCAAS,YAAW,EAAE,qBAAqB,mCAAS,SAAS,IAAI,CAAC;AAAA,MACtE;AAAA,IACF;AAGA,WAAO,MAAM,eAAe,YAAY,KAAK,GAAG,QAAQ;AAAA,EAC1D;AAAA,EAEO,+BAA+B,CAAC,OAAuB;AAC5D,QAAI,KAAK,kBAAkB,cAAc;AACvC,aAAO;AAAA,IACT;AACA,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;AAChF,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,UAAM,eAAe,IAAI,aAAa,KAAK,UAAU,OAAO,EAAE,eAAe;AAC7E,UAAM,iBAAiB;AAAA,MACrB;AAAA,QACE;AAAA,QACA,kBAAkB,CAAC,YAAY;AAAA,MACjC;AAAA,MACA;AAAA,QACE,WAAW;AAAA,QACX,YAAY;AAAA,MACd;AAAA,IACF;AACA,WAAO,KAAK,6BAA6B,cAAc;AAAA,EACzD;AAAA,EAEA,2BAA2B,MAAc;AACvC,WAAO,KAAK,6BAA6B,IAAI,aAAa,KAAK,QAAQ,EAAE,kBAAkB,CAAC;AAAA,EAC9F;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,aAAO,KAAK,SAAS,KAAK,mBAAmB,OAAO,CAAC;AAAA,IACvD;AACA;AAAA,EACF;AAAA,EAEO,mBAAmB,OAAO,YAAsD;AACrF,QAAI,UAAU,GAAG;AACf,aAAO,KAAK,SAAS,KAAK,mBAAmB,CAAC;AAAA,IAChD;AACA;AAAA,EACF;AAAA,EAEO,sBAAsB,YAA8B;AACzD,QAAI,UAAU,GAAG;AACf,aAAO,KAAK,SAAS,KAAK,yBAAyB,CAAC;AAAA,IACtD;AACA;AAAA,EACF;AAAA,EAEA,sBAAsB,MAAY;AAChC,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AAAA,EAEO,qBAAqB,CAAC,YAA4C;AACvE,WAAO,KAAK,UAAU,aAAa;AAAA,MACjC,GAAG;AAAA,MACH,yBAAwB,mCAAS,2BAA0B,OAAO,SAAS;AAAA,IAC7E,CAAC;AAAA,EACH;AAAA,EAEO,qBAAqB,CAAC,YAA4C;AACvE,WAAO,KAAK,UAAU,aAAa;AAAA,MACjC,GAAG;AAAA,MACH,yBAAwB,mCAAS,2BAA0B,OAAO,SAAS;AAAA,IAC7E,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,4BAA4B;AAC9B,QAAI,mBAAmB;AAEvB,QAAI,KAAK,SAAS,0BAA0B;AAC1C,yBAAmB,iBAAiB,OAAO,KAAK,SAAS,wBAAwB;AAAA,IACnF;AAEA,WAAO;AAAA,EACT;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,WAAW,QAAQ,KAAK,OAAO;AAEzD,UAAI,cAAc,SAAS;AACzB,aAAK,gBAAgB,KAAK,WAAW,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,0BAAoB,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":[]}
|
|
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 NavigateOptions,\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 browserPopupRedirectResolver,\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 { ALLOWED_PROTOCOLS, buildURL, stripOrigin, windowNavigate } from '../utils/';\nimport { RedirectUrls } from '../utils/redirectUrls';\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 | null | undefined;\n signUp!: SignUpResource | null | undefined;\n session!: SessionResource | null | undefined;\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 = async (options?: TernSecureAuthOptions): Promise<void> => {\n void this.#initialize(options || {});\n };\n\n public static create(options: TernSecureAuthOptions): TernSecureAuth {\n const instance = this.getOrCreateInstance();\n void instance.initialize(options);\n return instance;\n }\n\n #initialize = (options: TernSecureAuthOptions): void => {\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 popupRedirectResolver: browserPopupRedirectResolver,\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 * 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 * @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('[ternauth] Error during client auth request initialization:', error);\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\n await this.navigate(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 private checkRedirectResult = async (): 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 return this.checkRedirectResult();\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\n if (redirectUrl) {\n await this.navigate(this.constructUrlWithAuthRedirect(redirectUrl));\n }\n\n this.#setCreatedActiveSession(session);\n this.#emit();\n } catch (error) {\n console.error('[TernSecureAuth] Error creating active session:', error);\n }\n };\n\n public navigate = async (to: string | undefined, options?: NavigateOptions): Promise<unknown> => {\n if (!to || !inBrowser()) {\n return;\n }\n\n let toURL = new URL(to, window.location.href);\n\n if (!this.#allowedRedirectProtocols.includes(toURL.protocol)) {\n console.warn(\n `TernSecureAuth: \"${toURL.protocol}\" is not a valid protocol. Redirecting to \"/\" instead. If you think this is a mistake, please open an issue.`,\n );\n toURL = new URL('/', window.location.href);\n }\n\n const customNavigate =\n options?.replace && this.#options.routerReplace\n ? this.#options.routerReplace\n : this.#options.routerPush;\n\n if ((toURL.origin !== 'null' && toURL.origin !== window.location.origin) || !customNavigate) {\n windowNavigate(toURL);\n return;\n }\n\n const metadata = {\n ...(options?.metadata ? { __internal_metadata: options?.metadata } : {}),\n windowNavigate,\n };\n\n // React router only wants the path, search or hash portion.\n return await customNavigate(stripOrigin(toURL), metadata);\n };\n\n public constructUrlWithAuthRedirect = (to: string): string => {\n if (this.#instanceType === 'production') {\n return to;\n }\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 const redirectUrls = new RedirectUrls(this.#options, options).toSearchParams();\n const constructedUrl = buildURL(\n {\n base,\n hashSearchParams: [redirectUrls],\n },\n {\n stringify: true,\n skipOrigin: false,\n },\n );\n return this.constructUrlWithAuthRedirect(constructedUrl);\n };\n\n #constructAfterSignInUrl = (): string => {\n return this.constructUrlWithAuthRedirect(new RedirectUrls(this.#options).getAfterSignInUrl());\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 return this.navigate(this.constructSignInUrl(options));\n }\n return;\n };\n\n public redirectToSignUp = async (options?: SignUpRedirectOptions): Promise<unknown> => {\n if (inBrowser()) {\n return this.navigate(this.constructSignUpUrl());\n }\n return;\n };\n\n public redirectAfterSignIn = async (): Promise<unknown> => {\n if (inBrowser()) {\n return this.navigate(this.#constructAfterSignInUrl());\n }\n return;\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', {\n ...options,\n signInForceRedirectUrl: options?.signInForceRedirectUrl || window.location.href,\n });\n };\n\n public constructSignUpUrl = (options?: SignUpRedirectOptions): string => {\n return this.#buildUrl('signUpUrl', {\n ...options,\n signUpForceRedirectUrl: options?.signUpForceRedirectUrl || window.location.href,\n });\n };\n\n get #allowedRedirectProtocols() {\n let allowedProtocols = ALLOWED_PROTOCOLS;\n\n if (this.#options.allowedRedirectProtocols) {\n allowedProtocols = allowedProtocols.concat(this.#options.allowedRedirectProtocols);\n }\n\n return allowedProtocols;\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: false });\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":[]}
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
import { TernSecureBase } from "./Base";
|
|
12
12
|
class SignIn extends TernSecureBase {
|
|
13
13
|
pathRoot = "/sessions/createsession";
|
|
14
|
-
status;
|
|
14
|
+
status = null;
|
|
15
15
|
auth;
|
|
16
16
|
csrfToken;
|
|
17
17
|
_currentUser = null;
|
|
@@ -74,8 +74,7 @@ class SignIn extends TernSecureBase {
|
|
|
74
74
|
if (redirectResult) {
|
|
75
75
|
return redirectResult;
|
|
76
76
|
}
|
|
77
|
-
await this._signInWithRedirect(provider, options);
|
|
78
|
-
return;
|
|
77
|
+
return await this._signInWithRedirect(provider, options);
|
|
79
78
|
} else {
|
|
80
79
|
return await this._signInWithPopUp(provider, options);
|
|
81
80
|
}
|
|
@@ -208,19 +207,13 @@ class SignIn extends TernSecureBase {
|
|
|
208
207
|
try {
|
|
209
208
|
const config = this.getProviderConfig(providerName);
|
|
210
209
|
this.configureProvider(config.provider, options);
|
|
211
|
-
const
|
|
212
|
-
if (credential) {
|
|
213
|
-
return {
|
|
214
|
-
status: "success",
|
|
215
|
-
message: "Authentication successful",
|
|
216
|
-
user: credential.user,
|
|
217
|
-
providerId: credential.providerId,
|
|
218
|
-
operationType: credential.operationType
|
|
219
|
-
};
|
|
220
|
-
}
|
|
210
|
+
const { user, providerId, operationType } = await authMethod(this.auth, config.provider);
|
|
221
211
|
return {
|
|
222
212
|
status: "success",
|
|
223
|
-
message: "
|
|
213
|
+
message: "Authentication successful",
|
|
214
|
+
user,
|
|
215
|
+
providerId,
|
|
216
|
+
operationType
|
|
224
217
|
};
|
|
225
218
|
} catch (error) {
|
|
226
219
|
const authError = handleFirebaseAuthError(error);
|
|
@@ -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 as SignInResponseFromTypes,\n SignInStatus,\n SocialProviderOptions,\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\n/**\n * Supported OAuth providers\n */\nexport type SupportedProvider =\n | 'google'\n | 'apple'\n | 'microsoft'\n | 'github'\n | 'twitter'\n | 'facebook'\n | string; // Allow custom providers like 'custom.provider.com'\n\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: SupportedProvider,\n options: SocialProviderOptions = {},\n ): Promise<SignInResponse | void> => {\n try {\n const { mode = 'popup' } = options;\n if (mode === 'redirect') {\n const redirectResult = await this.authRedirectResult();\n\n if (redirectResult) {\n return redirectResult;\n }\n\n await this._signInWithRedirect(provider, options);\n return;\n } else {\n return await this._signInWithPopUp(provider, options);\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: SupportedProvider): ProviderConfig {\n switch (providerName.toLowerCase()) {\n case 'google': {\n const googleProvider = new GoogleAuthProvider();\n return { provider: googleProvider };\n }\n case 'apple': {\n const appleProvider = new OAuthProvider('apple.com');\n return { provider: appleProvider };\n }\n case 'microsoft': {\n const microsoftProvider = new OAuthProvider('microsoft.com');\n return { provider: microsoftProvider };\n }\n case 'github': {\n const githubProvider = new OAuthProvider('github.com');\n return { provider: githubProvider };\n }\n case 'twitter': {\n const twitterProvider = new OAuthProvider('twitter.com');\n return { provider: twitterProvider };\n }\n case 'facebook': {\n const facebookProvider = new OAuthProvider('facebook.com');\n return { provider: facebookProvider };\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 /**\n * Sets custom OAuth parameters on the provider if provided by consumer\n * @param provider - Firebase auth provider instance\n * @param customParameters - Consumer-provided OAuth parameters\n */\n private setProviderCustomParameters(\n provider: GoogleAuthProvider | OAuthProvider,\n customParameters?: Record<string, string>,\n ): void {\n if (!customParameters || Object.keys(customParameters).length === 0) {\n return;\n }\n\n provider.setCustomParameters(customParameters);\n }\n\n /**\n * Adds OAuth scopes to the provider if provided by consumer\n * Handles provider-specific scope setting logic\n * @param provider - Firebase auth provider instance\n * @param scopes - Array of OAuth scopes to request\n */\n private setProviderScopes(provider: GoogleAuthProvider | OAuthProvider, scopes?: string[]): void {\n if (!scopes || scopes.length === 0) {\n return;\n }\n\n if (provider instanceof GoogleAuthProvider) {\n // Google provider supports individual scope addition\n scopes.forEach(scope => {\n (provider as GoogleAuthProvider).addScope(scope);\n });\n } else if (provider instanceof OAuthProvider) {\n // OAuth providers expect space-separated scope string\n (provider as OAuthProvider).addScope(scopes.join(' '));\n }\n }\n\n /**\n * Configures OAuth provider with consumer-provided options\n * @param provider - Firebase auth provider instance\n * @param options - Consumer options containing custom parameters and scopes\n */\n private configureProvider(\n provider: GoogleAuthProvider | OAuthProvider,\n options: SocialProviderOptions,\n ): void {\n this.setProviderCustomParameters(provider, options.customParameters);\n this.setProviderScopes(provider, options.scopes);\n }\n\n private executeAuthMethod = async (\n authMethod: AuthMethodFunction,\n providerName: SupportedProvider,\n options: SocialProviderOptions = {},\n ): Promise<SignInResponse> => {\n try {\n const config = this.getProviderConfig(providerName);\n\n this.configureProvider(config.provider, options);\n\n const credential = await authMethod(this.auth, config.provider);\n\n if (credential) {\n return {\n status: 'success',\n message: 'Authentication successful',\n user: credential.user,\n providerId: credential.providerId,\n operationType: credential.operationType,\n };\n }\n\n return {\n status: 'success',\n message: 'Redirect initiated',\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 private async _signInWithRedirect(\n providerName: SupportedProvider,\n options: SocialProviderOptions = {},\n ): Promise<SignInResponse> {\n return this.executeAuthMethod(signInWithRedirect, providerName, options);\n }\n\n private async _signInWithPopUp(\n providerName: SupportedProvider,\n options: SocialProviderOptions = {},\n ): Promise<SignInResponse> {\n return this.executeAuthMethod(signInWithPopup, providerName, options);\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 SocialProviderOptions,\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;\n\ntype AuthMethodFunction = (\n auth: Auth,\n provider: GoogleAuthProvider | OAuthProvider,\n) => Promise<FirebaseAuthResult>;\n\n/**\n * Supported OAuth providers\n */\nexport type SupportedProvider =\n | 'google'\n | 'apple'\n | 'microsoft'\n | 'github'\n | 'twitter'\n | 'facebook'\n | string; // Allow custom providers like 'custom.provider.com'\n\nexport class SignIn extends TernSecureBase implements SignInResource {\n pathRoot = '/sessions/createsession';\n\n status: SignInStatus | null = null;\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: SupportedProvider,\n options: SocialProviderOptions = {},\n ): Promise<SignInResponse> => {\n try {\n const { mode = 'popup' } = options;\n if (mode === 'redirect') {\n const redirectResult = await this.authRedirectResult();\n\n if (redirectResult) {\n return redirectResult;\n }\n\n return await this._signInWithRedirect(provider, options);\n } else {\n return await this._signInWithPopUp(provider, options);\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: SupportedProvider): ProviderConfig {\n switch (providerName.toLowerCase()) {\n case 'google': {\n const googleProvider = new GoogleAuthProvider();\n return { provider: googleProvider };\n }\n case 'apple': {\n const appleProvider = new OAuthProvider('apple.com');\n return { provider: appleProvider };\n }\n case 'microsoft': {\n const microsoftProvider = new OAuthProvider('microsoft.com');\n return { provider: microsoftProvider };\n }\n case 'github': {\n const githubProvider = new OAuthProvider('github.com');\n return { provider: githubProvider };\n }\n case 'twitter': {\n const twitterProvider = new OAuthProvider('twitter.com');\n return { provider: twitterProvider };\n }\n case 'facebook': {\n const facebookProvider = new OAuthProvider('facebook.com');\n return { provider: facebookProvider };\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 /**\n * Sets custom OAuth parameters on the provider if provided by consumer\n * @param provider - Firebase auth provider instance\n * @param customParameters - Consumer-provided OAuth parameters\n */\n private setProviderCustomParameters(\n provider: GoogleAuthProvider | OAuthProvider,\n customParameters?: Record<string, string>,\n ): void {\n if (!customParameters || Object.keys(customParameters).length === 0) {\n return;\n }\n\n provider.setCustomParameters(customParameters);\n }\n\n /**\n * Adds OAuth scopes to the provider if provided by consumer\n * Handles provider-specific scope setting logic\n * @param provider - Firebase auth provider instance\n * @param scopes - Array of OAuth scopes to request\n */\n private setProviderScopes(provider: GoogleAuthProvider | OAuthProvider, scopes?: string[]): void {\n if (!scopes || scopes.length === 0) {\n return;\n }\n\n if (provider instanceof GoogleAuthProvider) {\n // Google provider supports individual scope addition\n scopes.forEach(scope => {\n (provider as GoogleAuthProvider).addScope(scope);\n });\n } else if (provider instanceof OAuthProvider) {\n // OAuth providers expect space-separated scope string\n (provider as OAuthProvider).addScope(scopes.join(' '));\n }\n }\n\n /**\n * Configures OAuth provider with consumer-provided options\n * @param provider - Firebase auth provider instance\n * @param options - Consumer options containing custom parameters and scopes\n */\n private configureProvider(\n provider: GoogleAuthProvider | OAuthProvider,\n options: SocialProviderOptions,\n ): void {\n this.setProviderCustomParameters(provider, options.customParameters);\n this.setProviderScopes(provider, options.scopes);\n }\n\n private executeAuthMethod = async (\n authMethod: AuthMethodFunction,\n providerName: SupportedProvider,\n options: SocialProviderOptions = {},\n ): Promise<SignInResponse> => {\n try {\n const config = this.getProviderConfig(providerName);\n\n this.configureProvider(config.provider, options);\n\n const { user, providerId, operationType } = await authMethod(this.auth, config.provider);\n\n return {\n status: 'success',\n message: 'Authentication successful',\n user,\n providerId,\n operationType,\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 private async _signInWithRedirect(\n providerName: SupportedProvider,\n options: SocialProviderOptions = {},\n ): Promise<SignInResponse> {\n return this.executeAuthMethod(signInWithRedirect, providerName, options);\n }\n\n private async _signInWithPopUp(\n providerName: SupportedProvider,\n options: SocialProviderOptions = {},\n ): Promise<SignInResponse> {\n return this.executeAuthMethod(signInWithPopup, providerName, options);\n }\n\n public async checkRedirectResult(): Promise<SignInResponse | null> {\n return this.authRedirectResult();\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -176,6 +176,7 @@ function hasBannedProtocol(val) {
|
|
|
176
176
|
return BANNED_URI_PROTOCOLS.some((bp) => bp === protocol);
|
|
177
177
|
}
|
|
178
178
|
const isAllowedRedirect = (allowedRedirectOrigins, currentOrigin) => (_url) => {
|
|
179
|
+
if (!currentOrigin) return true;
|
|
179
180
|
let url = _url;
|
|
180
181
|
if (typeof url === "string") {
|
|
181
182
|
url = relativeToAbsoluteUrl(url, currentOrigin);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/construct.ts"],"sourcesContent":["import { camelToSnake } from '@tern-secure/shared/caseUtils';\nimport { globs } from '@tern-secure/shared/globs';\nimport { logger } from '@tern-secure/shared/logger';\n\nimport { joinPaths } from './path';\nimport { getQueryParams } from './querystring';\n\nconst DUMMY_URL_BASE = 'http://ternsecure-dummy';\n\nconst BANNED_URI_PROTOCOLS = ['javascript:'] as const;\n\nexport type constructUrlWithRedirectProps = {\n signInUrl: string;\n signInPathParam?: string;\n currentPath: string;\n signUpUrl?: string;\n signUpPathParam?: string;\n};\n\ninterface BuildURLParams extends Partial<URL> {\n base?: string;\n hashPath?: string;\n hashSearch?: string;\n hashSearchParams?:\n | URLSearchParams\n | Record<string, string>\n | Array<URLSearchParams | Record<string, string>>;\n}\n\ninterface BuildURLOptions<T> {\n skipOrigin?: boolean;\n stringify?: T;\n}\n\n/**\n *\n * buildURL(params: URLParams, options: BuildURLOptions): string\n *\n * Builds a URL safely by using the native URL() constructor. It can\n * also build a secondary path and search URL that lives inside the hash\n * of the main URL. For example:\n *\n * https://foo.com/bar?qux=42#/hash-bar?hash-qux=42\n *\n * References:\n * https://developer.mozilla.org/en-US/docs/Web/API/URL\n *\n * @param {BuildURLParams} params\n * @param {BuildURLOptions} options\n * @returns {URL | string} Returns the URL href\n */\nexport function buildURL<B extends boolean>(\n params: BuildURLParams,\n options?: BuildURLOptions<B>,\n): B extends true ? string : URL;\n\nexport function buildURL(\n params: BuildURLParams,\n options: BuildURLOptions<boolean> = {},\n): URL | string {\n const { base, hashPath, hashSearch, searchParams, hashSearchParams, ...rest } = params;\n\n let baseFallback = '';\n if (typeof window !== 'undefined' && !!window.location) {\n baseFallback = window.location.href;\n } else {\n baseFallback = 'http://react-native-fake-base-url';\n }\n\n const url = new URL(base || '', baseFallback);\n\n // Handle search parameters\n // params.searchParams comes from Partial<URL>, so it's URLSearchParams | undefined\n if (searchParams instanceof URLSearchParams) {\n searchParams.forEach((value, key) => {\n if (value !== null && value !== undefined) {\n url.searchParams.set(camelToSnake(key), value);\n }\n });\n }\n\n Object.assign(url, rest);\n\n // Handle hash-related parameters\n if (hashPath || hashSearch || hashSearchParams) {\n const dummyUrlForHash = new URL(DUMMY_URL_BASE + url.hash.substring(1));\n\n dummyUrlForHash.pathname = joinPaths(dummyUrlForHash.pathname, hashPath || '');\n\n const searchParamsFromHashSearchString = getQueryParams(hashSearch || '');\n\n for (const [key, val] of Object.entries(searchParamsFromHashSearchString)) {\n dummyUrlForHash.searchParams.append(key, val);\n }\n\n if (hashSearchParams) {\n const paramsArr = Array.isArray(hashSearchParams) ? hashSearchParams : [hashSearchParams];\n for (const _params of paramsArr) {\n if (!(_params instanceof URLSearchParams) && typeof _params !== 'object') {\n continue;\n }\n const params = new URLSearchParams(_params);\n params.forEach((value, key) => {\n if (value !== null && value !== undefined) {\n dummyUrlForHash.searchParams.set(camelToSnake(key), value);\n }\n });\n }\n }\n\n const newHash = dummyUrlForHash.href.replace(DUMMY_URL_BASE, '');\n if (newHash !== '/') {\n // Assign them to the hash of the main url\n url.hash = newHash;\n }\n }\n\n const { stringify, skipOrigin } = options;\n if (stringify) {\n return skipOrigin ? url.href.replace(url.origin, '') : url.href;\n }\n return url;\n}\n\n/**\n * Constructs a full URL with the current origin\n * @param path - The path to construct the URL for\n * @returns The full URL with origin\n */\nexport const constructFullUrl = (path: string) => {\n if (typeof window === 'undefined') return path;\n const baseUrl = window.location.origin;\n if (path.startsWith('http')) {\n return path;\n }\n return `${baseUrl}${path.startsWith('/') ? path : `/${path}`}`;\n};\n\n/**\n * Checks if the current URL has a redirect loop\n * @param currentPath - The current pathname\n * @param redirectPath - The path we're trying to redirect to\n * @returns boolean indicating if there's a redirect loop\n */\nexport const hasRedirectLoop = (currentPath: string, redirectPath: string): boolean => {\n if (!currentPath || !redirectPath) return false;\n\n // Remove any query parameters for comparison\n const cleanCurrentPath = currentPath.split('?')[0];\n const cleanRedirectPath = redirectPath.split('?')[0];\n\n return cleanCurrentPath === cleanRedirectPath;\n};\n\nexport const urlWithRedirect = (options: constructUrlWithRedirectProps): string => {\n const {\n signInUrl,\n signInPathParam = '/sign-in',\n currentPath,\n signUpUrl,\n signUpPathParam = '/sign-up',\n } = options;\n\n const baseUrl = window.location.origin;\n\n if (typeof window === 'undefined') {\n return signInUrl;\n }\n\n const url = new URL(signInUrl, baseUrl);\n\n if (!currentPath.includes(signInPathParam) && !currentPath.includes(signUpPathParam)) {\n url.searchParams.set('redirect', currentPath);\n }\n\n return url.toString();\n};\n\n/**\n * Stores the current path before signing out\n */\nexport const storePreviousPath = (path: string): void => {\n if (typeof window !== 'undefined') {\n sessionStorage.setItem('previousPath', path);\n }\n};\n\n/**\n * Gets the stored previous path\n */\nexport const getPreviousPath = (): string | null => {\n if (typeof window !== 'undefined') {\n return sessionStorage.getItem('previousPath');\n }\n return null;\n};\n\n/**\n * Gets a validated redirect URL ensuring it's from the same origin\n * @param redirectUrl - The URL to validate\n * @param searchParams - The search parameters to check for redirect\n * @returns A validated redirect URL\n */\nexport const getValidRedirectUrl = (\n searchParams: URLSearchParams,\n configuredRedirect?: string,\n): string => {\n // Check URL search param first (highest priority)\n const urlRedirect = searchParams.get('redirect');\n if (urlRedirect) {\n return validateUrl(urlRedirect);\n }\n\n // Then check configured redirect (for first visits)\n if (configuredRedirect) {\n return validateUrl(configuredRedirect);\n }\n\n // Default fallback\n return '/';\n};\n\n/**\n * Validates and sanitizes URLs\n */\nconst validateUrl = (url: string): string => {\n try {\n // For absolute URLs\n if (url.startsWith('http')) {\n const urlObj = new URL(url);\n if (typeof window !== 'undefined' && urlObj.origin !== window.location.origin) {\n return '/';\n }\n }\n\n // For relative URLs\n return '/';\n } catch {\n return '/';\n }\n};\n\nexport function toURL(url: string | URL): URL {\n return new URL(url.toString(), window.location.origin);\n}\n\n/**\n *\n * stripOrigin(url: URL | string): string\n *\n * Strips the origin part of a URL and preserves path, search and hash is applicable\n *\n * References:\n * https://developer.mozilla.org/en-US/docs/Web/API/URL\n *\n * @param {URL | string} url\n * @returns {string} Returns the URL href without the origin\n */\nexport function stripOrigin(url: URL | string): string {\n url = toURL(url);\n return url.href.replace(url.origin, '');\n}\n\n/**\n * trimTrailingSlash(path: string): string\n *\n * Strips the trailing slashes from a string\n *\n * @returns {string} Returns the string without trailing slashes\n * @param path\n */\nexport const trimTrailingSlash = (path: string): string => {\n return (path || '').replace(/\\/+$/, '');\n};\n\nexport function isValidUrl(val: unknown): val is string {\n if (!val) {\n return false;\n }\n\n try {\n new URL(val as string);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function relativeToAbsoluteUrl(url: string, origin: string | URL): URL {\n try {\n return new URL(url);\n } catch {\n return new URL(url, origin);\n }\n}\n\n// Regular expression to detect disallowed patterns\nconst disallowedPatterns = [\n /\\0/, // Null bytes\n /^\\/\\//, // Protocol-relative\n // eslint-disable-next-line no-control-regex\n /[\\x00-\\x1F]/, // Control characters\n];\n\n/**\n * Check for potentially problematic URLs that could have been crafted to intentionally bypass the origin check. Note that the URLs passed to this\n * function are assumed to be from an \"allowed origin\", so we are not executing origin-specific checks here.\n */\nexport function isProblematicUrl(url: URL): boolean {\n if (hasBannedProtocol(url)) {\n return true;\n }\n // Check against disallowed patterns\n for (const pattern of disallowedPatterns) {\n if (pattern.test(url.pathname)) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function hasBannedProtocol(val: string | URL) {\n if (!isValidUrl(val)) {\n return false;\n }\n const protocol = new URL(val).protocol;\n return BANNED_URI_PROTOCOLS.some(bp => bp === protocol);\n}\n\nexport const isAllowedRedirect =\n (allowedRedirectOrigins: Array<string | RegExp> | undefined, currentOrigin: string) =>\n (_url: URL | string) => {\n let url = _url;\n if (typeof url === 'string') {\n url = relativeToAbsoluteUrl(url, currentOrigin);\n }\n\n if (!allowedRedirectOrigins) {\n return true;\n }\n\n const isSameOrigin = currentOrigin === url.origin;\n\n const isAllowed =\n !isProblematicUrl(url) &&\n (isSameOrigin ||\n allowedRedirectOrigins\n .map(origin =>\n typeof origin === 'string' ? globs.toRegexp(trimTrailingSlash(origin)) : origin,\n )\n .some(origin => origin.test(trimTrailingSlash(url.origin))));\n\n if (!isAllowed) {\n logger.warnOnce(\n `Clerk: Redirect URL ${url} is not on one of the allowedRedirectOrigins, falling back to the default redirect URL.`,\n );\n }\n return isAllowed;\n };\n"],"mappings":"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","names":["params"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/construct.ts"],"sourcesContent":["import { camelToSnake } from '@tern-secure/shared/caseUtils';\nimport { globs } from '@tern-secure/shared/globs';\nimport { logger } from '@tern-secure/shared/logger';\n\nimport { joinPaths } from './path';\nimport { getQueryParams } from './querystring';\n\nconst DUMMY_URL_BASE = 'http://ternsecure-dummy';\n\nconst BANNED_URI_PROTOCOLS = ['javascript:'] as const;\n\nexport type constructUrlWithRedirectProps = {\n signInUrl: string;\n signInPathParam?: string;\n currentPath: string;\n signUpUrl?: string;\n signUpPathParam?: string;\n};\n\ninterface BuildURLParams extends Partial<URL> {\n base?: string;\n hashPath?: string;\n hashSearch?: string;\n hashSearchParams?:\n | URLSearchParams\n | Record<string, string>\n | Array<URLSearchParams | Record<string, string>>;\n}\n\ninterface BuildURLOptions<T> {\n skipOrigin?: boolean;\n stringify?: T;\n}\n\n/**\n *\n * buildURL(params: URLParams, options: BuildURLOptions): string\n *\n * Builds a URL safely by using the native URL() constructor. It can\n * also build a secondary path and search URL that lives inside the hash\n * of the main URL. For example:\n *\n * https://foo.com/bar?qux=42#/hash-bar?hash-qux=42\n *\n * References:\n * https://developer.mozilla.org/en-US/docs/Web/API/URL\n *\n * @param {BuildURLParams} params\n * @param {BuildURLOptions} options\n * @returns {URL | string} Returns the URL href\n */\nexport function buildURL<B extends boolean>(\n params: BuildURLParams,\n options?: BuildURLOptions<B>,\n): B extends true ? string : URL;\n\nexport function buildURL(\n params: BuildURLParams,\n options: BuildURLOptions<boolean> = {},\n): URL | string {\n const { base, hashPath, hashSearch, searchParams, hashSearchParams, ...rest } = params;\n\n let baseFallback = '';\n if (typeof window !== 'undefined' && !!window.location) {\n baseFallback = window.location.href;\n } else {\n baseFallback = 'http://react-native-fake-base-url';\n }\n\n const url = new URL(base || '', baseFallback);\n\n // Handle search parameters\n // params.searchParams comes from Partial<URL>, so it's URLSearchParams | undefined\n if (searchParams instanceof URLSearchParams) {\n searchParams.forEach((value, key) => {\n if (value !== null && value !== undefined) {\n url.searchParams.set(camelToSnake(key), value);\n }\n });\n }\n\n Object.assign(url, rest);\n\n // Handle hash-related parameters\n if (hashPath || hashSearch || hashSearchParams) {\n const dummyUrlForHash = new URL(DUMMY_URL_BASE + url.hash.substring(1));\n\n dummyUrlForHash.pathname = joinPaths(dummyUrlForHash.pathname, hashPath || '');\n\n const searchParamsFromHashSearchString = getQueryParams(hashSearch || '');\n\n for (const [key, val] of Object.entries(searchParamsFromHashSearchString)) {\n dummyUrlForHash.searchParams.append(key, val);\n }\n\n if (hashSearchParams) {\n const paramsArr = Array.isArray(hashSearchParams) ? hashSearchParams : [hashSearchParams];\n for (const _params of paramsArr) {\n if (!(_params instanceof URLSearchParams) && typeof _params !== 'object') {\n continue;\n }\n const params = new URLSearchParams(_params);\n params.forEach((value, key) => {\n if (value !== null && value !== undefined) {\n dummyUrlForHash.searchParams.set(camelToSnake(key), value);\n }\n });\n }\n }\n\n const newHash = dummyUrlForHash.href.replace(DUMMY_URL_BASE, '');\n if (newHash !== '/') {\n // Assign them to the hash of the main url\n url.hash = newHash;\n }\n }\n\n const { stringify, skipOrigin } = options;\n if (stringify) {\n return skipOrigin ? url.href.replace(url.origin, '') : url.href;\n }\n return url;\n}\n\n/**\n * Constructs a full URL with the current origin\n * @param path - The path to construct the URL for\n * @returns The full URL with origin\n */\nexport const constructFullUrl = (path: string) => {\n if (typeof window === 'undefined') return path;\n const baseUrl = window.location.origin;\n if (path.startsWith('http')) {\n return path;\n }\n return `${baseUrl}${path.startsWith('/') ? path : `/${path}`}`;\n};\n\n/**\n * Checks if the current URL has a redirect loop\n * @param currentPath - The current pathname\n * @param redirectPath - The path we're trying to redirect to\n * @returns boolean indicating if there's a redirect loop\n */\nexport const hasRedirectLoop = (currentPath: string, redirectPath: string): boolean => {\n if (!currentPath || !redirectPath) return false;\n\n // Remove any query parameters for comparison\n const cleanCurrentPath = currentPath.split('?')[0];\n const cleanRedirectPath = redirectPath.split('?')[0];\n\n return cleanCurrentPath === cleanRedirectPath;\n};\n\nexport const urlWithRedirect = (options: constructUrlWithRedirectProps): string => {\n const {\n signInUrl,\n signInPathParam = '/sign-in',\n currentPath,\n signUpUrl,\n signUpPathParam = '/sign-up',\n } = options;\n\n const baseUrl = window.location.origin;\n\n if (typeof window === 'undefined') {\n return signInUrl;\n }\n\n const url = new URL(signInUrl, baseUrl);\n\n if (!currentPath.includes(signInPathParam) && !currentPath.includes(signUpPathParam)) {\n url.searchParams.set('redirect', currentPath);\n }\n\n return url.toString();\n};\n\n/**\n * Stores the current path before signing out\n */\nexport const storePreviousPath = (path: string): void => {\n if (typeof window !== 'undefined') {\n sessionStorage.setItem('previousPath', path);\n }\n};\n\n/**\n * Gets the stored previous path\n */\nexport const getPreviousPath = (): string | null => {\n if (typeof window !== 'undefined') {\n return sessionStorage.getItem('previousPath');\n }\n return null;\n};\n\n/**\n * Gets a validated redirect URL ensuring it's from the same origin\n * @param redirectUrl - The URL to validate\n * @param searchParams - The search parameters to check for redirect\n * @returns A validated redirect URL\n */\nexport const getValidRedirectUrl = (\n searchParams: URLSearchParams,\n configuredRedirect?: string,\n): string => {\n // Check URL search param first (highest priority)\n const urlRedirect = searchParams.get('redirect');\n if (urlRedirect) {\n return validateUrl(urlRedirect);\n }\n\n // Then check configured redirect (for first visits)\n if (configuredRedirect) {\n return validateUrl(configuredRedirect);\n }\n\n // Default fallback\n return '/';\n};\n\n/**\n * Validates and sanitizes URLs\n */\nconst validateUrl = (url: string): string => {\n try {\n // For absolute URLs\n if (url.startsWith('http')) {\n const urlObj = new URL(url);\n if (typeof window !== 'undefined' && urlObj.origin !== window.location.origin) {\n return '/';\n }\n }\n\n // For relative URLs\n return '/';\n } catch {\n return '/';\n }\n};\n\nexport function toURL(url: string | URL): URL {\n return new URL(url.toString(), window.location.origin);\n}\n\n/**\n *\n * stripOrigin(url: URL | string): string\n *\n * Strips the origin part of a URL and preserves path, search and hash is applicable\n *\n * References:\n * https://developer.mozilla.org/en-US/docs/Web/API/URL\n *\n * @param {URL | string} url\n * @returns {string} Returns the URL href without the origin\n */\nexport function stripOrigin(url: URL | string): string {\n url = toURL(url);\n return url.href.replace(url.origin, '');\n}\n\n/**\n * trimTrailingSlash(path: string): string\n *\n * Strips the trailing slashes from a string\n *\n * @returns {string} Returns the string without trailing slashes\n * @param path\n */\nexport const trimTrailingSlash = (path: string): string => {\n return (path || '').replace(/\\/+$/, '');\n};\n\nexport function isValidUrl(val: unknown): val is string {\n if (!val) {\n return false;\n }\n\n try {\n new URL(val as string);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function relativeToAbsoluteUrl(url: string, origin: string | URL): URL {\n try {\n return new URL(url);\n } catch {\n return new URL(url, origin);\n }\n}\n\n// Regular expression to detect disallowed patterns\nconst disallowedPatterns = [\n /\\0/, // Null bytes\n /^\\/\\//, // Protocol-relative\n // eslint-disable-next-line no-control-regex\n /[\\x00-\\x1F]/, // Control characters\n];\n\n/**\n * Check for potentially problematic URLs that could have been crafted to intentionally bypass the origin check. Note that the URLs passed to this\n * function are assumed to be from an \"allowed origin\", so we are not executing origin-specific checks here.\n */\nexport function isProblematicUrl(url: URL): boolean {\n if (hasBannedProtocol(url)) {\n return true;\n }\n // Check against disallowed patterns\n for (const pattern of disallowedPatterns) {\n if (pattern.test(url.pathname)) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function hasBannedProtocol(val: string | URL) {\n if (!isValidUrl(val)) {\n return false;\n }\n const protocol = new URL(val).protocol;\n return BANNED_URI_PROTOCOLS.some(bp => bp === protocol);\n}\n\nexport const isAllowedRedirect =\n (allowedRedirectOrigins: Array<string | RegExp> | undefined, currentOrigin: string) =>\n (_url: URL | string) => {\n // On server-side (no origin), allow all redirects\n // They will be validated on client-side\n if (!currentOrigin) return true;\n\n let url = _url;\n if (typeof url === 'string') {\n url = relativeToAbsoluteUrl(url, currentOrigin);\n }\n\n if (!allowedRedirectOrigins) {\n return true;\n }\n\n const isSameOrigin = currentOrigin === url.origin;\n\n const isAllowed =\n !isProblematicUrl(url) &&\n (isSameOrigin ||\n allowedRedirectOrigins\n .map(origin =>\n typeof origin === 'string' ? globs.toRegexp(trimTrailingSlash(origin)) : origin,\n )\n .some(origin => origin.test(trimTrailingSlash(url.origin))));\n\n if (!isAllowed) {\n logger.warnOnce(\n `Clerk: Redirect URL ${url} is not on one of the allowedRedirectOrigins, falling back to the default redirect URL.`,\n );\n }\n return isAllowed;\n };\n"],"mappings":"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","names":["params"]}
|
|
@@ -117,6 +117,7 @@ class RedirectUrls {
|
|
|
117
117
|
}
|
|
118
118
|
#toAbsoluteUrls(obj) {
|
|
119
119
|
const origin = typeof window !== "undefined" ? window.location.origin : "";
|
|
120
|
+
if (!origin) return obj;
|
|
120
121
|
return applyFunctionToObj(obj, (url) => relativeToAbsoluteUrl(url, origin));
|
|
121
122
|
}
|
|
122
123
|
#filterRedirects = (obj) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/redirectUrls.ts"],"sourcesContent":["import { camelToSnake } from '@tern-secure/shared/caseUtils';\nimport { applyFunctionToObj, filterProps, removeUndefined } from '@tern-secure/shared/object';\nimport type { RedirectOptions, TernSecureAuthOptions } from '@tern-secure/types';\n\nimport { isAllowedRedirect, relativeToAbsoluteUrl } from './construct';\n\n/**\n * RedirectUrls class handles all redirect URL construction logic\n * for sign-in, sign-up, and post-authentication flows.\n *\n * This class centralizes the redirect logic previously scattered across\n * multiple methods, making it reusable and maintainable.\n */\nexport class RedirectUrls {\n private static keys: (keyof RedirectOptions)[] = [\n 'signInForceRedirectUrl',\n 'signInFallbackRedirectUrl',\n 'signUpForceRedirectUrl',\n 'signUpFallbackRedirectUrl',\n 'afterSignInUrl',\n 'afterSignUpUrl',\n 'redirectUrl',\n ];\n\n private static preserved = ['redirectUrl'];\n\n private readonly options: TernSecureAuthOptions;\n private readonly fromOptions: RedirectOptions;\n private readonly fromProps: RedirectOptions;\n private readonly fromSearchParams: RedirectOptions & { redirectUrl?: string | null };\n\n constructor(options: TernSecureAuthOptions, props: RedirectOptions = {}, searchParams: any = {}) {\n this.options = options;\n this.fromOptions = this.#parse(options || {});\n this.fromProps = this.#parse(props || {});\n this.fromSearchParams = this.#parseSearchParams(searchParams || {});\n }\n\n getAfterSignInUrl() {\n return this.#getRedirectUrl('signIn');\n }\n\n getAfterSignUpUrl() {\n return this.#getRedirectUrl('signUp');\n }\n\n getPreservedSearchParams() {\n return this.#toSearchParams(this.#flattenPreserved());\n }\n\n toSearchParams() {\n return this.#toSearchParams(this.#flattenAll());\n }\n\n #toSearchParams(obj: Record<string, string | undefined | null>): URLSearchParams {\n const camelCased = Object.fromEntries(\n Object.entries(obj).map(([key, value]) => [camelToSnake(key), value]),\n );\n return new URLSearchParams(removeUndefined(camelCased) as Record<string, string>);\n }\n\n #flattenPreserved() {\n return Object.fromEntries(\n Object.entries({ ...this.fromSearchParams }).filter(([key]) =>\n RedirectUrls.preserved.includes(key),\n ),\n );\n }\n\n #flattenAll() {\n const signUpForceRedirectUrl =\n this.fromSearchParams.signUpForceRedirectUrl ||\n this.fromProps.signUpForceRedirectUrl ||\n this.fromOptions.signUpForceRedirectUrl;\n const signUpFallbackRedirectUrl =\n this.fromSearchParams.signUpFallbackRedirectUrl ||\n this.fromProps.signUpFallbackRedirectUrl ||\n this.fromOptions.signUpFallbackRedirectUrl;\n const signInForceRedirectUrl =\n this.fromSearchParams.signInForceRedirectUrl ||\n this.fromProps.signInForceRedirectUrl ||\n this.fromOptions.signInForceRedirectUrl;\n const signInFallbackRedirectUrl =\n this.fromSearchParams.signInFallbackRedirectUrl ||\n this.fromProps.signInFallbackRedirectUrl ||\n this.fromOptions.signInFallbackRedirectUrl;\n const afterSignInUrl =\n this.fromSearchParams.afterSignInUrl ||\n this.fromProps.afterSignInUrl ||\n this.fromOptions.afterSignInUrl;\n const afterSignUpUrl =\n this.fromSearchParams.afterSignUpUrl ||\n this.fromProps.afterSignUpUrl ||\n this.fromOptions.afterSignUpUrl;\n const redirectUrl =\n this.fromSearchParams.redirectUrl ||\n this.fromProps.redirectUrl ||\n this.fromOptions.redirectUrl;\n\n const res: RedirectOptions = {\n signUpForceRedirectUrl,\n signUpFallbackRedirectUrl,\n signInForceRedirectUrl,\n signInFallbackRedirectUrl,\n afterSignInUrl,\n afterSignUpUrl,\n redirectUrl,\n };\n return res;\n }\n\n #getRedirectUrl(prefix: 'signIn' | 'signUp') {\n const forceKey = `${prefix}ForceRedirectUrl` as const;\n const fallbackKey = `${prefix}FallbackRedirectUrl` as const;\n\n let newKeyInUse: string | undefined;\n\n let result;\n // Prioritize forceRedirectUrl\n result =\n this.fromSearchParams[forceKey] || this.fromProps[forceKey] || this.fromOptions[forceKey];\n if (result) {\n newKeyInUse = forceKey;\n }\n\n // Try to get redirect_url, only allowed as a search param\n result ||= this.fromSearchParams.redirectUrl;\n if (result) {\n newKeyInUse = 'redirectUrl';\n }\n\n // Otherwise, fallback to fallbackRedirectUrl\n result ||=\n this.fromSearchParams[fallbackKey] ||\n this.fromProps[fallbackKey] ||\n this.fromOptions[fallbackKey];\n if (result) {\n newKeyInUse = fallbackKey;\n }\n\n if (!result) {\n if (typeof window === 'undefined') {\n return '/';\n }\n return window.location.href;\n }\n return result || '/';\n }\n\n #parse(obj: unknown) {\n const res = {} as RedirectOptions;\n RedirectUrls.keys.forEach(key => {\n // @ts-expect-error\n res[key] = obj[key];\n });\n\n //const absoluteUrls = this.#toAbsoluteUrls(filterProps(res, Boolean));\n //const filtered = this.#filterRedirects(absoluteUrls);\n //return applyFunctionToObj(filtered, val => val.toString());\n\n return applyFunctionToObj(\n this.#filterRedirects(this.#toAbsoluteUrls(filterProps(res, Boolean))),\n val => val.toString(),\n );\n }\n\n #parseSearchParams(obj: any) {\n const res = {} as typeof this.fromSearchParams;\n RedirectUrls.keys.forEach(key => {\n if (obj instanceof URLSearchParams) {\n res[key] = obj.get(camelToSnake(key));\n } else {\n res[key] = obj[camelToSnake(key)];\n }\n });\n\n return applyFunctionToObj(\n this.#filterRedirects(this.#toAbsoluteUrls(filterProps(res, Boolean))),\n val => val.toString(),\n );\n }\n\n #toAbsoluteUrls(obj: RedirectOptions) {\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n return applyFunctionToObj(obj, (url: string) => relativeToAbsoluteUrl(url, origin));\n }\n\n #filterRedirects = (obj: RedirectOptions) => {\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n return filterProps(obj, isAllowedRedirect(this.options?.allowedRedirectOrigins, origin));\n };\n}\n"],"mappings":"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
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/redirectUrls.ts"],"sourcesContent":["import { camelToSnake } from '@tern-secure/shared/caseUtils';\nimport { applyFunctionToObj, filterProps, removeUndefined } from '@tern-secure/shared/object';\nimport type { RedirectOptions, TernSecureAuthOptions } from '@tern-secure/types';\n\nimport { isAllowedRedirect, relativeToAbsoluteUrl } from './construct';\n\n/**\n * RedirectUrls class handles all redirect URL construction logic\n * for sign-in, sign-up, and post-authentication flows.\n *\n * This class centralizes the redirect logic previously scattered across\n * multiple methods, making it reusable and maintainable.\n */\nexport class RedirectUrls {\n private static keys: (keyof RedirectOptions)[] = [\n 'signInForceRedirectUrl',\n 'signInFallbackRedirectUrl',\n 'signUpForceRedirectUrl',\n 'signUpFallbackRedirectUrl',\n 'afterSignInUrl',\n 'afterSignUpUrl',\n 'redirectUrl',\n ];\n\n private static preserved = ['redirectUrl'];\n\n private readonly options: TernSecureAuthOptions;\n private readonly fromOptions: RedirectOptions;\n private readonly fromProps: RedirectOptions;\n private readonly fromSearchParams: RedirectOptions & { redirectUrl?: string | null };\n\n constructor(options: TernSecureAuthOptions, props: RedirectOptions = {}, searchParams: any = {}) {\n this.options = options;\n this.fromOptions = this.#parse(options || {});\n this.fromProps = this.#parse(props || {});\n this.fromSearchParams = this.#parseSearchParams(searchParams || {});\n }\n\n getAfterSignInUrl() {\n return this.#getRedirectUrl('signIn');\n }\n\n getAfterSignUpUrl() {\n return this.#getRedirectUrl('signUp');\n }\n\n getPreservedSearchParams() {\n return this.#toSearchParams(this.#flattenPreserved());\n }\n\n toSearchParams() {\n return this.#toSearchParams(this.#flattenAll());\n }\n\n #toSearchParams(obj: Record<string, string | undefined | null>): URLSearchParams {\n const camelCased = Object.fromEntries(\n Object.entries(obj).map(([key, value]) => [camelToSnake(key), value]),\n );\n return new URLSearchParams(removeUndefined(camelCased) as Record<string, string>);\n }\n\n #flattenPreserved() {\n return Object.fromEntries(\n Object.entries({ ...this.fromSearchParams }).filter(([key]) =>\n RedirectUrls.preserved.includes(key),\n ),\n );\n }\n\n #flattenAll() {\n const signUpForceRedirectUrl =\n this.fromSearchParams.signUpForceRedirectUrl ||\n this.fromProps.signUpForceRedirectUrl ||\n this.fromOptions.signUpForceRedirectUrl;\n const signUpFallbackRedirectUrl =\n this.fromSearchParams.signUpFallbackRedirectUrl ||\n this.fromProps.signUpFallbackRedirectUrl ||\n this.fromOptions.signUpFallbackRedirectUrl;\n const signInForceRedirectUrl =\n this.fromSearchParams.signInForceRedirectUrl ||\n this.fromProps.signInForceRedirectUrl ||\n this.fromOptions.signInForceRedirectUrl;\n const signInFallbackRedirectUrl =\n this.fromSearchParams.signInFallbackRedirectUrl ||\n this.fromProps.signInFallbackRedirectUrl ||\n this.fromOptions.signInFallbackRedirectUrl;\n const afterSignInUrl =\n this.fromSearchParams.afterSignInUrl ||\n this.fromProps.afterSignInUrl ||\n this.fromOptions.afterSignInUrl;\n const afterSignUpUrl =\n this.fromSearchParams.afterSignUpUrl ||\n this.fromProps.afterSignUpUrl ||\n this.fromOptions.afterSignUpUrl;\n const redirectUrl =\n this.fromSearchParams.redirectUrl ||\n this.fromProps.redirectUrl ||\n this.fromOptions.redirectUrl;\n\n const res: RedirectOptions = {\n signUpForceRedirectUrl,\n signUpFallbackRedirectUrl,\n signInForceRedirectUrl,\n signInFallbackRedirectUrl,\n afterSignInUrl,\n afterSignUpUrl,\n redirectUrl,\n };\n return res;\n }\n\n #getRedirectUrl(prefix: 'signIn' | 'signUp') {\n const forceKey = `${prefix}ForceRedirectUrl` as const;\n const fallbackKey = `${prefix}FallbackRedirectUrl` as const;\n\n let newKeyInUse: string | undefined;\n\n let result;\n // Prioritize forceRedirectUrl\n result =\n this.fromSearchParams[forceKey] || this.fromProps[forceKey] || this.fromOptions[forceKey];\n if (result) {\n newKeyInUse = forceKey;\n }\n\n // Try to get redirect_url, only allowed as a search param\n result ||= this.fromSearchParams.redirectUrl;\n if (result) {\n newKeyInUse = 'redirectUrl';\n }\n\n // Otherwise, fallback to fallbackRedirectUrl\n result ||=\n this.fromSearchParams[fallbackKey] ||\n this.fromProps[fallbackKey] ||\n this.fromOptions[fallbackKey];\n if (result) {\n newKeyInUse = fallbackKey;\n }\n\n if (!result) {\n if (typeof window === 'undefined') {\n return '/';\n }\n return window.location.href;\n }\n return result || '/';\n }\n\n #parse(obj: unknown) {\n const res = {} as RedirectOptions;\n RedirectUrls.keys.forEach(key => {\n // @ts-expect-error\n res[key] = obj[key];\n });\n\n //const absoluteUrls = this.#toAbsoluteUrls(filterProps(res, Boolean));\n //const filtered = this.#filterRedirects(absoluteUrls);\n //return applyFunctionToObj(filtered, val => val.toString());\n\n return applyFunctionToObj(\n this.#filterRedirects(this.#toAbsoluteUrls(filterProps(res, Boolean))),\n val => val.toString(),\n );\n }\n\n #parseSearchParams(obj: any) {\n const res = {} as typeof this.fromSearchParams;\n RedirectUrls.keys.forEach(key => {\n if (obj instanceof URLSearchParams) {\n res[key] = obj.get(camelToSnake(key));\n } else {\n res[key] = obj[camelToSnake(key)];\n }\n });\n\n return applyFunctionToObj(\n this.#filterRedirects(this.#toAbsoluteUrls(filterProps(res, Boolean))),\n val => val.toString(),\n );\n }\n\n #toAbsoluteUrls(obj: RedirectOptions) {\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n // If no origin (server-side), return URLs as-is without conversion\n // They will be properly converted on the client-side\n if (!origin) return obj;\n\n return applyFunctionToObj(obj, (url: string) => relativeToAbsoluteUrl(url, origin));\n }\n\n #filterRedirects = (obj: RedirectOptions) => {\n const origin = typeof window !== 'undefined' ? window.location.origin : '';\n return filterProps(obj, isAllowedRedirect(this.options?.allowedRedirectOrigins, origin));\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -5,6 +5,6 @@ export type { TernServerAuthOptions, AuthenticatedApp } from './instance/TernAut
|
|
|
5
5
|
export { CoreApiClient, coreApiClient } from './instance/coreApiClient';
|
|
6
6
|
export type { ApiResponse, ApiResponseJSON, RequestOptions, BeforeRequestHook, AfterResponseHook } from './instance/coreApiClient';
|
|
7
7
|
export { SignIn, TernSecureBase, buildURL } from './resources/internal';
|
|
8
|
-
export type { AuthErrorTree, TernSecureConfig, SignInFormValues, SignInProps, SignUpProps, SignInResponse, SignInForceRedirectUrl, SignUpForceRedirectUrl, ResendEmailVerification, TernSecureUser, TernSecureState } from '@tern-secure/types';
|
|
8
|
+
export type { AuthErrorTree, TernSecureConfig, SignInFormValues, SignInProps, SignUpProps, SignInResponse, SignInForceRedirectUrl, SignUpForceRedirectUrl, SignInFallbackRedirectUrl, ResendEmailVerification, TernSecureUser, TernSecureState } from '@tern-secure/types';
|
|
9
9
|
export { RedirectUrls } from './utils/redirectUrls';
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,YAAY,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAEzF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACxE,YAAY,EACR,WAAW,EACX,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACpB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAExE,YAAY,EACR,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,cAAc,EACd,eAAe,EAClB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,YAAY,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAEzF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACxE,YAAY,EACR,WAAW,EACX,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACpB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAExE,YAAY,EACR,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACtB,yBAAyB,EACzB,uBAAuB,EACvB,cAAc,EACd,eAAe,EAClB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CreateActiveSession, InstanceType, ListenerCallback, NavigateOptions, SessionResource, SignedInSession, SignInRedirectOptions, SignInResource,
|
|
1
|
+
import type { CreateActiveSession, InstanceType, ListenerCallback, NavigateOptions, SessionResource, SignedInSession, SignInRedirectOptions, SignInResource, SignOut, SignUpRedirectOptions, SignUpResource, TernAuthSDK, TernSecureAuth as TernSecureAuthInterface, TernSecureAuthOptions, TernSecureUser, TernSecureUserData, UnsubscribeCallback } from '@tern-secure/types';
|
|
2
2
|
import type { Auth as TernAuth } from 'firebase/auth';
|
|
3
3
|
import { AuthCookieManager } from '../resources/internal';
|
|
4
4
|
import { type ApiClient } from './c_coreApiClient';
|
|
@@ -67,7 +67,7 @@ export declare class TernSecureAuth implements TernSecureAuthInterface {
|
|
|
67
67
|
onAuthStateChanged(callback: (cb: any) => void): () => void;
|
|
68
68
|
onIdTokenChanged(callback: (cb: any) => void): () => void;
|
|
69
69
|
private updateCurrentSession;
|
|
70
|
-
checkRedirectResult
|
|
70
|
+
private checkRedirectResult;
|
|
71
71
|
getRedirectResult: () => Promise<any>;
|
|
72
72
|
addListener: (listener: ListenerCallback) => UnsubscribeCallback;
|
|
73
73
|
on: TernSecureAuthInterface['on'];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TernAuth.d.ts","sourceRoot":"","sources":["../../../src/instance/TernAuth.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,mBAAmB,EAEnB,YAAY,EACZ,gBAAgB,EAChB,eAAe,EAEf,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,cAAc,
|
|
1
|
+
{"version":3,"file":"TernAuth.d.ts","sourceRoot":"","sources":["../../../src/instance/TernAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,7 +13,7 @@ export type SignInParams = {
|
|
|
13
13
|
export type SupportedProvider = 'google' | 'apple' | 'microsoft' | 'github' | 'twitter' | 'facebook' | string;
|
|
14
14
|
export declare class SignIn extends TernSecureBase implements SignInResource {
|
|
15
15
|
pathRoot: string;
|
|
16
|
-
status
|
|
16
|
+
status: SignInStatus | null;
|
|
17
17
|
private auth;
|
|
18
18
|
private csrfToken;
|
|
19
19
|
private _currentUser;
|
|
@@ -21,7 +21,7 @@ export declare class SignIn extends TernSecureBase implements SignInResource {
|
|
|
21
21
|
signInWithCredential: (credential: UserCredential) => Promise<import("..").ApiResponseJSON<any> | null>;
|
|
22
22
|
withEmailAndPassword: (params: SignInFormValues) => Promise<SignInResponse>;
|
|
23
23
|
withCredential: (params: SignInFormValues) => Promise<void>;
|
|
24
|
-
withSocialProvider: (provider: SupportedProvider, options?: SocialProviderOptions) => Promise<SignInResponse
|
|
24
|
+
withSocialProvider: (provider: SupportedProvider, options?: SocialProviderOptions) => Promise<SignInResponse>;
|
|
25
25
|
completeMfaSignIn: (_mfaToken: string, _mfaContext?: any) => Promise<SignInResponse>;
|
|
26
26
|
sendPasswordResetEmail: (email: string) => Promise<void>;
|
|
27
27
|
resendEmailVerification: () => Promise<ResendEmailVerification>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SignIn.d.ts","sourceRoot":"","sources":["../../../src/resources/SignIn.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,EACd,cAAc,IAAI,uBAAuB,EACzC,YAAY,EACZ,qBAAqB,EAEtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAW1D,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAExC,KAAK,cAAc,GAAG,uBAAuB,CAAC;AAO9C,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC;AAE1C,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B,CAAC;AASF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,QAAQ,GACR,OAAO,GACP,WAAW,GACX,QAAQ,GACR,SAAS,GACT,UAAU,GACV,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"SignIn.d.ts","sourceRoot":"","sources":["../../../src/resources/SignIn.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,EACd,cAAc,IAAI,uBAAuB,EACzC,YAAY,EACZ,qBAAqB,EAEtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAW1D,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAExC,KAAK,cAAc,GAAG,uBAAuB,CAAC;AAO9C,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC;AAE1C,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B,CAAC;AASF;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,QAAQ,GACR,OAAO,GACP,WAAW,GACX,QAAQ,GACR,SAAS,GACT,UAAU,GACV,MAAM,CAAC;AAEX,qBAAa,MAAO,SAAQ,cAAe,YAAW,cAAc;IAClE,QAAQ,SAA6B;IAErC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAQ;IACnC,OAAO,CAAC,IAAI,CAAO;IACnB,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,YAAY,CAA+B;gBAEvC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS;IAMrD,oBAAoB,GAAU,YAAY,cAAc,uDAWtD;IAEF,oBAAoB,GAAU,QAAQ,gBAAgB,KAAG,OAAO,CAAC,cAAc,CAAC,CAwB9E;IAEF,cAAc,GAAU,QAAQ,gBAAgB,KAAG,OAAO,CAAC,IAAI,CAAC,CAS9D;IAEF,kBAAkB,GAChB,UAAU,iBAAiB,EAC3B,UAAS,qBAA0B,KAClC,OAAO,CAAC,cAAc,CAAC,CAqBxB;IAEF,iBAAiB,GAAU,WAAW,MAAM,EAAE,cAAc,GAAG,KAAG,OAAO,CAAC,cAAc,CAAC,CAEvF;IAEF,sBAAsB,GAAU,OAAO,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC,CAE3D;IAEF,uBAAuB,QAAa,OAAO,CAAC,uBAAuB,CAAC,CAuBlE;IAEF,OAAO,CAAC,iBAAiB;YA+BX,kBAAkB;IAwBhC;;;;OAIG;IACH,OAAO,CAAC,2BAA2B;IAWnC;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAgBzB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,iBAAiB,CA2BvB;YAEY,mBAAmB;YAOnB,gBAAgB;IAOjB,mBAAmB,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;CAGnE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"construct.d.ts","sourceRoot":"","sources":["../../../src/utils/construct.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,UAAU,cAAe,SAAQ,OAAO,CAAC,GAAG,CAAC;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EACb,eAAe,GACf,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtB,KAAK,CAAC,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrD;AAED,UAAU,eAAe,CAAC,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,CAAC,CAAC;CACf;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,OAAO,EACxC,MAAM,EAAE,cAAc,EACtB,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,GAC3B,CAAC,SAAS,IAAI,GAAG,MAAM,GAAG,GAAG,CAAC;AAsEjC;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,WAO5C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAI,aAAa,MAAM,EAAE,cAAc,MAAM,KAAG,OAQ3E,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,SAAS,6BAA6B,KAAG,MAsBxE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,KAAG,IAIhD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,QAAO,MAAM,GAAG,IAK3C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC9B,cAAc,eAAe,EAC7B,qBAAqB,MAAM,KAC1B,MAcF,CAAC;AAsBF,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,GAAG,CAE5C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,GAAG,MAAM,CAGrD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,KAAG,MAEhD,CAAC;AAEF,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,MAAM,CAWtD;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,GAAG,GAAG,CAM5E;AAUD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAYlD;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,WAMlD;AAED,eAAO,MAAM,iBAAiB,GAC3B,wBAAwB,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,SAAS,EAAE,eAAe,MAAM,MACjF,MAAM,GAAG,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"construct.d.ts","sourceRoot":"","sources":["../../../src/utils/construct.ts"],"names":[],"mappings":"AAWA,MAAM,MAAM,6BAA6B,GAAG;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,UAAU,cAAe,SAAQ,OAAO,CAAC,GAAG,CAAC;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EACb,eAAe,GACf,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACtB,KAAK,CAAC,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrD;AAED,UAAU,eAAe,CAAC,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,CAAC,CAAC;CACf;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,OAAO,EACxC,MAAM,EAAE,cAAc,EACtB,OAAO,CAAC,EAAE,eAAe,CAAC,CAAC,CAAC,GAC3B,CAAC,SAAS,IAAI,GAAG,MAAM,GAAG,GAAG,CAAC;AAsEjC;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,WAO5C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAI,aAAa,MAAM,EAAE,cAAc,MAAM,KAAG,OAQ3E,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,SAAS,6BAA6B,KAAG,MAsBxE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,KAAG,IAIhD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,QAAO,MAAM,GAAG,IAK3C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC9B,cAAc,eAAe,EAC7B,qBAAqB,MAAM,KAC1B,MAcF,CAAC;AAsBF,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,GAAG,CAE5C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,GAAG,MAAM,CAGrD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,KAAG,MAEhD,CAAC;AAEF,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,MAAM,CAWtD;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,GAAG,GAAG,CAM5E;AAUD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAYlD;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,WAMlD;AAED,eAAO,MAAM,iBAAiB,GAC3B,wBAAwB,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,SAAS,EAAE,eAAe,MAAM,MACjF,MAAM,GAAG,GAAG,MAAM,YA+BlB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redirectUrls.d.ts","sourceRoot":"","sources":["../../../src/utils/redirectUrls.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAIjF;;;;;;GAMG;AACH,qBAAa,YAAY;;IACvB,OAAO,CAAC,MAAM,CAAC,IAAI,CAQjB;IAEF,OAAO,CAAC,MAAM,CAAC,SAAS,CAAmB;IAE3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAChD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkB;IAC5C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAoD;gBAEzE,OAAO,EAAE,qBAAqB,EAAE,KAAK,GAAE,eAAoB,EAAE,YAAY,GAAE,GAAQ;IAO/F,iBAAiB;IAIjB,iBAAiB;IAIjB,wBAAwB;IAIxB,cAAc;
|
|
1
|
+
{"version":3,"file":"redirectUrls.d.ts","sourceRoot":"","sources":["../../../src/utils/redirectUrls.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAIjF;;;;;;GAMG;AACH,qBAAa,YAAY;;IACvB,OAAO,CAAC,MAAM,CAAC,IAAI,CAQjB;IAEF,OAAO,CAAC,MAAM,CAAC,SAAS,CAAmB;IAE3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAChD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAkB;IAC9C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAkB;IAC5C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAoD;gBAEzE,OAAO,EAAE,qBAAqB,EAAE,KAAK,GAAE,eAAoB,EAAE,YAAY,GAAE,GAAQ;IAO/F,iBAAiB;IAIjB,iBAAiB;IAIjB,wBAAwB;IAIxB,cAAc;CAiJf"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tern-secure/auth",
|
|
3
|
-
"version": "1.1.0-canary.
|
|
3
|
+
"version": "1.1.0-canary.v20251024005655",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/TernSecure/auth.git",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"server-only": "^0.0.1",
|
|
27
27
|
"tslib": "2.4.1",
|
|
28
|
-
"@tern-secure/shared": "1.3.0-canary.
|
|
29
|
-
"@tern-secure/types": "1.1.0-canary.
|
|
28
|
+
"@tern-secure/shared": "1.3.0-canary.v20251024005655",
|
|
29
|
+
"@tern-secure/types": "1.1.0-canary.v20251024005655"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"firebase": "^12.0.0",
|