@tern-secure/auth 1.1.0-canary.v20251023005301 → 1.1.0-canary.v20251028151628
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/auth/cookies/session.js +2 -2
- package/dist/cjs/auth/cookies/session.js.map +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/instance/TernAuth.js +14 -11
- 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/resources/SignUp.js +31 -2
- package/dist/cjs/resources/SignUp.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/auth/cookies/session.js +2 -2
- package/dist/esm/auth/cookies/session.js.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/instance/TernAuth.js +14 -11
- 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/resources/SignUp.js +31 -2
- package/dist/esm/resources/SignUp.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/resources/SignUp.d.ts +10 -7
- package/dist/types/resources/SignUp.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
|
@@ -24,8 +24,8 @@ __export(session_exports, {
|
|
|
24
24
|
module.exports = __toCommonJS(session_exports);
|
|
25
25
|
var import_cookie = require("@tern-secure/shared/cookie");
|
|
26
26
|
const SESSION_COOKIE_NAME = "__session";
|
|
27
|
-
const ID_TOKEN_COOKIE_NAME = "
|
|
28
|
-
const REFRESH_TOKEN_COOKIE_NAME = "
|
|
27
|
+
const ID_TOKEN_COOKIE_NAME = "TernSecure_[DEFAULT]";
|
|
28
|
+
const REFRESH_TOKEN_COOKIE_NAME = "TernSecureID_[DEFAULT]";
|
|
29
29
|
const CUSTOM_COOKIE_NAME = "__custom";
|
|
30
30
|
const createSessionCookie = () => {
|
|
31
31
|
const sessionCookie = (0, import_cookie.cookieHandler)(SESSION_COOKIE_NAME);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/auth/cookies/session.ts"],"sourcesContent":["import { cookieHandler, getCookieName, getCookiePrefix } from '@tern-secure/shared/cookie';\n\nconst SESSION_COOKIE_NAME = '__session';\nconst ID_TOKEN_COOKIE_NAME = '
|
|
1
|
+
{"version":3,"sources":["../../../../src/auth/cookies/session.ts"],"sourcesContent":["import { cookieHandler, getCookieName, getCookiePrefix } from '@tern-secure/shared/cookie';\n\nconst SESSION_COOKIE_NAME = '__session';\nconst ID_TOKEN_COOKIE_NAME = 'TernSecure_[DEFAULT]';\nconst REFRESH_TOKEN_COOKIE_NAME = 'TernSecureID_[DEFAULT]';\nconst CUSTOM_COOKIE_NAME = '__custom';\n\nexport type SessionCookieHandler = {\n set: (token: string) => void;\n remove: () => void;\n get: () => string | undefined;\n};\n\nexport const createSessionCookie = (): SessionCookieHandler => {\n const sessionCookie = cookieHandler(SESSION_COOKIE_NAME);\n\n const set = (token: string) => {\n sessionCookie.set(token, {\n httpOnly: false,\n secure: true,\n sameSite: 'strict',\n path: '/',\n });\n };\n\n const remove = () => {\n sessionCookie.remove({\n path: '/',\n });\n };\n\n const get = () => {\n return sessionCookie.get();\n };\n\n return {\n set,\n remove,\n get,\n };\n};\n\nexport const createIdTokenCookie = (): SessionCookieHandler => {\n const prefix = getCookiePrefix();\n const cookieName = getCookieName(ID_TOKEN_COOKIE_NAME, prefix);\n const sessionCookie = cookieHandler(cookieName);\n\n const set = (token: string) => {\n sessionCookie.set(token, {\n httpOnly: false,\n secure: true,\n sameSite: 'strict',\n path: '/',\n });\n };\n\n const remove = () => {\n sessionCookie.remove({\n path: '/',\n });\n };\n\n const get = () => sessionCookie.get();\n\n return {\n set,\n remove,\n get,\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAA8D;AAE9D,MAAM,sBAAsB;AAC5B,MAAM,uBAAuB;AAC7B,MAAM,4BAA4B;AAClC,MAAM,qBAAqB;AAQpB,MAAM,sBAAsB,MAA4B;AAC7D,QAAM,oBAAgB,6BAAc,mBAAmB;AAEvD,QAAM,MAAM,CAAC,UAAkB;AAC7B,kBAAc,IAAI,OAAO;AAAA,MACvB,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,MAAM;AACnB,kBAAc,OAAO;AAAA,MACnB,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAEA,QAAM,MAAM,MAAM;AAChB,WAAO,cAAc,IAAI;AAAA,EAC3B;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,MAAM,sBAAsB,MAA4B;AAC7D,QAAM,aAAS,+BAAgB;AAC/B,QAAM,iBAAa,6BAAc,sBAAsB,MAAM;AAC7D,QAAM,oBAAgB,6BAAc,UAAU;AAE9C,QAAM,MAAM,CAAC,UAAkB;AAC7B,kBAAc,IAAI,OAAO;AAAA,MACvB,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,MAAM;AACnB,kBAAc,OAAO;AAAA,MACnB,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAEA,QAAM,MAAM,MAAM,cAAc,IAAI;AAEpC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
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 SignUpFallbackRedirectUrl,\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;AAkBjD,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.v20251028151628";
|
|
44
44
|
static sdkMetadata = {
|
|
45
45
|
name: "@tern-secure/auth",
|
|
46
|
-
version: "1.1.0-canary.
|
|
46
|
+
version: "1.1.0-canary.v20251028151628",
|
|
47
47
|
environment: process.env.NODE_ENV || "production"
|
|
48
48
|
};
|
|
49
49
|
static instance = null;
|
|
@@ -178,7 +178,10 @@ class TernSecureAuth {
|
|
|
178
178
|
if (!this.#options.apiUrl) {
|
|
179
179
|
throw new Error("apiUrl is required to initialize TernSecureAuth");
|
|
180
180
|
}
|
|
181
|
-
this.initializeFirebaseApp(this.#options.ternSecureConfig
|
|
181
|
+
this.initializeFirebaseApp(this.#options.ternSecureConfig, {
|
|
182
|
+
appName: this.#options.appName,
|
|
183
|
+
tenantId: this.#options.tenantId
|
|
184
|
+
});
|
|
182
185
|
const isBrowserCookiePersistence = this.#options.persistence === "browserCookie";
|
|
183
186
|
if (!isBrowserCookiePersistence) {
|
|
184
187
|
this.authStateUnsubscribe = this.initAuthStateListener();
|
|
@@ -201,8 +204,8 @@ class TernSecureAuth {
|
|
|
201
204
|
throw error;
|
|
202
205
|
}
|
|
203
206
|
};
|
|
204
|
-
initializeFirebaseApp(config) {
|
|
205
|
-
const appName =
|
|
207
|
+
initializeFirebaseApp(config, options) {
|
|
208
|
+
const appName = (options == null ? void 0 : options.appName) || "[DEFAULT]";
|
|
206
209
|
this.firebaseClientApp = (0, import_app.getApps)().length === 0 ? (0, import_app.initializeApp)(config, appName) : (0, import_app.getApps)()[0];
|
|
207
210
|
const persistence = this.#setPersistence();
|
|
208
211
|
const auth = (0, import_auth.initializeAuth)(this.firebaseClientApp, {
|
|
@@ -210,8 +213,8 @@ class TernSecureAuth {
|
|
|
210
213
|
popupRedirectResolver: import_auth.browserPopupRedirectResolver
|
|
211
214
|
});
|
|
212
215
|
this.auth = auth;
|
|
213
|
-
if (
|
|
214
|
-
this.auth.tenantId =
|
|
216
|
+
if (options == null ? void 0 : options.tenantId) {
|
|
217
|
+
this.auth.tenantId = options.tenantId;
|
|
215
218
|
}
|
|
216
219
|
this.#configureEmulator();
|
|
217
220
|
(0, import_installations.getInstallations)(this.firebaseClientApp);
|
|
@@ -324,7 +327,7 @@ class TernSecureAuth {
|
|
|
324
327
|
this.signedInSession = null;
|
|
325
328
|
}
|
|
326
329
|
}
|
|
327
|
-
async
|
|
330
|
+
checkRedirectResult = async () => {
|
|
328
331
|
try {
|
|
329
332
|
const result = await (0, import_auth.getRedirectResult)(this.auth);
|
|
330
333
|
if (result) {
|
|
@@ -342,9 +345,9 @@ class TernSecureAuth {
|
|
|
342
345
|
error: authError.code
|
|
343
346
|
};
|
|
344
347
|
}
|
|
345
|
-
}
|
|
348
|
+
};
|
|
346
349
|
getRedirectResult = async () => {
|
|
347
|
-
|
|
350
|
+
return this.checkRedirectResult();
|
|
348
351
|
};
|
|
349
352
|
addListener = (listener) => {
|
|
350
353
|
this.#listeners.push(listener);
|
|
@@ -544,7 +547,7 @@ class TernSecureAuth {
|
|
|
544
547
|
}
|
|
545
548
|
const emulatorUrl = host.startsWith("http") ? host : `http://${host}`;
|
|
546
549
|
try {
|
|
547
|
-
(0, import_auth.connectAuthEmulator)(this.auth, emulatorUrl, { disableWarnings:
|
|
550
|
+
(0, import_auth.connectAuthEmulator)(this.auth, emulatorUrl, { disableWarnings: false });
|
|
548
551
|
console.warn(`[TernSecure] Firebase Auth Emulator connected at ${emulatorUrl}`);
|
|
549
552
|
} catch (error) {
|
|
550
553
|
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 appName: this.#options.appName,\n tenantId: this.#options.tenantId,\n });\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(\n config: TernSecureConfig,\n options?: { appName?: string; tenantId?: string },\n ): void {\n const appName = options?.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 (options?.tenantId) {\n this.auth.tenantId = options.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,kBAAkB;AAAA,QACzD,SAAS,KAAK,SAAS;AAAA,QACvB,UAAU,KAAK,SAAS;AAAA,MAC1B,CAAC;AAED,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,sBACN,QACA,SACM;AACN,UAAM,WAAU,mCAAS,YAAW;AACpC,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,mCAAS,UAAU;AACrB,WAAK,KAAK,WAAW,QAAQ;AAAA,IAC/B;AAEA,SAAK,mBAAmB;AAExB,+CAAiB,KAAK,iBAAiB;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,MAAM;AAxSrB;AAySI,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;AAlThC;AAmTI,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":[]}
|
|
@@ -21,17 +21,46 @@ __export(SignUp_exports, {
|
|
|
21
21
|
SignUp: () => SignUp
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(SignUp_exports);
|
|
24
|
-
|
|
24
|
+
var import_errors = require("@tern-secure/shared/errors");
|
|
25
|
+
var import_auth = require("firebase/auth");
|
|
26
|
+
var import_Base = require("./Base");
|
|
27
|
+
class SignUp extends import_Base.TernSecureBase {
|
|
25
28
|
status = null;
|
|
26
29
|
username = null;
|
|
27
30
|
firstName = null;
|
|
28
31
|
lastName = null;
|
|
32
|
+
displayName = null;
|
|
29
33
|
email = null;
|
|
34
|
+
phoneNumber = null;
|
|
30
35
|
auth;
|
|
31
|
-
ternSecureConfig;
|
|
32
36
|
constructor(auth) {
|
|
37
|
+
super();
|
|
33
38
|
this.auth = auth;
|
|
34
39
|
}
|
|
40
|
+
withEmailAndPassword = async (params) => {
|
|
41
|
+
try {
|
|
42
|
+
const { email, password } = params;
|
|
43
|
+
const { user, providerId, operationType } = await (0, import_auth.createUserWithEmailAndPassword)(
|
|
44
|
+
this.auth,
|
|
45
|
+
email,
|
|
46
|
+
password
|
|
47
|
+
);
|
|
48
|
+
return {
|
|
49
|
+
status: "complete",
|
|
50
|
+
user,
|
|
51
|
+
providerId,
|
|
52
|
+
operationType,
|
|
53
|
+
message: "User registration successful"
|
|
54
|
+
};
|
|
55
|
+
} catch (error) {
|
|
56
|
+
const authError = (0, import_errors.handleFirebaseAuthError)(error);
|
|
57
|
+
return {
|
|
58
|
+
status: "error",
|
|
59
|
+
message: authError.message,
|
|
60
|
+
error: authError.code
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
};
|
|
35
64
|
withSocialProvider() {
|
|
36
65
|
throw new Error("Method not implemented.");
|
|
37
66
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/resources/SignUp.ts"],"sourcesContent":["import type {\n
|
|
1
|
+
{"version":3,"sources":["../../../src/resources/SignUp.ts"],"sourcesContent":["import { handleFirebaseAuthError } from '@tern-secure/shared/errors';\nimport type {\n SignUpInitialValue,\n SignUpResource,\n SignUpResponse,\n SignUpStatus,\n} from '@tern-secure/types';\nimport type { Auth } from 'firebase/auth';\nimport { createUserWithEmailAndPassword } from 'firebase/auth';\n\nimport { TernSecureBase } from './Base';\n\nexport class SignUp extends TernSecureBase implements SignUpResource {\n status: SignUpStatus | null = null;\n username: string | null = null;\n firstName: string | null = null;\n lastName: string | null = null;\n displayName: string | null = null;\n email: string | null = null;\n phoneNumber: string | null = null;\n private auth: Auth;\n\n constructor(auth: Auth) {\n super();\n this.auth = auth;\n }\n\n withEmailAndPassword = async (params: SignUpInitialValue): Promise<SignUpResponse> => {\n try {\n const { email, password } = params;\n const { user, providerId, operationType } = await createUserWithEmailAndPassword(\n this.auth,\n email,\n password,\n );\n return {\n status: 'complete',\n user,\n providerId,\n operationType,\n message: 'User registration successful',\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 withSocialProvider(): Promise<void> {\n throw new Error('Method not implemented.');\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAwC;AAQxC,kBAA+C;AAE/C,kBAA+B;AAExB,MAAM,eAAe,2BAAyC;AAAA,EACnE,SAA8B;AAAA,EAC9B,WAA0B;AAAA,EAC1B,YAA2B;AAAA,EAC3B,WAA0B;AAAA,EAC1B,cAA6B;AAAA,EAC7B,QAAuB;AAAA,EACvB,cAA6B;AAAA,EACrB;AAAA,EAER,YAAY,MAAY;AACtB,UAAM;AACN,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,uBAAuB,OAAO,WAAwD;AACpF,QAAI;AACF,YAAM,EAAE,OAAO,SAAS,IAAI;AAC5B,YAAM,EAAE,MAAM,YAAY,cAAc,IAAI,UAAM;AAAA,QAChD,KAAK;AAAA,QACL;AAAA,QACA;AAAA,MACF;AACA,aAAO;AAAA,QACL,QAAQ;AAAA,QACR;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF,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,EAEA,qBAAoC;AAClC,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC3C;AACF;","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":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uBAA6B;AAC7B,oBAAiE;AAGjE,uBAAyD;AASlD,MAAM,aAAa;AAAA,EACxB,OAAe,OAAkC;AAAA,IAC/C;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAe,YAAY,CAAC,aAAa;AAAA,EAExB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,SAAgC,QAAyB,CAAC,GAAG,eAAoB,CAAC,GAAG;AAC/F,SAAK,UAAU;AACf,SAAK,cAAc,KAAK,OAAO,WAAW,CAAC,CAAC;AAC5C,SAAK,YAAY,KAAK,OAAO,SAAS,CAAC,CAAC;AACxC,SAAK,mBAAmB,KAAK,mBAAmB,gBAAgB,CAAC,CAAC;AAAA,EACpE;AAAA,EAEA,oBAAoB;AAClB,WAAO,KAAK,gBAAgB,QAAQ;AAAA,EACtC;AAAA,EAEA,oBAAoB;AAClB,WAAO,KAAK,gBAAgB,QAAQ;AAAA,EACtC;AAAA,EAEA,2BAA2B;AACzB,WAAO,KAAK,gBAAgB,KAAK,kBAAkB,CAAC;AAAA,EACtD;AAAA,EAEA,iBAAiB;AACf,WAAO,KAAK,gBAAgB,KAAK,YAAY,CAAC;AAAA,EAChD;AAAA,EAEA,gBAAgB,KAAiE;AAC/E,UAAM,aAAa,OAAO;AAAA,MACxB,OAAO,QAAQ,GAAG,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,KAAC,+BAAa,GAAG,GAAG,KAAK,CAAC;AAAA,IACtE;AACA,WAAO,IAAI,oBAAgB,+BAAgB,UAAU,CAA2B;AAAA,EAClF;AAAA,EAEA,oBAAoB;AAClB,WAAO,OAAO;AAAA,MACZ,OAAO,QAAQ,EAAE,GAAG,KAAK,iBAAiB,CAAC,EAAE;AAAA,QAAO,CAAC,CAAC,GAAG,MACvD,aAAa,UAAU,SAAS,GAAG;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,cAAc;AACZ,UAAM,yBACJ,KAAK,iBAAiB,0BACtB,KAAK,UAAU,0BACf,KAAK,YAAY;AACnB,UAAM,4BACJ,KAAK,iBAAiB,6BACtB,KAAK,UAAU,6BACf,KAAK,YAAY;AACnB,UAAM,yBACJ,KAAK,iBAAiB,0BACtB,KAAK,UAAU,0BACf,KAAK,YAAY;AACnB,UAAM,4BACJ,KAAK,iBAAiB,6BACtB,KAAK,UAAU,6BACf,KAAK,YAAY;AACnB,UAAM,iBACJ,KAAK,iBAAiB,kBACtB,KAAK,UAAU,kBACf,KAAK,YAAY;AACnB,UAAM,iBACJ,KAAK,iBAAiB,kBACtB,KAAK,UAAU,kBACf,KAAK,YAAY;AACnB,UAAM,cACJ,KAAK,iBAAiB,eACtB,KAAK,UAAU,eACf,KAAK,YAAY;AAEnB,UAAM,MAAuB;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,gBAAgB,QAA6B;AAC3C,UAAM,WAAW,GAAG,MAAM;AAC1B,UAAM,cAAc,GAAG,MAAM;AAE7B,QAAI;AAEJ,QAAI;AAEJ,aACE,KAAK,iBAAiB,QAAQ,KAAK,KAAK,UAAU,QAAQ,KAAK,KAAK,YAAY,QAAQ;AAC1F,QAAI,QAAQ;AACV,oBAAc;AAAA,IAChB;AAGA,eAAW,KAAK,iBAAiB;AACjC,QAAI,QAAQ;AACV,oBAAc;AAAA,IAChB;AAGA,eACE,KAAK,iBAAiB,WAAW,KACjC,KAAK,UAAU,WAAW,KAC1B,KAAK,YAAY,WAAW;AAC9B,QAAI,QAAQ;AACV,oBAAc;AAAA,IAChB;AAEA,QAAI,CAAC,QAAQ;AACX,UAAI,OAAO,WAAW,aAAa;AACjC,eAAO;AAAA,MACT;AACA,aAAO,OAAO,SAAS;AAAA,IACzB;AACA,WAAO,UAAU;AAAA,EACnB;AAAA,EAEA,OAAO,KAAc;AACnB,UAAM,MAAM,CAAC;AACb,iBAAa,KAAK,QAAQ,SAAO;AAE/B,UAAI,GAAG,IAAI,IAAI,GAAG;AAAA,IACpB,CAAC;AAMD,eAAO;AAAA,MACL,KAAK,iBAAiB,KAAK,oBAAgB,2BAAY,KAAK,OAAO,CAAC,CAAC;AAAA,MACrE,SAAO,IAAI,SAAS;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,mBAAmB,KAAU;AAC3B,UAAM,MAAM,CAAC;AACb,iBAAa,KAAK,QAAQ,SAAO;AAC/B,UAAI,eAAe,iBAAiB;AAClC,YAAI,GAAG,IAAI,IAAI,QAAI,+BAAa,GAAG,CAAC;AAAA,MACtC,OAAO;AACL,YAAI,GAAG,IAAI,QAAI,+BAAa,GAAG,CAAC;AAAA,MAClC;AAAA,IACF,CAAC;AAED,eAAO;AAAA,MACL,KAAK,iBAAiB,KAAK,oBAAgB,2BAAY,KAAK,OAAO,CAAC,CAAC;AAAA,MACrE,SAAO,IAAI,SAAS;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,gBAAgB,KAAsB;AACpC,UAAM,SAAS,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS;
|
|
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":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { cookieHandler, getCookieName, getCookiePrefix } from "@tern-secure/shared/cookie";
|
|
2
2
|
const SESSION_COOKIE_NAME = "__session";
|
|
3
|
-
const ID_TOKEN_COOKIE_NAME = "
|
|
4
|
-
const REFRESH_TOKEN_COOKIE_NAME = "
|
|
3
|
+
const ID_TOKEN_COOKIE_NAME = "TernSecure_[DEFAULT]";
|
|
4
|
+
const REFRESH_TOKEN_COOKIE_NAME = "TernSecureID_[DEFAULT]";
|
|
5
5
|
const CUSTOM_COOKIE_NAME = "__custom";
|
|
6
6
|
const createSessionCookie = () => {
|
|
7
7
|
const sessionCookie = cookieHandler(SESSION_COOKIE_NAME);
|