@tern-secure/auth 1.1.0-canary.v20251008131428 → 1.1.0-canary.v20251019190011
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/{resources → auth}/AuthCookieManager.js +12 -1
- package/dist/cjs/auth/AuthCookieManager.js.map +1 -0
- package/dist/cjs/auth/cookies/session.js +83 -0
- package/dist/cjs/auth/cookies/session.js.map +1 -0
- package/dist/cjs/auth/request.js +159 -0
- package/dist/cjs/auth/request.js.map +1 -0
- package/dist/cjs/index.js +2 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/instance/TernAuth.js +163 -19
- package/dist/cjs/instance/TernAuth.js.map +1 -1
- package/dist/cjs/instance/events.js +3 -2
- package/dist/cjs/instance/events.js.map +1 -1
- package/dist/cjs/instance/jwtClient.js +72 -0
- package/dist/cjs/instance/jwtClient.js.map +1 -0
- package/dist/cjs/resources/Base.js +7 -0
- package/dist/cjs/resources/Base.js.map +1 -1
- package/dist/cjs/resources/Session.js +105 -0
- package/dist/cjs/resources/Session.js.map +1 -0
- package/dist/cjs/resources/SignIn.js +25 -27
- package/dist/cjs/resources/SignIn.js.map +1 -1
- package/dist/cjs/resources/Token.js +32 -0
- package/dist/cjs/resources/Token.js.map +1 -0
- package/dist/cjs/resources/UserData.js +43 -0
- package/dist/cjs/resources/UserData.js.map +1 -0
- package/dist/cjs/resources/cookie.js +154 -0
- package/dist/cjs/resources/cookie.js.map +1 -0
- package/dist/cjs/resources/internal.js +4 -2
- package/dist/cjs/resources/internal.js.map +1 -1
- package/dist/cjs/utils/jwt.js +46 -0
- package/dist/cjs/utils/jwt.js.map +1 -0
- package/dist/cjs/utils/mapDecode.js +33 -0
- package/dist/cjs/utils/mapDecode.js.map +1 -0
- package/dist/esm/{resources → auth}/AuthCookieManager.js +13 -4
- package/dist/esm/auth/AuthCookieManager.js.map +1 -0
- package/dist/esm/auth/cookies/session.js +58 -0
- package/dist/esm/auth/cookies/session.js.map +1 -0
- package/dist/esm/auth/request.js +134 -0
- package/dist/esm/auth/request.js.map +1 -0
- package/dist/esm/index.js +2 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/instance/TernAuth.js +166 -21
- package/dist/esm/instance/TernAuth.js.map +1 -1
- package/dist/esm/instance/events.js +3 -2
- package/dist/esm/instance/events.js.map +1 -1
- package/dist/esm/instance/jwtClient.js +47 -0
- package/dist/esm/instance/jwtClient.js.map +1 -0
- package/dist/esm/resources/Base.js +7 -0
- package/dist/esm/resources/Base.js.map +1 -1
- package/dist/esm/resources/Session.js +81 -0
- package/dist/esm/resources/Session.js.map +1 -0
- package/dist/esm/resources/SignIn.js +25 -27
- package/dist/esm/resources/SignIn.js.map +1 -1
- package/dist/esm/resources/Token.js +8 -0
- package/dist/esm/resources/Token.js.map +1 -0
- package/dist/esm/resources/UserData.js +19 -0
- package/dist/esm/resources/UserData.js.map +1 -0
- package/dist/esm/resources/cookie.js +130 -0
- package/dist/esm/resources/cookie.js.map +1 -0
- package/dist/esm/resources/internal.js +2 -1
- package/dist/esm/resources/internal.js.map +1 -1
- package/dist/esm/utils/jwt.js +22 -0
- package/dist/esm/utils/jwt.js.map +1 -0
- package/dist/esm/utils/mapDecode.js +9 -0
- package/dist/esm/utils/mapDecode.js.map +1 -0
- package/dist/types/{resources → auth}/AuthCookieManager.d.ts +5 -1
- package/dist/types/auth/AuthCookieManager.d.ts.map +1 -0
- package/dist/types/auth/cookies/session.d.ts +8 -0
- package/dist/types/auth/cookies/session.d.ts.map +1 -0
- package/dist/types/auth/request.d.ts +49 -0
- package/dist/types/auth/request.d.ts.map +1 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/instance/TernAuth.d.ts +27 -5
- package/dist/types/instance/TernAuth.d.ts.map +1 -1
- package/dist/types/instance/events.d.ts +9 -1
- package/dist/types/instance/events.d.ts.map +1 -1
- package/dist/types/instance/jwtClient.d.ts +22 -0
- package/dist/types/instance/jwtClient.d.ts.map +1 -0
- package/dist/types/resources/Base.d.ts +6 -0
- package/dist/types/resources/Base.d.ts.map +1 -1
- package/dist/types/resources/Session.d.ts +49 -0
- package/dist/types/resources/Session.d.ts.map +1 -0
- package/dist/types/resources/SignIn.d.ts +8 -6
- package/dist/types/resources/SignIn.d.ts.map +1 -1
- package/dist/types/resources/Token.d.ts +5 -0
- package/dist/types/resources/Token.d.ts.map +1 -0
- package/dist/types/resources/UserData.d.ts +8 -0
- package/dist/types/resources/UserData.d.ts.map +1 -0
- package/dist/types/resources/cookie.d.ts +24 -0
- package/dist/types/resources/cookie.d.ts.map +1 -0
- package/dist/types/resources/internal.d.ts +2 -1
- package/dist/types/resources/internal.d.ts.map +1 -1
- package/dist/types/utils/jwt.d.ts +12 -0
- package/dist/types/utils/jwt.d.ts.map +1 -0
- package/dist/types/utils/mapDecode.d.ts +4 -0
- package/dist/types/utils/mapDecode.d.ts.map +1 -0
- package/package.json +4 -5
- package/dist/cjs/resources/AuthCookieManager.js.map +0 -1
- package/dist/esm/resources/AuthCookieManager.js.map +0 -1
- package/dist/types/resources/AuthCookieManager.d.ts.map +0 -1
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.ts"],"sourcesContent":["export { TernSecureAuth } from './instance/TernAuth';\nexport type { TernAuth } from './instance/TernAuth';\nexport { TernServerAuth } from './instance/TernAuthServer';\nexport type { TernServerAuthOptions, AuthenticatedApp } from './instance/TernAuthServer';\n\nexport { CoreApiClient, coreApiClient } from './instance/coreApiClient';\nexport type { \n ApiResponse, \n ApiResponseJSON, \n RequestOptions,\n BeforeRequestHook,\n AfterResponseHook\n} from './instance/coreApiClient';\n\nexport { SignIn, TernSecureBase } from './resources/internal';\n\nexport type {\n TernSecureConfig,\n
|
|
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 SignInRedirectUrl,\n SignUpRedirectUrl,\n ResendEmailVerification,\n TernSecureUser,\n TernSecureState\n} from '@tern-secure/types';"],"mappings":"AAAA,SAAS,sBAAsB;AAE/B,SAAS,sBAAsB;AAG/B,SAAS,eAAe,qBAAqB;AAS7C,SAAS,QAAQ,gBAAgB,gBAAgB;","names":[]}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
browserLocalPersistence,
|
|
8
8
|
browserSessionPersistence,
|
|
9
9
|
connectAuthEmulator,
|
|
10
|
+
getIdToken,
|
|
10
11
|
getRedirectResult,
|
|
11
12
|
initializeAuth,
|
|
12
13
|
inMemoryPersistence,
|
|
@@ -14,18 +15,20 @@ import {
|
|
|
14
15
|
onIdTokenChanged
|
|
15
16
|
} from "firebase/auth";
|
|
16
17
|
import { getInstallations } from "firebase/installations";
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
18
|
+
import { createClientAuthRequest } from "../auth/request";
|
|
19
|
+
import { AuthCookieManager, Session, SignIn, SignUp, TernSecureBase } from "../resources/internal";
|
|
20
|
+
import { buildURL, hasRedirectLoop } from "../utils/construct";
|
|
19
21
|
import { createCoreApiClient } from "./c_coreApiClient";
|
|
20
22
|
import { eventBus, events } from "./events";
|
|
23
|
+
import { createClientFromJwt } from "./jwtClient";
|
|
21
24
|
function inBrowser() {
|
|
22
25
|
return typeof window !== "undefined";
|
|
23
26
|
}
|
|
24
27
|
class TernSecureAuth {
|
|
25
|
-
static version = "1.1.0-canary.
|
|
28
|
+
static version = "1.1.0-canary.v20251019190011";
|
|
26
29
|
static sdkMetadata = {
|
|
27
30
|
name: "@tern-secure/auth",
|
|
28
|
-
version: "1.1.0-canary.
|
|
31
|
+
version: "1.1.0-canary.v20251019190011",
|
|
29
32
|
environment: process.env.NODE_ENV || "production"
|
|
30
33
|
};
|
|
31
34
|
static instance = null;
|
|
@@ -47,9 +50,11 @@ class TernSecureAuth {
|
|
|
47
50
|
#listeners = [];
|
|
48
51
|
#options = {};
|
|
49
52
|
#authCookieManager;
|
|
53
|
+
#clientAuthRequest;
|
|
50
54
|
#publicEventBus = createTernAuthEventBus();
|
|
51
55
|
signIn;
|
|
52
56
|
signUp;
|
|
57
|
+
session;
|
|
53
58
|
get isReady() {
|
|
54
59
|
return this.status === "ready";
|
|
55
60
|
}
|
|
@@ -100,6 +105,15 @@ class TernSecureAuth {
|
|
|
100
105
|
TernSecureBase.ternsecure = this;
|
|
101
106
|
}
|
|
102
107
|
getApiClient = () => this.#apiClient;
|
|
108
|
+
/**
|
|
109
|
+
* Get user data for the provided ID token via backend API
|
|
110
|
+
*/
|
|
111
|
+
async getUserData() {
|
|
112
|
+
if (!this.#clientAuthRequest) {
|
|
113
|
+
throw new Error("Client auth request not initialized");
|
|
114
|
+
}
|
|
115
|
+
return this.#clientAuthRequest.getUserData();
|
|
116
|
+
}
|
|
103
117
|
setLoading(isLoading) {
|
|
104
118
|
this.isLoading = isLoading;
|
|
105
119
|
}
|
|
@@ -109,6 +123,9 @@ class TernSecureAuth {
|
|
|
109
123
|
_internal_getOption(key) {
|
|
110
124
|
return this.#options[key];
|
|
111
125
|
}
|
|
126
|
+
_internal_getAllOptions() {
|
|
127
|
+
return Object.freeze({ ...this.#options });
|
|
128
|
+
}
|
|
112
129
|
static getorCreateInstance(options) {
|
|
113
130
|
if (!this.instance) {
|
|
114
131
|
this.instance = new TernSecureAuth(options);
|
|
@@ -139,11 +156,19 @@ class TernSecureAuth {
|
|
|
139
156
|
throw new Error("apiUrl is required to initialize TernSecureAuth");
|
|
140
157
|
}
|
|
141
158
|
this.initializeFirebaseApp(this.#options.ternSecureConfig);
|
|
142
|
-
|
|
159
|
+
const isBrowserCookiePersistence = this.#options.persistence === "browserCookie";
|
|
160
|
+
if (!isBrowserCookiePersistence) {
|
|
161
|
+
this.authStateUnsubscribe = this.initAuthStateListener();
|
|
162
|
+
}
|
|
143
163
|
this.#authCookieManager = new AuthCookieManager();
|
|
144
164
|
this.csrfToken = this.#authCookieManager.getCSRFToken();
|
|
165
|
+
this.#clientAuthRequest = createClientAuthRequest();
|
|
145
166
|
this.signIn = new SignIn(this.auth, this.csrfToken);
|
|
146
167
|
this.signUp = new SignUp(this.auth);
|
|
168
|
+
eventBus.on(events.SessionChanged, () => {
|
|
169
|
+
this.#setCreatedActiveSession(this.user || null);
|
|
170
|
+
this.#emit();
|
|
171
|
+
});
|
|
147
172
|
this.#setStatus("ready");
|
|
148
173
|
this.#publicEventBus.emit(ternEvents.Status, "ready");
|
|
149
174
|
return this;
|
|
@@ -168,6 +193,35 @@ class TernSecureAuth {
|
|
|
168
193
|
this.#configureEmulator();
|
|
169
194
|
getInstallations(this.firebaseClientApp);
|
|
170
195
|
}
|
|
196
|
+
/**
|
|
197
|
+
* use when cookie are not httpOnly
|
|
198
|
+
*/
|
|
199
|
+
initClient = () => {
|
|
200
|
+
var _a;
|
|
201
|
+
const idTokenInCookie = (_a = this.#authCookieManager) == null ? void 0 : _a.getIdTokenCookie();
|
|
202
|
+
const jwtClient = createClientFromJwt(idTokenInCookie || null);
|
|
203
|
+
this.user = jwtClient;
|
|
204
|
+
this.#emit();
|
|
205
|
+
};
|
|
206
|
+
/**
|
|
207
|
+
* @deprecated will be removed in future releases.
|
|
208
|
+
*/
|
|
209
|
+
initClientAuthRequest = () => {
|
|
210
|
+
var _a;
|
|
211
|
+
(_a = this.#clientAuthRequest) == null ? void 0 : _a.getIdTokenFromCookie().then((idTokenInCookie) => {
|
|
212
|
+
const { token } = idTokenInCookie;
|
|
213
|
+
const jwtClient = createClientFromJwt(token || null);
|
|
214
|
+
this.user = jwtClient;
|
|
215
|
+
this.#emit();
|
|
216
|
+
}).catch((error) => {
|
|
217
|
+
console.error(
|
|
218
|
+
"[ternauth] Error during client auth request initialization:",
|
|
219
|
+
error
|
|
220
|
+
);
|
|
221
|
+
this.user = null;
|
|
222
|
+
this.#emit();
|
|
223
|
+
});
|
|
224
|
+
};
|
|
171
225
|
signOut = async (options) => {
|
|
172
226
|
const redirectUrl = (options == null ? void 0 : options.redirectUrl) || this.#constructAfterSignOutUrl();
|
|
173
227
|
if (options == null ? void 0 : options.onBeforeSignOut) {
|
|
@@ -181,16 +235,29 @@ class TernSecureAuth {
|
|
|
181
235
|
window.location.href = redirectUrl;
|
|
182
236
|
}
|
|
183
237
|
eventBus.emit(events.UserSignOut, null);
|
|
184
|
-
eventBus.emit(events.
|
|
238
|
+
eventBus.emit(events.TokenUpdate, { token: null });
|
|
185
239
|
this.#emit();
|
|
186
240
|
};
|
|
187
241
|
get currentSession() {
|
|
188
242
|
return this.signedInSession;
|
|
189
243
|
}
|
|
244
|
+
initAuthListener() {
|
|
245
|
+
(async () => {
|
|
246
|
+
await this.auth.authStateReady();
|
|
247
|
+
const user = this.auth.currentUser;
|
|
248
|
+
this._currentUser = user;
|
|
249
|
+
this.user = user;
|
|
250
|
+
await this.updateCurrentSession();
|
|
251
|
+
this.#emit();
|
|
252
|
+
})();
|
|
253
|
+
return () => {
|
|
254
|
+
};
|
|
255
|
+
}
|
|
190
256
|
initAuthStateListener() {
|
|
191
257
|
return onAuthStateChanged(this.auth, async (user) => {
|
|
192
258
|
await this.auth.authStateReady();
|
|
193
259
|
this._currentUser = user;
|
|
260
|
+
this.user = user;
|
|
194
261
|
await this.updateCurrentSession();
|
|
195
262
|
this.#emit();
|
|
196
263
|
});
|
|
@@ -199,10 +266,18 @@ class TernSecureAuth {
|
|
|
199
266
|
return onIdTokenChanged(this.auth, async (user) => {
|
|
200
267
|
await this.auth.authStateReady();
|
|
201
268
|
this._currentUser = user;
|
|
269
|
+
this.user = user;
|
|
202
270
|
await this.updateCurrentSession();
|
|
203
271
|
this.#emit();
|
|
204
272
|
});
|
|
205
273
|
}
|
|
274
|
+
async getIdToken() {
|
|
275
|
+
await this.auth.authStateReady();
|
|
276
|
+
if (!this.auth.currentUser) {
|
|
277
|
+
return null;
|
|
278
|
+
}
|
|
279
|
+
return getIdToken(this.auth.currentUser);
|
|
280
|
+
}
|
|
206
281
|
onAuthStateChanged(callback) {
|
|
207
282
|
return onAuthStateChanged(this.auth, callback);
|
|
208
283
|
}
|
|
@@ -223,7 +298,8 @@ class TernSecureAuth {
|
|
|
223
298
|
issuedAtTime: res.issuedAtTime,
|
|
224
299
|
expirationTime: res.expirationTime,
|
|
225
300
|
authTime: res.authTime,
|
|
226
|
-
signInProvider: res.signInProvider || "unknown"
|
|
301
|
+
signInProvider: res.signInProvider || "unknown",
|
|
302
|
+
signInSecondFactor: res.signInSecondFactor
|
|
227
303
|
};
|
|
228
304
|
} catch (error) {
|
|
229
305
|
console.error("[TernSecureAuth] Error updating session:", error);
|
|
@@ -235,7 +311,7 @@ class TernSecureAuth {
|
|
|
235
311
|
const result = await getRedirectResult(this.auth);
|
|
236
312
|
if (result) {
|
|
237
313
|
return {
|
|
238
|
-
|
|
314
|
+
status: "success",
|
|
239
315
|
user: result.user
|
|
240
316
|
};
|
|
241
317
|
}
|
|
@@ -243,13 +319,15 @@ class TernSecureAuth {
|
|
|
243
319
|
} catch (error) {
|
|
244
320
|
const authError = handleFirebaseAuthError(error);
|
|
245
321
|
return {
|
|
246
|
-
|
|
322
|
+
status: "error",
|
|
247
323
|
message: authError.message,
|
|
248
|
-
error: authError.code
|
|
249
|
-
user: null
|
|
324
|
+
error: authError.code
|
|
250
325
|
};
|
|
251
326
|
}
|
|
252
327
|
}
|
|
328
|
+
getRedirectResult = async () => {
|
|
329
|
+
throw new Error("getRedirectResult not implemented");
|
|
330
|
+
};
|
|
253
331
|
addListener = (listener) => {
|
|
254
332
|
this.#listeners.push(listener);
|
|
255
333
|
if (this._currentUser) {
|
|
@@ -269,6 +347,24 @@ class TernSecureAuth {
|
|
|
269
347
|
off = (...args) => {
|
|
270
348
|
this.#publicEventBus.off(...args);
|
|
271
349
|
};
|
|
350
|
+
createActiveSession = async ({
|
|
351
|
+
session,
|
|
352
|
+
redirectUrl
|
|
353
|
+
}) => {
|
|
354
|
+
try {
|
|
355
|
+
if (!session) {
|
|
356
|
+
throw new Error("No session provided to createActiveSession");
|
|
357
|
+
}
|
|
358
|
+
const sessionResult = await session.getIdTokenResult();
|
|
359
|
+
const sessionData = new Session(sessionResult);
|
|
360
|
+
await sessionData.create(this.csrfToken || "");
|
|
361
|
+
await this.redirectAfterSignIn();
|
|
362
|
+
this.#setCreatedActiveSession(session);
|
|
363
|
+
this.#emit();
|
|
364
|
+
} catch (error) {
|
|
365
|
+
console.error("[TernSecureAuth] Error creating active session:", error);
|
|
366
|
+
}
|
|
367
|
+
};
|
|
272
368
|
initialize(options) {
|
|
273
369
|
this._initialize(options);
|
|
274
370
|
return Promise.resolve();
|
|
@@ -351,9 +447,9 @@ class TernSecureAuth {
|
|
|
351
447
|
if (effectiveRedirectUrl) {
|
|
352
448
|
if (inBrowser()) {
|
|
353
449
|
const absoluteRedirectUrl = new URL(effectiveRedirectUrl, window.location.origin).href;
|
|
354
|
-
(_a = paramsForBuildUrl.searchParams) == null ? void 0 : _a.set("
|
|
450
|
+
(_a = paramsForBuildUrl.searchParams) == null ? void 0 : _a.set("redirect_url", absoluteRedirectUrl);
|
|
355
451
|
} else {
|
|
356
|
-
(_b = paramsForBuildUrl.searchParams) == null ? void 0 : _b.set("
|
|
452
|
+
(_b = paramsForBuildUrl.searchParams) == null ? void 0 : _b.set("redirect_url", effectiveRedirectUrl);
|
|
357
453
|
}
|
|
358
454
|
}
|
|
359
455
|
const constructedUrl = buildURL(paramsForBuildUrl, {
|
|
@@ -375,12 +471,60 @@ class TernSecureAuth {
|
|
|
375
471
|
}
|
|
376
472
|
return this.constructUrlWithAuthRedirect(constructedUrl);
|
|
377
473
|
};
|
|
474
|
+
#constructAfterSignInUrl = () => {
|
|
475
|
+
if (!inBrowser()) {
|
|
476
|
+
return "/";
|
|
477
|
+
}
|
|
478
|
+
let redirectPath = void 0;
|
|
479
|
+
const defaultRedirectPath = "/";
|
|
480
|
+
if (this.#options.signInForceRedirectUrl) {
|
|
481
|
+
redirectPath = this.#options.signInForceRedirectUrl;
|
|
482
|
+
}
|
|
483
|
+
if (!redirectPath) {
|
|
484
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
485
|
+
const redirectPathFromParams = urlParams.get("redirect_url");
|
|
486
|
+
if (redirectPathFromParams) {
|
|
487
|
+
redirectPath = redirectPathFromParams;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
if (!redirectPath) {
|
|
491
|
+
redirectPath = defaultRedirectPath;
|
|
492
|
+
}
|
|
493
|
+
const currentPath = window.location.pathname;
|
|
494
|
+
if (hasRedirectLoop(currentPath, redirectPath)) {
|
|
495
|
+
return defaultRedirectPath;
|
|
496
|
+
}
|
|
497
|
+
return this.constructUrlWithAuthRedirect(redirectPath);
|
|
498
|
+
};
|
|
378
499
|
#constructAfterSignOutUrl = () => {
|
|
379
500
|
if (!this.#options.afterSignOutUrl) {
|
|
380
501
|
return "/";
|
|
381
502
|
}
|
|
382
503
|
return this.constructUrlWithAuthRedirect(this.#options.afterSignOutUrl);
|
|
383
504
|
};
|
|
505
|
+
redirectToSignIn = async (options) => {
|
|
506
|
+
if (inBrowser()) {
|
|
507
|
+
const url = this.constructSignInUrl(options);
|
|
508
|
+
window.location.href = url;
|
|
509
|
+
}
|
|
510
|
+
return;
|
|
511
|
+
};
|
|
512
|
+
redirectToSignUp = async (options) => {
|
|
513
|
+
if (inBrowser()) {
|
|
514
|
+
const redirectUrl = this.constructSignUpUrl();
|
|
515
|
+
window.location.href = redirectUrl;
|
|
516
|
+
}
|
|
517
|
+
return;
|
|
518
|
+
};
|
|
519
|
+
redirectAfterSignIn = async () => {
|
|
520
|
+
if (inBrowser()) {
|
|
521
|
+
const destinationUrl = this.#constructAfterSignInUrl();
|
|
522
|
+
window.location.href = destinationUrl;
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
redirectAfterSignUp = () => {
|
|
526
|
+
throw new Error("redirectAfterSignUp is not implemented yet");
|
|
527
|
+
};
|
|
384
528
|
constructSignInUrl = (options) => {
|
|
385
529
|
return this.#buildUrl("signInUrl", { ...options });
|
|
386
530
|
};
|
|
@@ -398,13 +542,11 @@ class TernSecureAuth {
|
|
|
398
542
|
};
|
|
399
543
|
};
|
|
400
544
|
#emit = () => {
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
});
|
|
407
|
-
}
|
|
545
|
+
for (const listener of this.#listeners) {
|
|
546
|
+
listener({
|
|
547
|
+
user: this.user,
|
|
548
|
+
session: this.signedInSession
|
|
549
|
+
});
|
|
408
550
|
}
|
|
409
551
|
};
|
|
410
552
|
#setStatus(newStatus) {
|
|
@@ -416,8 +558,11 @@ class TernSecureAuth {
|
|
|
416
558
|
}
|
|
417
559
|
}
|
|
418
560
|
}
|
|
561
|
+
#setCreatedActiveSession = (session) => {
|
|
562
|
+
this.user = session;
|
|
563
|
+
};
|
|
419
564
|
#setPersistence = () => {
|
|
420
|
-
const persistenceType = this.#options.persistence
|
|
565
|
+
const persistenceType = this.#options.persistence;
|
|
421
566
|
switch (persistenceType) {
|
|
422
567
|
case "browserCookie":
|
|
423
568
|
return inMemoryPersistence;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/instance/TernAuth.ts"],"sourcesContent":["import { handleFirebaseAuthError } from '@tern-secure/shared/errors';\nimport { createTernAuthEventBus, ternEvents } from '@tern-secure/shared/ternStatusEvent';\nimport { stripScheme } from '@tern-secure/shared/url';\nimport { handleValueOrFn } from '@tern-secure/shared/utils';\nimport type {\n DomainOrProxyUrl,\n InstanceType,\n ListenerCallback,\n RedirectOptions,\n SignedInSession,\n SignInRedirectOptions,\n SignInResource,\n SignInResponseTree,\n SignOut,\n SignOutOptions,\n SignUpRedirectOptions,\n SignUpResource,\n TernSecureAuth as TernSecureAuthInterface,\n TernSecureAuthOptions,\n TernSecureAuthStatus,\n TernSecureConfig,\n TernSecureResources,\n TernSecureSDK,\n TernSecureUser,\n UnsubscribeCallback,\n} from '@tern-secure/types';\nimport type { FirebaseApp } from 'firebase/app';\nimport { getApps, initializeApp } from 'firebase/app';\nimport type { Auth, Auth as TernAuth } from 'firebase/auth';\nimport {\n browserLocalPersistence,\n browserSessionPersistence,\n connectAuthEmulator,\n getRedirectResult,\n initializeAuth,\n inMemoryPersistence,\n onAuthStateChanged,\n onIdTokenChanged,\n} from 'firebase/auth';\nimport { getInstallations } from 'firebase/installations';\n\nimport { AuthCookieManager, SignIn, SignUp, TernSecureBase } from '../resources/internal';\nimport { buildURL } from '../utils/construct';\nimport { type ApiClient, createCoreApiClient } from './c_coreApiClient';\nimport { eventBus, events } from './events';\n\nexport function inBrowser(): boolean {\n return typeof window !== 'undefined';\n}\n\nexport { TernAuth };\n\n/**\n * Firebase implementation of the TernSecureAuth interface\n */\nexport class TernSecureAuth implements TernSecureAuthInterface {\n public static version: string = PACKAGE_VERSION;\n public static sdkMetadata: TernSecureSDK = {\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 = {} as TernSecureAuthOptions;\n #authCookieManager?: AuthCookieManager;\n #publicEventBus = createTernAuthEventBus();\n\n signIn!: SignInResource;\n signUp!: SignUpResource;\n\n get isReady(): boolean {\n return this.status === 'ready';\n }\n\n get status(): TernSecureAuthInterface['status'] {\n return this.#status;\n }\n\n get version(): string {\n return TernSecureAuth.version;\n }\n\n set sdkMetadata(metadata: TernSecureSDK) {\n TernSecureAuth.sdkMetadata = metadata;\n }\n\n get sdkMetadata(): TernSecureSDK {\n return TernSecureAuth.sdkMetadata;\n }\n\n get requiresVerification(): boolean {\n return this.#options.requiresVerification ?? true;\n }\n\n get apiUrl(): string {\n return this.#apiUrl;\n }\n\n get domain(): string {\n if (inBrowser()) {\n const strippedDomainString = stripScheme(\n handleValueOrFn(this.#domain, new URL(window.location.href)),\n );\n if (this.#instanceType === 'production') {\n return strippedDomainString;\n }\n return strippedDomainString;\n }\n return '';\n }\n\n get instanceType() {\n return this.#instanceType;\n }\n\n public constructor(options?: TernSecureAuthOptions) {\n this.#domain = options?.ternSecureConfig?.authDomain;\n this.#apiUrl = options?.apiUrl || '';\n this.#instanceType = (process.env.NODE_ENV as InstanceType) || 'production';\n\n this.#apiClient = createCoreApiClient({\n domain: this.#domain,\n apiUrl: options?.apiUrl,\n instanceType: this.instanceType as InstanceType,\n });\n\n this.#publicEventBus.emit(ternEvents.Status, 'loading');\n TernSecureBase.ternsecure = this;\n }\n\n public getApiClient = (): ApiClient => this.#apiClient;\n\n public setLoading(isLoading: boolean): void {\n this.isLoading = isLoading;\n }\n\n public authCookieManager(): AuthCookieManager | undefined {\n return this.#authCookieManager;\n }\n\n public _internal_getOption<K extends keyof TernSecureAuthOptions>(key: K): TernSecureAuthOptions[K] {\n return this.#options[key];\n }\n\n static getorCreateInstance(options?: TernSecureAuthOptions): TernSecureAuth {\n if (!this.instance) {\n this.instance = new TernSecureAuth(options);\n }\n return this.instance;\n }\n\n static clearInstance() {\n if (TernSecureAuth.instance) {\n if (TernSecureAuth.instance.authStateUnsubscribe) {\n TernSecureAuth.instance.authStateUnsubscribe();\n TernSecureAuth.instance.authStateUnsubscribe = null;\n }\n TernSecureAuth.instance = null;\n }\n }\n\n public static initialize(options: TernSecureAuthOptions): TernSecureAuth {\n const instance = this.getorCreateInstance(options);\n instance.#initialize(options);\n return instance;\n }\n\n #initialize = (options: TernSecureAuthOptions): TernSecureAuth => {\n this.#options = this.#initOptions(options);\n\n try {\n if (!this.#options.ternSecureConfig) {\n throw new Error('TernSecureConfig is required to initialize TernSecureAuth');\n }\n\n if (!this.#options.apiUrl) {\n throw new Error('apiUrl is required to initialize TernSecureAuth');\n }\n\n this.initializeFirebaseApp(this.#options.ternSecureConfig);\n this.authStateUnsubscribe = this.initAuthStateListener();\n // /this.authStateUnsubscribe = this._onIdTokenChanged();\n\n this.#authCookieManager = new AuthCookieManager();\n this.csrfToken = this.#authCookieManager.getCSRFToken();\n\n this.signIn = new SignIn(this.auth, this.csrfToken);\n this.signUp = new SignUp(this.auth);\n\n this.#setStatus('ready');\n this.#publicEventBus.emit(ternEvents.Status, 'ready');\n\n return this;\n } catch (error) {\n this.error = error as Error;\n this.#setStatus('error');\n this.#publicEventBus.emit(ternEvents.Status, 'error');\n throw error;\n }\n };\n\n private initializeFirebaseApp(config: TernSecureConfig) {\n const appName = config.appName || '[DEFAULT]';\n this.firebaseClientApp = getApps().length === 0 ? initializeApp(config, appName) : getApps()[0];\n\n const persistence = this.#setPersistence();\n const auth = initializeAuth(this.firebaseClientApp, {\n persistence,\n });\n\n this.auth = auth;\n\n if (config.tenantId) {\n this.auth.tenantId = config.tenantId;\n }\n\n this.#configureEmulator();\n\n getInstallations(this.firebaseClientApp);\n }\n\n public signOut: SignOut = async (options?: SignOutOptions) => {\n const redirectUrl = options?.redirectUrl || this.#constructAfterSignOutUrl();\n if (options?.onBeforeSignOut) {\n await options.onBeforeSignOut();\n }\n\n await this.auth.signOut();\n\n if (options?.onAfterSignOut) {\n await options.onAfterSignOut();\n }\n if (inBrowser()) {\n window.location.href = redirectUrl;\n }\n eventBus.emit(events.UserSignOut, null);\n eventBus.emit(events.TokenRefreshed, { token: null });\n this.#emit();\n };\n\n get currentSession(): SignedInSession | null {\n return this.signedInSession;\n }\n\n private initAuthStateListener(): () => void {\n return onAuthStateChanged(this.auth, async (user: TernSecureUser | null) => {\n await this.auth.authStateReady();\n this._currentUser = user;\n await this.updateCurrentSession();\n\n this.#emit();\n });\n }\n\n private _onIdTokenChanged(): () => void {\n return onIdTokenChanged(this.auth, async (user: TernSecureUser | null) => {\n await this.auth.authStateReady();\n this._currentUser = user;\n await this.updateCurrentSession();\n\n //eventBus.emit(events.TokenRefreshed, { token: user ? await user.getIdTokenResult() : null });\n this.#emit();\n });\n }\n\n public onAuthStateChanged(callback: (cb: any) => void): () => void {\n return onAuthStateChanged(this.auth, callback);\n }\n\n public onIdTokenChanged(callback: (cb: any) => void): () => void {\n return onIdTokenChanged(this.auth, callback);\n }\n\n private async updateCurrentSession(): Promise<void> {\n if (!this._currentUser) {\n this.signedInSession = null;\n return;\n }\n\n try {\n const res = await this._currentUser.getIdTokenResult();\n this.signedInSession = {\n status: 'active',\n token: res.token,\n claims: res.claims,\n issuedAtTime: res.issuedAtTime,\n expirationTime: res.expirationTime,\n authTime: res.authTime,\n signInProvider: res.signInProvider || 'unknown',\n };\n } catch (error) {\n console.error('[TernSecureAuth] Error updating session:', error);\n this.signedInSession = null;\n }\n }\n\n public async checkRedirectResult(): Promise<SignInResponseTree | null> {\n try {\n const result = await getRedirectResult(this.auth);\n if (result) {\n return {\n success: true,\n user: result.user as TernSecureUser,\n };\n }\n return null;\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n return {\n success: false,\n message: authError.message,\n error: authError.code,\n user: null,\n };\n }\n }\n\n public addListener = (listener: ListenerCallback): UnsubscribeCallback => {\n this.#listeners.push(listener);\n if (this._currentUser) {\n listener({\n user: this._currentUser,\n session: this.signedInSession,\n });\n }\n\n const unsubscribe = () => {\n this.#listeners = this.#listeners.filter(l => l !== listener);\n };\n return unsubscribe;\n };\n\n public on: TernSecureAuthInterface['on'] = (...args) => {\n this.#publicEventBus.on(...args);\n };\n\n public off: TernSecureAuthInterface['off'] = (...args) => {\n this.#publicEventBus.off(...args);\n };\n\n public initialize(options: TernSecureAuthOptions): Promise<void> {\n this._initialize(options);\n return Promise.resolve();\n }\n\n public static create(options: TernSecureAuthOptions): TernSecureAuth {\n const instance = this.getorCreateInstance();\n instance.initialize(options);\n return instance;\n }\n\n _initialize = (options: TernSecureAuthOptions): void => {\n this.#options = this.#initOptions(options);\n try {\n if (!this.#options.ternSecureConfig) {\n throw new Error('TernSecureConfig is required to initialize TernSecureAuth');\n }\n\n this.initializeFirebaseApp(this.#options.ternSecureConfig);\n\n this.signIn = new SignIn(this.auth, this.csrfToken);\n this.signUp = new SignUp(this.auth);\n\n this.#setStatus('ready');\n } catch (error) {\n this.error = error as Error;\n this.#setStatus('error');\n throw error;\n }\n };\n\n public constructUrlWithAuthRedirect = (to: string): string => {\n const baseUrl = window.location.origin;\n const url = new URL(to, baseUrl);\n\n if (url.origin === window.location.origin) {\n return url.href;\n }\n\n return url.toString();\n };\n\n #buildUrl = (key: 'signInUrl' | 'signUpUrl', options: RedirectOptions): string => {\n if (!key || !this.isReady) {\n return '';\n }\n\n const baseUrlConfig = key === 'signInUrl' ? this.#options.signInUrl : this.#options.signUpUrl;\n const defaultPagePath = key === 'signInUrl' ? '/sign-in' : '/sign-up';\n const base = baseUrlConfig || defaultPagePath;\n\n let effectiveRedirectUrl: string | null | undefined;\n\n // Priority 1: Get redirect URL from options (signInForceRedirectUrl or signUpForceRedirectUrl)\n if (key === 'signInUrl' && 'signInForceRedirectUrl' in options) {\n effectiveRedirectUrl = options.signInForceRedirectUrl;\n } else if (key === 'signUpUrl' && 'signUpForceRedirectUrl' in options) {\n effectiveRedirectUrl = options.signUpForceRedirectUrl;\n }\n\n // Priority 2: If no force redirect from options, check 'redirect' param in current URL (only in browser)\n if (!effectiveRedirectUrl && inBrowser()) {\n const currentUrlParams = new URLSearchParams(window.location.search);\n const existingRedirectParam = currentUrlParams.get('redirect_url');\n if (existingRedirectParam) {\n effectiveRedirectUrl = existingRedirectParam;\n }\n }\n\n // Priority 3: If still no redirect URL, fallback to current page's full path (only in browser)\n // This ensures that if the call originates from a page, it attempts to redirect back there by default.\n if (!effectiveRedirectUrl && inBrowser()) {\n effectiveRedirectUrl =\n window.location.pathname + window.location.search + window.location.hash;\n }\n\n if (effectiveRedirectUrl && inBrowser()) {\n let signInPagePath: string | undefined;\n try {\n signInPagePath = this.#options.signInUrl\n ? new URL(this.#options.signInUrl, window.location.origin).pathname\n : defaultPagePath;\n } catch {\n signInPagePath = defaultPagePath;\n }\n\n let signUpPagePath: string | undefined;\n try {\n signUpPagePath = this.#options.signUpUrl\n ? new URL(this.#options.signUpUrl, window.location.origin).pathname\n : key === 'signUpUrl'\n ? defaultPagePath\n : '/sign-in';\n } catch {\n signUpPagePath = key === 'signUpUrl' ? defaultPagePath : '/sign-in';\n }\n\n const redirectTargetObj = new URL(effectiveRedirectUrl, window.location.origin);\n\n if (\n redirectTargetObj.pathname === signInPagePath ||\n redirectTargetObj.pathname === signUpPagePath\n ) {\n // If the intended redirect path is the sign-in or sign-up page itself,\n // change the redirect target to the application root ('/').\n effectiveRedirectUrl = '/';\n }\n }\n\n const paramsForBuildUrl: Parameters<typeof buildURL>[0] = {\n base,\n searchParams: new URLSearchParams(),\n };\n\n if (effectiveRedirectUrl) {\n // Check if a redirect URL was determined\n if (inBrowser()) {\n const absoluteRedirectUrl = new URL(effectiveRedirectUrl, window.location.origin).href;\n paramsForBuildUrl.searchParams?.set('redirect', absoluteRedirectUrl);\n } else {\n // If not in browser, use the effectiveRedirectUrl as is.\n // This assumes it's either absolute or a path the server can interpret.\n paramsForBuildUrl.searchParams?.set('redirect', effectiveRedirectUrl);\n }\n }\n\n const constructedUrl = buildURL(paramsForBuildUrl, {\n stringify: true,\n skipOrigin: false,\n });\n\n if (typeof constructedUrl !== 'string') {\n console.error(\n '[TernSecure] Error: buildURL did not return a string as expected. Falling back to base URL.',\n );\n if (inBrowser()) {\n try {\n return new URL(base, window.location.origin).href;\n } catch {\n return base;\n }\n }\n return base;\n }\n\n return this.constructUrlWithAuthRedirect(constructedUrl);\n };\n\n #constructAfterSignOutUrl = (): string => {\n if (!this.#options.afterSignOutUrl) {\n return '/';\n }\n return this.constructUrlWithAuthRedirect(this.#options.afterSignOutUrl);\n };\n\n public constructSignInUrl = (options?: SignInRedirectOptions): string => {\n return this.#buildUrl('signInUrl', { ...options });\n };\n\n public constructSignUpUrl = (options?: SignUpRedirectOptions): string => {\n return this.#buildUrl('signUpUrl', { ...options });\n };\n\n __internal_setCountry = (country: string | null) => {\n if (!this.__internal_country) {\n this.__internal_country = country;\n }\n };\n\n #initOptions = (options: TernSecureAuthOptions): TernSecureAuthOptions => {\n return {\n ...options,\n };\n };\n\n #emit = (): void => {\n if (this._currentUser) {\n for (const listener of this.#listeners) {\n listener({\n user: this._currentUser,\n session: this.signedInSession,\n });\n }\n }\n };\n\n #setStatus(newStatus: TernSecureAuthStatus): void {\n if (this.#status !== newStatus) {\n this.#status = newStatus;\n this.#publicEventBus.emit(ternEvents.Status, this.#status);\n\n if (newStatus === 'ready') {\n this.#publicEventBus.emit(ternEvents.Status, 'ready');\n }\n }\n }\n\n #setPersistence = () => {\n const persistenceType = this.#options.persistence || 'none';\n\n switch (persistenceType) {\n case 'browserCookie':\n return inMemoryPersistence;\n case 'session':\n return browserSessionPersistence;\n case 'local':\n return browserLocalPersistence;\n case 'none':\n default:\n return inMemoryPersistence;\n }\n };\n\n #emulatorHost = (): string | undefined => {\n if (typeof process === 'undefined') return undefined;\n return process.env.FIREBASE_AUTH_EMULATOR_HOST;\n };\n\n #configureEmulator = (): void => {\n const host = this.#emulatorHost();\n const isDev = this.#instanceType === 'development';\n const shouldUseEmulator = isDev && !!host;\n if (!shouldUseEmulator || !host) {\n return;\n }\n\n const emulatorUrl = host.startsWith('http') ? host : `http://${host}`;\n\n try {\n //(this.auth as unknown as any)._canInitEmulator = true;\n connectAuthEmulator(this.auth, emulatorUrl, { disableWarnings: true });\n console.warn(`[TernSecure] Firebase Auth Emulator connected at ${emulatorUrl}`);\n } catch (error) {\n console.error('[TernSecure] Error connecting to Firebase Auth Emulator:', error);\n }\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/instance/TernAuth.ts"],"sourcesContent":["import { handleFirebaseAuthError } from '@tern-secure/shared/errors';\nimport { createTernAuthEventBus, ternEvents } from '@tern-secure/shared/ternStatusEvent';\nimport { stripScheme } from '@tern-secure/shared/url';\nimport { handleValueOrFn } from '@tern-secure/shared/utils';\nimport type {\n CreateActiveSession,\n DomainOrProxyUrl,\n InstanceType,\n ListenerCallback,\n RedirectOptions,\n SessionResource,\n SignedInSession,\n SignInRedirectOptions,\n SignInResource,\n SignInResponse,\n SignOut,\n SignOutOptions,\n SignUpRedirectOptions,\n SignUpResource,\n TernAuthSDK,\n TernSecureAuth as TernSecureAuthInterface,\n TernSecureAuthOptions,\n TernSecureAuthStatus,\n TernSecureConfig,\n TernSecureResources,\n TernSecureUser,\n TernSecureUserData,\n UnsubscribeCallback,\n} from '@tern-secure/types';\nimport type { FirebaseApp } from 'firebase/app';\nimport { getApps, initializeApp } from 'firebase/app';\nimport type { Auth, Auth as TernAuth } from 'firebase/auth';\nimport {\n browserLocalPersistence,\n browserSessionPersistence,\n connectAuthEmulator,\n getIdToken,\n getRedirectResult,\n initializeAuth,\n inMemoryPersistence,\n onAuthStateChanged,\n onIdTokenChanged,\n} from 'firebase/auth';\nimport { getInstallations } from 'firebase/installations';\n\nimport { type ClientAuthRequest, createClientAuthRequest } from '../auth/request';\nimport { AuthCookieManager, Session, SignIn, SignUp, TernSecureBase } from '../resources/internal';\nimport { buildURL, hasRedirectLoop } from '../utils/construct';\nimport { type ApiClient, createCoreApiClient } from './c_coreApiClient';\nimport { eventBus, events } from './events';\nimport { createClientFromJwt } from './jwtClient';\n\nexport function inBrowser(): boolean {\n return typeof window !== 'undefined';\n}\n\nexport { TernAuth };\n\n/**\n * Firebase implementation of the TernSecureAuth interface\n */\nexport class TernSecureAuth implements TernSecureAuthInterface {\n public static version: string = PACKAGE_VERSION;\n public static sdkMetadata: TernAuthSDK = {\n name: PACKAGE_NAME,\n version: PACKAGE_VERSION,\n environment: process.env.NODE_ENV || 'production',\n };\n private static instance: TernSecureAuth | null = null;\n private _currentUser: TernSecureUser | null = null;\n private signedInSession: SignedInSession | null = null;\n private firebaseClientApp: FirebaseApp | undefined;\n private authStateUnsubscribe: (() => void) | null = null;\n private auth!: Auth;\n private csrfToken: string | undefined;\n public isLoading = false;\n public error: Error | null = null;\n public user: TernSecureUser | null | undefined = null;\n public __internal_country?: string | null;\n #domain: DomainOrProxyUrl['domain'];\n #apiClient: ApiClient;\n #apiUrl: string;\n #instanceType?: InstanceType;\n #status: TernSecureAuthInterface['status'] = 'loading';\n #listeners: Array<(emission: TernSecureResources) => void> = [];\n #options: TernSecureAuthOptions = {};\n #authCookieManager?: AuthCookieManager;\n #clientAuthRequest?: ClientAuthRequest;\n #publicEventBus = createTernAuthEventBus();\n\n signIn!: SignInResource;\n signUp!: SignUpResource;\n session!: SessionResource;\n\n get isReady(): boolean {\n return this.status === 'ready';\n }\n\n get status(): TernSecureAuthInterface['status'] {\n return this.#status;\n }\n\n get version(): string {\n return TernSecureAuth.version;\n }\n\n set sdkMetadata(metadata: TernAuthSDK) {\n TernSecureAuth.sdkMetadata = metadata;\n }\n\n get sdkMetadata(): TernAuthSDK {\n return TernSecureAuth.sdkMetadata;\n }\n\n get requiresVerification(): boolean {\n return this.#options.requiresVerification ?? true;\n }\n\n get apiUrl(): string {\n return this.#apiUrl;\n }\n\n get domain(): string {\n if (inBrowser()) {\n const strippedDomainString = stripScheme(\n handleValueOrFn(this.#domain, new URL(window.location.href)),\n );\n if (this.#instanceType === 'production') {\n return strippedDomainString;\n }\n return strippedDomainString;\n }\n return '';\n }\n\n get instanceType() {\n return this.#instanceType;\n }\n\n public constructor(options?: TernSecureAuthOptions) {\n this.#domain = options?.ternSecureConfig?.authDomain;\n this.#apiUrl = options?.apiUrl || '';\n this.#instanceType = (process.env.NODE_ENV as InstanceType) || 'production';\n\n this.#apiClient = createCoreApiClient({\n domain: this.#domain,\n apiUrl: options?.apiUrl,\n instanceType: this.instanceType as InstanceType,\n });\n\n this.#publicEventBus.emit(ternEvents.Status, 'loading');\n TernSecureBase.ternsecure = this;\n }\n\n public getApiClient = (): ApiClient => this.#apiClient;\n\n /**\n * Get user data for the provided ID token via backend API\n */\n public async getUserData(): Promise<TernSecureUserData | null> {\n if (!this.#clientAuthRequest) {\n throw new Error('Client auth request not initialized');\n }\n\n return this.#clientAuthRequest.getUserData();\n }\n\n public setLoading(isLoading: boolean): void {\n this.isLoading = isLoading;\n }\n\n public authCookieManager(): AuthCookieManager | undefined {\n return this.#authCookieManager;\n }\n\n public _internal_getOption<K extends keyof TernSecureAuthOptions>(\n key: K,\n ): TernSecureAuthOptions[K] {\n return this.#options[key];\n }\n\n public _internal_getAllOptions(): Readonly<TernSecureAuthOptions> {\n return Object.freeze({ ...this.#options });\n }\n\n static getorCreateInstance(options?: TernSecureAuthOptions): TernSecureAuth {\n if (!this.instance) {\n this.instance = new TernSecureAuth(options);\n }\n return this.instance;\n }\n\n static clearInstance() {\n if (TernSecureAuth.instance) {\n if (TernSecureAuth.instance.authStateUnsubscribe) {\n TernSecureAuth.instance.authStateUnsubscribe();\n TernSecureAuth.instance.authStateUnsubscribe = null;\n }\n TernSecureAuth.instance = null;\n }\n }\n\n public static initialize(options: TernSecureAuthOptions): TernSecureAuth {\n const instance = this.getorCreateInstance(options);\n instance.#initialize(options);\n return instance;\n }\n\n #initialize = (options: TernSecureAuthOptions): TernSecureAuth => {\n this.#options = this.#initOptions(options);\n\n try {\n if (!this.#options.ternSecureConfig) {\n throw new Error('TernSecureConfig is required to initialize TernSecureAuth');\n }\n\n if (!this.#options.apiUrl) {\n throw new Error('apiUrl is required to initialize TernSecureAuth');\n }\n\n this.initializeFirebaseApp(this.#options.ternSecureConfig);\n\n const isBrowserCookiePersistence = this.#options.persistence === 'browserCookie';\n\n if (!isBrowserCookiePersistence) {\n this.authStateUnsubscribe = this.initAuthStateListener();\n }\n\n this.#authCookieManager = new AuthCookieManager();\n this.csrfToken = this.#authCookieManager.getCSRFToken();\n\n this.#clientAuthRequest = createClientAuthRequest();\n\n this.signIn = new SignIn(this.auth, this.csrfToken);\n this.signUp = new SignUp(this.auth);\n\n eventBus.on(events.SessionChanged, () => {\n this.#setCreatedActiveSession(this.user || null);\n this.#emit();\n });\n\n this.#setStatus('ready');\n this.#publicEventBus.emit(ternEvents.Status, 'ready');\n\n return this;\n } catch (error) {\n this.error = error as Error;\n this.#setStatus('error');\n this.#publicEventBus.emit(ternEvents.Status, 'error');\n throw error;\n }\n };\n\n private initializeFirebaseApp(config: TernSecureConfig) {\n const appName = config.appName || '[DEFAULT]';\n this.firebaseClientApp = getApps().length === 0 ? initializeApp(config, appName) : getApps()[0];\n\n const persistence = this.#setPersistence();\n const auth = initializeAuth(this.firebaseClientApp, {\n persistence,\n });\n\n this.auth = auth;\n\n if (config.tenantId) {\n this.auth.tenantId = config.tenantId;\n }\n\n this.#configureEmulator();\n\n getInstallations(this.firebaseClientApp);\n }\n\n\n /**\n * use when cookie are not httpOnly\n */\n initClient = () => {\n const idTokenInCookie = this.#authCookieManager?.getIdTokenCookie();\n const jwtClient = createClientFromJwt(idTokenInCookie || null);\n this.user = jwtClient as TernSecureUser | null;\n this.#emit();\n };\n\n\n /**\n * @deprecated will be removed in future releases.\n */\n initClientAuthRequest = () => {\n this.#clientAuthRequest\n ?.getIdTokenFromCookie()\n .then(idTokenInCookie => {\n const { token } = idTokenInCookie;\n const jwtClient = createClientFromJwt(token || null);\n this.user = jwtClient as TernSecureUser | null;\n this.#emit();\n })\n .catch(error => {\n console.error(\n '[ternauth] Error during client auth request initialization:',\n error\n );\n this.user = null;\n this.#emit();\n });\n };\n\n public signOut: SignOut = async (options?: SignOutOptions) => {\n const redirectUrl = options?.redirectUrl || this.#constructAfterSignOutUrl();\n if (options?.onBeforeSignOut) {\n await options.onBeforeSignOut();\n }\n\n await this.auth.signOut();\n\n if (options?.onAfterSignOut) {\n await options.onAfterSignOut();\n }\n if (inBrowser()) {\n window.location.href = redirectUrl;\n }\n eventBus.emit(events.UserSignOut, null);\n eventBus.emit(events.TokenUpdate, { token: null });\n this.#emit();\n };\n\n get currentSession(): SignedInSession | null {\n return this.signedInSession;\n }\n\n private initAuthListener(): () => void {\n (async () => {\n await this.auth.authStateReady();\n const user = this.auth.currentUser as TernSecureUser | null;\n this._currentUser = user;\n this.user = user;\n await this.updateCurrentSession();\n this.#emit();\n })();\n\n // Return a no-op unsubscribe function since we're not setting up a listener\n return () => {\n // No-op: nothing to unsubscribe from\n };\n }\n\n private initAuthStateListener(): () => void {\n return onAuthStateChanged(this.auth, async (user: TernSecureUser | null) => {\n await this.auth.authStateReady();\n this._currentUser = user;\n this.user = user;\n await this.updateCurrentSession();\n\n this.#emit();\n });\n }\n\n private _onIdTokenChanged(): () => void {\n return onIdTokenChanged(this.auth, async (user: TernSecureUser | null) => {\n await this.auth.authStateReady();\n this._currentUser = user;\n this.user = user;\n await this.updateCurrentSession();\n\n this.#emit();\n });\n }\n\n private async getIdToken(): Promise<string | null> {\n await this.auth.authStateReady();\n if (!this.auth.currentUser) {\n return null;\n }\n return getIdToken(this.auth.currentUser);\n }\n\n public onAuthStateChanged(callback: (cb: any) => void): () => void {\n return onAuthStateChanged(this.auth, callback);\n }\n\n public onIdTokenChanged(callback: (cb: any) => void): () => void {\n return onIdTokenChanged(this.auth, callback);\n }\n\n private async updateCurrentSession(): Promise<void> {\n if (!this._currentUser) {\n this.signedInSession = null;\n return;\n }\n\n try {\n const res = await this._currentUser.getIdTokenResult();\n this.signedInSession = {\n status: 'active',\n token: res.token,\n claims: res.claims,\n issuedAtTime: res.issuedAtTime,\n expirationTime: res.expirationTime,\n authTime: res.authTime,\n signInProvider: res.signInProvider || 'unknown',\n signInSecondFactor: res.signInSecondFactor,\n };\n } catch (error) {\n console.error('[TernSecureAuth] Error updating session:', error);\n this.signedInSession = null;\n }\n }\n\n public async checkRedirectResult(): Promise<SignInResponse | null> {\n try {\n const result = await getRedirectResult(this.auth);\n if (result) {\n return {\n status: 'success',\n user: result.user as TernSecureUser,\n };\n }\n return null;\n } catch (error) {\n const authError = handleFirebaseAuthError(error);\n return {\n status: 'error',\n message: authError.message,\n error: authError.code,\n };\n }\n }\n\n public getRedirectResult = async (): Promise<any> => {\n throw new Error('getRedirectResult not implemented');\n };\n\n public addListener = (listener: ListenerCallback): UnsubscribeCallback => {\n this.#listeners.push(listener);\n if (this._currentUser) {\n listener({\n user: this._currentUser,\n session: this.signedInSession,\n });\n }\n\n const unsubscribe = () => {\n this.#listeners = this.#listeners.filter(l => l !== listener);\n };\n return unsubscribe;\n };\n\n public on: TernSecureAuthInterface['on'] = (...args) => {\n this.#publicEventBus.on(...args);\n };\n\n public off: TernSecureAuthInterface['off'] = (...args) => {\n this.#publicEventBus.off(...args);\n };\n\n public createActiveSession: CreateActiveSession = async ({\n session,\n redirectUrl,\n }): Promise<void> => {\n try {\n if (!session) {\n throw new Error('No session provided to createActiveSession');\n }\n const sessionResult = await session.getIdTokenResult();\n const sessionData = new Session(sessionResult);\n await sessionData.create(this.csrfToken || '');\n await this.redirectAfterSignIn();\n this.#setCreatedActiveSession(session);\n this.#emit();\n } catch (error) {\n console.error('[TernSecureAuth] Error creating active session:', error);\n }\n };\n\n public initialize(options: TernSecureAuthOptions): Promise<void> {\n this._initialize(options);\n return Promise.resolve();\n }\n\n public static create(options: TernSecureAuthOptions): TernSecureAuth {\n const instance = this.getorCreateInstance();\n instance.initialize(options);\n return instance;\n }\n\n _initialize = (options: TernSecureAuthOptions): void => {\n this.#options = this.#initOptions(options);\n try {\n if (!this.#options.ternSecureConfig) {\n throw new Error('TernSecureConfig is required to initialize TernSecureAuth');\n }\n\n this.initializeFirebaseApp(this.#options.ternSecureConfig);\n\n this.signIn = new SignIn(this.auth, this.csrfToken);\n this.signUp = new SignUp(this.auth);\n\n this.#setStatus('ready');\n } catch (error) {\n this.error = error as Error;\n this.#setStatus('error');\n throw error;\n }\n };\n\n public constructUrlWithAuthRedirect = (to: string): string => {\n const baseUrl = window.location.origin;\n const url = new URL(to, baseUrl);\n\n if (url.origin === window.location.origin) {\n return url.href;\n }\n\n return url.toString();\n };\n\n #buildUrl = (key: 'signInUrl' | 'signUpUrl', options: RedirectOptions): string => {\n if (!key || !this.isReady) {\n return '';\n }\n\n const baseUrlConfig = key === 'signInUrl' ? this.#options.signInUrl : this.#options.signUpUrl;\n const defaultPagePath = key === 'signInUrl' ? '/sign-in' : '/sign-up';\n const base = baseUrlConfig || defaultPagePath;\n\n let effectiveRedirectUrl: string | null | undefined;\n\n // Priority 1: Get redirect URL from options (signInForceRedirectUrl or signUpForceRedirectUrl)\n if (key === 'signInUrl' && 'signInForceRedirectUrl' in options) {\n effectiveRedirectUrl = options.signInForceRedirectUrl;\n } else if (key === 'signUpUrl' && 'signUpForceRedirectUrl' in options) {\n effectiveRedirectUrl = options.signUpForceRedirectUrl;\n }\n\n // Priority 2: If no force redirect from options, check 'redirect' param in current URL (only in browser)\n if (!effectiveRedirectUrl && inBrowser()) {\n const currentUrlParams = new URLSearchParams(window.location.search);\n const existingRedirectParam = currentUrlParams.get('redirect_url');\n if (existingRedirectParam) {\n effectiveRedirectUrl = existingRedirectParam;\n }\n }\n\n // Priority 3: If still no redirect URL, fallback to current page's full path (only in browser)\n // This ensures that if the call originates from a page, it attempts to redirect back there by default.\n if (!effectiveRedirectUrl && inBrowser()) {\n effectiveRedirectUrl =\n window.location.pathname + window.location.search + window.location.hash;\n }\n\n if (effectiveRedirectUrl && inBrowser()) {\n let signInPagePath: string | undefined;\n try {\n signInPagePath = this.#options.signInUrl\n ? new URL(this.#options.signInUrl, window.location.origin).pathname\n : defaultPagePath;\n } catch {\n signInPagePath = defaultPagePath;\n }\n\n let signUpPagePath: string | undefined;\n try {\n signUpPagePath = this.#options.signUpUrl\n ? new URL(this.#options.signUpUrl, window.location.origin).pathname\n : key === 'signUpUrl'\n ? defaultPagePath\n : '/sign-in';\n } catch {\n signUpPagePath = key === 'signUpUrl' ? defaultPagePath : '/sign-in';\n }\n\n const redirectTargetObj = new URL(effectiveRedirectUrl, window.location.origin);\n\n if (\n redirectTargetObj.pathname === signInPagePath ||\n redirectTargetObj.pathname === signUpPagePath\n ) {\n // If the intended redirect path is the sign-in or sign-up page itself,\n // change the redirect target to the application root ('/').\n effectiveRedirectUrl = '/';\n }\n }\n\n const paramsForBuildUrl: Parameters<typeof buildURL>[0] = {\n base,\n searchParams: new URLSearchParams(),\n };\n\n if (effectiveRedirectUrl) {\n // Check if a redirect URL was determined\n if (inBrowser()) {\n const absoluteRedirectUrl = new URL(effectiveRedirectUrl, window.location.origin).href;\n paramsForBuildUrl.searchParams?.set('redirect_url', absoluteRedirectUrl);\n } else {\n // If not in browser, use the effectiveRedirectUrl as is.\n // This assumes it's either absolute or a path the server can interpret.\n paramsForBuildUrl.searchParams?.set('redirect_url', effectiveRedirectUrl);\n }\n }\n\n const constructedUrl = buildURL(paramsForBuildUrl, {\n stringify: true,\n skipOrigin: false,\n });\n\n if (typeof constructedUrl !== 'string') {\n console.error(\n '[TernSecure] Error: buildURL did not return a string as expected. Falling back to base URL.',\n );\n if (inBrowser()) {\n try {\n return new URL(base, window.location.origin).href;\n } catch {\n return base;\n }\n }\n return base;\n }\n\n return this.constructUrlWithAuthRedirect(constructedUrl);\n };\n\n #constructAfterSignInUrl = (): string => {\n if (!inBrowser()) {\n return '/';\n }\n\n let redirectPath: string | null | undefined = undefined;\n const defaultRedirectPath = '/';\n\n // Priority 1: Check for signInForceRedirectUrl from instance options\n if (this.#options.signInForceRedirectUrl) {\n redirectPath = this.#options.signInForceRedirectUrl;\n }\n\n // Priority 2: If no force redirect, check 'redirect' param in current URL\n if (!redirectPath) {\n const urlParams = new URLSearchParams(window.location.search);\n const redirectPathFromParams = urlParams.get('redirect_url');\n if (redirectPathFromParams) {\n redirectPath = redirectPathFromParams;\n }\n }\n\n // Priority 3: Fallback to default path\n if (!redirectPath) {\n redirectPath = defaultRedirectPath;\n }\n\n const currentPath = window.location.pathname;\n\n if (hasRedirectLoop(currentPath, redirectPath)) {\n //console.warn('[TernSecure] Redirect loop detected. Redirecting to default path.');\n return defaultRedirectPath;\n }\n\n return this.constructUrlWithAuthRedirect(redirectPath);\n };\n\n #constructAfterSignOutUrl = (): string => {\n if (!this.#options.afterSignOutUrl) {\n return '/';\n }\n return this.constructUrlWithAuthRedirect(this.#options.afterSignOutUrl);\n };\n\n public redirectToSignIn = async (options?: SignInRedirectOptions): Promise<unknown> => {\n if (inBrowser()) {\n const url = this.constructSignInUrl(options);\n window.location.href = url;\n }\n return;\n };\n\n public redirectToSignUp = async (options?: SignUpRedirectOptions): Promise<unknown> => {\n if (inBrowser()) {\n const redirectUrl = this.constructSignUpUrl();\n window.location.href = redirectUrl;\n }\n return;\n };\n\n redirectAfterSignIn = async (): Promise<void> => {\n if (inBrowser()) {\n const destinationUrl = this.#constructAfterSignInUrl();\n window.location.href = destinationUrl;\n }\n };\n\n redirectAfterSignUp = (): void => {\n throw new Error('redirectAfterSignUp is not implemented yet');\n };\n\n public constructSignInUrl = (options?: SignInRedirectOptions): string => {\n return this.#buildUrl('signInUrl', { ...options });\n };\n\n public constructSignUpUrl = (options?: SignUpRedirectOptions): string => {\n return this.#buildUrl('signUpUrl', { ...options });\n };\n\n __internal_setCountry = (country: string | null) => {\n if (!this.__internal_country) {\n this.__internal_country = country;\n }\n };\n\n #initOptions = (options: TernSecureAuthOptions): TernSecureAuthOptions => {\n return {\n ...options,\n };\n };\n\n #emit = (): void => {\n for (const listener of this.#listeners) {\n listener({\n user: this.user,\n session: this.signedInSession,\n });\n }\n };\n\n #setStatus(newStatus: TernSecureAuthStatus): void {\n if (this.#status !== newStatus) {\n this.#status = newStatus;\n this.#publicEventBus.emit(ternEvents.Status, this.#status);\n\n if (newStatus === 'ready') {\n this.#publicEventBus.emit(ternEvents.Status, 'ready');\n }\n }\n }\n\n #setCreatedActiveSession = (session: TernSecureUser | null) => {\n this.user = session;\n };\n\n #setPersistence = () => {\n const persistenceType = this.#options.persistence;\n\n switch (persistenceType) {\n case 'browserCookie':\n return inMemoryPersistence;\n case 'session':\n return browserSessionPersistence;\n case 'local':\n return browserLocalPersistence;\n case 'none':\n default:\n return inMemoryPersistence;\n }\n };\n\n #emulatorHost = (): string | undefined => {\n if (typeof process === 'undefined') return undefined;\n return process.env.FIREBASE_AUTH_EMULATOR_HOST;\n };\n\n #configureEmulator = (): void => {\n const host = this.#emulatorHost();\n const isDev = this.#instanceType === 'development';\n const shouldUseEmulator = isDev && !!host;\n if (!shouldUseEmulator || !host) {\n return;\n }\n\n const emulatorUrl = host.startsWith('http') ? host : `http://${host}`;\n\n try {\n //(this.auth as unknown as any)._canInitEmulator = true;\n connectAuthEmulator(this.auth, emulatorUrl, { disableWarnings: true });\n console.warn(`[TernSecure] Firebase Auth Emulator connected at ${emulatorUrl}`);\n } catch (error) {\n console.error('[TernSecure] Error connecting to Firebase Auth Emulator:', error);\n }\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { createEventBus } from "@tern-secure/shared/eventBus";
|
|
2
2
|
const events = {
|
|
3
|
-
//UserChanged: "user:userChanged",
|
|
4
3
|
UserSignOut: "user:userSignOut",
|
|
5
4
|
SessionChanged: "session:sessionChanged",
|
|
6
|
-
TokenRefreshed: "token:tokenRefreshed"
|
|
5
|
+
TokenRefreshed: "token:tokenRefreshed",
|
|
6
|
+
TokenUpdate: "token:tokenUpdate",
|
|
7
|
+
TokenJwt: "token:tokenJwt"
|
|
7
8
|
};
|
|
8
9
|
const eventBus = createEventBus();
|
|
9
10
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/instance/events.ts"],"sourcesContent":["import { createEventBus } from
|
|
1
|
+
{"version":3,"sources":["../../../src/instance/events.ts"],"sourcesContent":["import { createEventBus } from '@tern-secure/shared/eventBus';\nimport type { IdTokenResult } from '@tern-secure/types';\n\nexport const events = {\n UserSignOut: 'user:userSignOut',\n SessionChanged: 'session:sessionChanged',\n TokenRefreshed: 'token:tokenRefreshed',\n TokenUpdate: 'token:tokenUpdate',\n TokenJwt: 'token:tokenJwt',\n} as const;\n\ntype TokenUpdatePayload = { token: IdTokenResult | null };\ntype TokenJwt = { tokenType: 'idToken' | 'sessionToken' | 'refreshToken' | 'customToken', response: string };\n\ntype InternalEvents = {\n [events.UserSignOut]: null;\n [events.SessionChanged]: null;\n [events.TokenRefreshed]: TokenUpdatePayload;\n [events.TokenUpdate]: TokenUpdatePayload;\n [events.TokenJwt]: TokenJwt;\n};\n\nexport const eventBus = createEventBus<InternalEvents>();\n"],"mappings":"AAAA,SAAS,sBAAsB;AAGxB,MAAM,SAAS;AAAA,EACpB,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,UAAU;AACZ;AAaO,MAAM,WAAW,eAA+B;","names":[]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { decode } from "../utils/jwt";
|
|
2
|
+
const createClientFromJwt = (jwtToken) => {
|
|
3
|
+
if (!jwtToken) {
|
|
4
|
+
return null;
|
|
5
|
+
}
|
|
6
|
+
const { decoded } = decode(jwtToken);
|
|
7
|
+
console.log("[TernAuth] Loaded user from JWT:", decoded);
|
|
8
|
+
return decoded;
|
|
9
|
+
};
|
|
10
|
+
const updateClient = (user, options) => {
|
|
11
|
+
try {
|
|
12
|
+
if (options.onUserUpdate) {
|
|
13
|
+
options.onUserUpdate(user);
|
|
14
|
+
}
|
|
15
|
+
if (user && options.onSessionUpdate) {
|
|
16
|
+
user.getIdTokenResult().then((tokenResult) => {
|
|
17
|
+
const session = {
|
|
18
|
+
status: "active",
|
|
19
|
+
token: tokenResult.token,
|
|
20
|
+
claims: tokenResult.claims,
|
|
21
|
+
issuedAtTime: tokenResult.issuedAtTime,
|
|
22
|
+
expirationTime: tokenResult.expirationTime,
|
|
23
|
+
authTime: tokenResult.authTime,
|
|
24
|
+
signInProvider: tokenResult.signInProvider || "unknown",
|
|
25
|
+
signInSecondFactor: tokenResult.signInSecondFactor
|
|
26
|
+
};
|
|
27
|
+
if (options.onSessionUpdate) {
|
|
28
|
+
options.onSessionUpdate(session);
|
|
29
|
+
}
|
|
30
|
+
}).catch((error) => {
|
|
31
|
+
console.error("[TernAuth] Error getting token result for session:", error);
|
|
32
|
+
if (options.onSessionUpdate) {
|
|
33
|
+
options.onSessionUpdate(null);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
} else if (options.onSessionUpdate) {
|
|
37
|
+
options.onSessionUpdate(null);
|
|
38
|
+
}
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error("[TernAuth] Error updating client:", error);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
export {
|
|
44
|
+
createClientFromJwt,
|
|
45
|
+
updateClient
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=jwtClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/instance/jwtClient.ts"],"sourcesContent":["import type { DecodedIdToken, SignedInSession, TernSecureUser } from '@tern-secure/types';\n\nimport type { AuthCookieManager } from '../auth/AuthCookieManager';\nimport { decode } from '../utils/jwt';\n\n/**\n * Utility functions for loading user from JWT cookie and updating client state\n * This addresses the issue where user is undefined when client loads on page refresh\n */\n\nexport interface ClientUpdateOptions {\n authCookieManager: AuthCookieManager;\n onUserUpdate?: (user: TernSecureUser | null) => void;\n onSessionUpdate?: (session: SignedInSession | null) => void;\n}\n\n/**\n * Creates Firebase user from stored JWT token (ID token)\n * Since the token is already a Firebase ID token, we validate it and wait for auth state\n */\nconst createClientFromJwt = (jwtToken: string | null): DecodedIdToken | null => {\n if (!jwtToken) {\n return null;\n }\n\n const { decoded } = decode(jwtToken);\n\n console.log('[TernAuth] Loaded user from JWT:', decoded);\n\n return decoded;\n};\n\n/**\n * Updates client user state and triggers callbacks\n */\nconst updateClient = (\n user: TernSecureUser | null,\n options: Pick<ClientUpdateOptions, 'onUserUpdate' | 'onSessionUpdate'>,\n): void => {\n try {\n // Update user\n if (options.onUserUpdate) {\n options.onUserUpdate(user);\n }\n\n // Update session if user exists\n if (user && options.onSessionUpdate) {\n user\n .getIdTokenResult()\n .then(tokenResult => {\n const session: SignedInSession = {\n status: 'active',\n token: tokenResult.token,\n claims: tokenResult.claims,\n issuedAtTime: tokenResult.issuedAtTime,\n expirationTime: tokenResult.expirationTime,\n authTime: tokenResult.authTime,\n signInProvider: tokenResult.signInProvider || 'unknown',\n signInSecondFactor: tokenResult.signInSecondFactor,\n };\n if (options.onSessionUpdate) {\n options.onSessionUpdate(session);\n }\n })\n .catch(error => {\n console.error('[TernAuth] Error getting token result for session:', error);\n if (options.onSessionUpdate) {\n options.onSessionUpdate(null);\n }\n });\n } else if (options.onSessionUpdate) {\n options.onSessionUpdate(null);\n }\n } catch (error) {\n console.error('[TernAuth] Error updating client:', error);\n }\n};\n\nexport { createClientFromJwt, updateClient };\n"],"mappings":"AAGA,SAAS,cAAc;AAiBvB,MAAM,sBAAsB,CAAC,aAAmD;AAC9E,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,QAAM,EAAE,QAAQ,IAAI,OAAO,QAAQ;AAEnC,UAAQ,IAAI,oCAAoC,OAAO;AAEvD,SAAO;AACT;AAKA,MAAM,eAAe,CACnB,MACA,YACS;AACT,MAAI;AAEF,QAAI,QAAQ,cAAc;AACxB,cAAQ,aAAa,IAAI;AAAA,IAC3B;AAGA,QAAI,QAAQ,QAAQ,iBAAiB;AACnC,WACG,iBAAiB,EACjB,KAAK,iBAAe;AACnB,cAAM,UAA2B;AAAA,UAC/B,QAAQ;AAAA,UACR,OAAO,YAAY;AAAA,UACnB,QAAQ,YAAY;AAAA,UACpB,cAAc,YAAY;AAAA,UAC1B,gBAAgB,YAAY;AAAA,UAC5B,UAAU,YAAY;AAAA,UACtB,gBAAgB,YAAY,kBAAkB;AAAA,UAC9C,oBAAoB,YAAY;AAAA,QAClC;AACA,YAAI,QAAQ,iBAAiB;AAC3B,kBAAQ,gBAAgB,OAAO;AAAA,QACjC;AAAA,MACF,CAAC,EACA,MAAM,WAAS;AACd,gBAAQ,MAAM,sDAAsD,KAAK;AACzE,YAAI,QAAQ,iBAAiB;AAC3B,kBAAQ,gBAAgB,IAAI;AAAA,QAC9B;AAAA,MACF,CAAC;AAAA,IACL,WAAW,QAAQ,iBAAiB;AAClC,cAAQ,gBAAgB,IAAI;AAAA,IAC9B;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,qCAAqC,KAAK;AAAA,EAC1D;AACF;","names":[]}
|
|
@@ -78,6 +78,13 @@ class TernSecureBase {
|
|
|
78
78
|
async basePost(params) {
|
|
79
79
|
return TernSecureBase.basePost(params);
|
|
80
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Instance method to make GET requests
|
|
83
|
+
* This is a convenience method that sets the HTTP method to GET
|
|
84
|
+
*/
|
|
85
|
+
async baseGet(params) {
|
|
86
|
+
return this.fetchFromCoreApi({ ...params, method: "GET" });
|
|
87
|
+
}
|
|
81
88
|
/**
|
|
82
89
|
* Protected instance method for making POST requests with specific path and body
|
|
83
90
|
* This is designed to be used by child classes like SignIn
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/resources/Base.ts"],"sourcesContent":["import { isValidBrowserOnline } from '@tern-secure/shared/browser';\nimport type { TernSecureApiErrorJSON } from '@tern-secure/types';\n\nimport type { ApiRequestInit, ApiResponse, ApiResponseJSON } from '../instance/coreApiClient';\n//import { coreApiClient} from '../instance/coreApiClient';\nimport { TernSecureAPIResponseError, TernSecureRuntimeError } from './Error';\nimport type { AuthCookieManager, TernSecureAuth } from './internal';\n\nexport type HTTPMethod =\n | 'CONNECT'\n | 'DELETE'\n | 'GET'\n | 'HEAD'\n | 'OPTIONS'\n | 'PATCH'\n | 'POST'\n | 'PUT'\n | 'TRACE';\n\nexport type PostMutateParams = {\n action?: string | undefined;\n body?: any;\n method?: HTTPMethod | undefined;\n path?: string;\n};\n\nexport abstract class TernSecureBase {\n static ternsecure: TernSecureAuth;\n\n static get apiClient() {\n return TernSecureBase.ternsecure.getApiClient();\n }\n\n static get authCookieManager(): AuthCookieManager | undefined {\n return this.ternsecure.authCookieManager();\n }\n protected get authCookieManager(): AuthCookieManager | undefined {\n return TernSecureBase.authCookieManager;\n }\n\n /**\n * Core method to fetch data from API endpoints using coreApiClient\n * This method handles the complete request lifecycle including error handling\n */\n protected static async fetchFromCoreApi<J>(\n requestInit: ApiRequestInit,\n ): Promise<ApiResponseJSON<J> | null> {\n let apiResponse: ApiResponse<J>;\n try {\n apiResponse = await TernSecureBase.apiClient.request<J>(requestInit, { timeoutMs: 10000 });\n } catch (error) {\n if (this.shouldRethrowofflineNetworkError()) {\n throw new TernSecureRuntimeError((error as Error)?.message || String(error), {\n code: 'OFFLINE_NETWORK_ERROR',\n });\n } else if (!isValidBrowserOnline()) {\n console.warn(error);\n return null;\n } else {\n throw error;\n }\n }\n\n const { payload, status, statusText, headers } = apiResponse;\n\n if (headers) {\n const country = headers.get('x-country');\n this.ternsecure.__internal_setCountry(country ? country.toLowerCase() : null);\n }\n\n if (status >= 200 && status <= 299) {\n return payload;\n }\n\n if (status >= 400) {\n const errors = payload?.errors as TernSecureApiErrorJSON[];\n const message = errors?.[0]?.message;\n\n const apiResponseOptions: ConstructorParameters<typeof TernSecureAPIResponseError>[1] = {\n data: errors,\n status,\n };\n if (status === 429 && headers) {\n const retryAfter = headers.get('retry-After');\n if (retryAfter) {\n const value = parseInt(retryAfter, 10);\n if (!isNaN(value)) {\n apiResponseOptions.retryAfter = value;\n }\n }\n }\n\n throw new TernSecureAPIResponseError(message || statusText, apiResponseOptions);\n }\n\n return null;\n }\n\n /**\n * Convenience method for making POST requests\n */\n static async basePost(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi({ ...params, method: 'POST' });\n }\n\n /**\n * Instance method to fetch data from API endpoints\n */\n protected async fetchFromCoreApi(\n requestInit: ApiRequestInit,\n ): Promise<ApiResponseJSON<any> | null> {\n return TernSecureBase.fetchFromCoreApi(requestInit);\n }\n\n /**\n * Instance method for making POST requests\n */\n protected async basePost(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return TernSecureBase.basePost(params);\n }\n\n /**\n * Protected instance method for making POST requests with specific path and body\n * This is designed to be used by child classes like SignIn\n */\n protected async _post(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return this.basePost({\n path: params.path,\n body: params.body,\n });\n }\n\n static async makeApiRequest(requestInit: ApiRequestInit): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi(requestInit);\n }\n\n protected async makeApiRequest(\n requestInit: ApiRequestInit,\n ): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi(requestInit);\n }\n\n private static shouldRethrowofflineNetworkError(): boolean {\n const experimental = TernSecureBase.ternsecure?._internal_getOption?.('experimental');\n return experimental?.rethrowOfflineNetworkErrors || false;\n }\n}\n"],"mappings":"AAAA,SAAS,4BAA4B;AAKrC,SAAS,4BAA4B,8BAA8B;
|
|
1
|
+
{"version":3,"sources":["../../../src/resources/Base.ts"],"sourcesContent":["import { isValidBrowserOnline } from '@tern-secure/shared/browser';\nimport type { TernSecureApiErrorJSON } from '@tern-secure/types';\n\nimport type { ApiRequestInit, ApiResponse, ApiResponseJSON } from '../instance/coreApiClient';\n//import { coreApiClient} from '../instance/coreApiClient';\nimport { TernSecureAPIResponseError, TernSecureRuntimeError } from './Error';\nimport type { AuthCookieManager, TernSecureAuth } from './internal';\n\nexport type HTTPMethod =\n | 'CONNECT'\n | 'DELETE'\n | 'GET'\n | 'HEAD'\n | 'OPTIONS'\n | 'PATCH'\n | 'POST'\n | 'PUT'\n | 'TRACE';\n\nexport type PostMutateParams = {\n action?: string | undefined;\n body?: any;\n method?: HTTPMethod | undefined;\n path?: string;\n search?: ConstructorParameters<typeof URLSearchParams>[0];\n};\n\nexport abstract class TernSecureBase {\n static ternsecure: TernSecureAuth;\n\n static get apiClient() {\n return TernSecureBase.ternsecure.getApiClient();\n }\n\n static get authCookieManager(): AuthCookieManager | undefined {\n return this.ternsecure.authCookieManager();\n }\n protected get authCookieManager(): AuthCookieManager | undefined {\n return TernSecureBase.authCookieManager;\n }\n\n /**\n * Core method to fetch data from API endpoints using coreApiClient\n * This method handles the complete request lifecycle including error handling\n */\n protected static async fetchFromCoreApi<J>(\n requestInit: ApiRequestInit,\n ): Promise<ApiResponseJSON<J> | null> {\n let apiResponse: ApiResponse<J>;\n try {\n apiResponse = await TernSecureBase.apiClient.request<J>(requestInit, { timeoutMs: 10000 });\n } catch (error) {\n if (this.shouldRethrowofflineNetworkError()) {\n throw new TernSecureRuntimeError((error as Error)?.message || String(error), {\n code: 'OFFLINE_NETWORK_ERROR',\n });\n } else if (!isValidBrowserOnline()) {\n console.warn(error);\n return null;\n } else {\n throw error;\n }\n }\n\n const { payload, status, statusText, headers } = apiResponse;\n\n if (headers) {\n const country = headers.get('x-country');\n this.ternsecure.__internal_setCountry(country ? country.toLowerCase() : null);\n }\n\n if (status >= 200 && status <= 299) {\n return payload;\n }\n\n if (status >= 400) {\n const errors = payload?.errors as TernSecureApiErrorJSON[];\n const message = errors?.[0]?.message;\n\n const apiResponseOptions: ConstructorParameters<typeof TernSecureAPIResponseError>[1] = {\n data: errors,\n status,\n };\n if (status === 429 && headers) {\n const retryAfter = headers.get('retry-After');\n if (retryAfter) {\n const value = parseInt(retryAfter, 10);\n if (!isNaN(value)) {\n apiResponseOptions.retryAfter = value;\n }\n }\n }\n\n throw new TernSecureAPIResponseError(message || statusText, apiResponseOptions);\n }\n\n return null;\n }\n\n /**\n * Convenience method for making POST requests\n */\n static async basePost(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi({ ...params, method: 'POST' });\n }\n\n /**\n * Instance method to fetch data from API endpoints\n */\n protected async fetchFromCoreApi(\n requestInit: ApiRequestInit,\n ): Promise<ApiResponseJSON<any> | null> {\n return TernSecureBase.fetchFromCoreApi(requestInit);\n }\n\n /**\n * Instance method for making POST requests\n */\n protected async basePost(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return TernSecureBase.basePost(params);\n }\n\n /**\n * Instance method to make GET requests\n * This is a convenience method that sets the HTTP method to GET\n */\n protected async baseGet(params: Omit<PostMutateParams, 'method'>): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi({ ...params, method: 'GET' });\n }\n\n /**\n * Protected instance method for making POST requests with specific path and body\n * This is designed to be used by child classes like SignIn\n */\n protected async _post(params: PostMutateParams): Promise<ApiResponseJSON<any> | null> {\n return this.basePost({\n path: params.path,\n body: params.body,\n });\n }\n\n static async makeApiRequest(requestInit: ApiRequestInit): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi(requestInit);\n }\n\n protected async makeApiRequest(\n requestInit: ApiRequestInit,\n ): Promise<ApiResponseJSON<any> | null> {\n return this.fetchFromCoreApi(requestInit);\n }\n\n private static shouldRethrowofflineNetworkError(): boolean {\n const experimental = TernSecureBase.ternsecure?._internal_getOption?.('experimental');\n return experimental?.rethrowOfflineNetworkErrors || false;\n }\n}\n"],"mappings":"AAAA,SAAS,4BAA4B;AAKrC,SAAS,4BAA4B,8BAA8B;AAsB5D,MAAe,eAAe;AAAA,EACnC,OAAO;AAAA,EAEP,WAAW,YAAY;AACrB,WAAO,eAAe,WAAW,aAAa;AAAA,EAChD;AAAA,EAEA,WAAW,oBAAmD;AAC5D,WAAO,KAAK,WAAW,kBAAkB;AAAA,EAC3C;AAAA,EACA,IAAc,oBAAmD;AAC/D,WAAO,eAAe;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAuB,iBACrB,aACoC;AA/CxC;AAgDI,QAAI;AACJ,QAAI;AACF,oBAAc,MAAM,eAAe,UAAU,QAAW,aAAa,EAAE,WAAW,IAAM,CAAC;AAAA,IAC3F,SAAS,OAAO;AACd,UAAI,KAAK,iCAAiC,GAAG;AAC3C,cAAM,IAAI,wBAAwB,+BAAiB,YAAW,OAAO,KAAK,GAAG;AAAA,UAC3E,MAAM;AAAA,QACR,CAAC;AAAA,MACH,WAAW,CAAC,qBAAqB,GAAG;AAClC,gBAAQ,KAAK,KAAK;AAClB,eAAO;AAAA,MACT,OAAO;AACL,cAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,EAAE,SAAS,QAAQ,YAAY,QAAQ,IAAI;AAEjD,QAAI,SAAS;AACX,YAAM,UAAU,QAAQ,IAAI,WAAW;AACvC,WAAK,WAAW,sBAAsB,UAAU,QAAQ,YAAY,IAAI,IAAI;AAAA,IAC9E;AAEA,QAAI,UAAU,OAAO,UAAU,KAAK;AAClC,aAAO;AAAA,IACT;AAEA,QAAI,UAAU,KAAK;AACjB,YAAM,SAAS,mCAAS;AACxB,YAAM,WAAU,sCAAS,OAAT,mBAAa;AAE7B,YAAM,qBAAkF;AAAA,QACtF,MAAM;AAAA,QACN;AAAA,MACF;AACA,UAAI,WAAW,OAAO,SAAS;AAC7B,cAAM,aAAa,QAAQ,IAAI,aAAa;AAC5C,YAAI,YAAY;AACd,gBAAM,QAAQ,SAAS,YAAY,EAAE;AACrC,cAAI,CAAC,MAAM,KAAK,GAAG;AACjB,+BAAmB,aAAa;AAAA,UAClC;AAAA,QACF;AAAA,MACF;AAEA,YAAM,IAAI,2BAA2B,WAAW,YAAY,kBAAkB;AAAA,IAChF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,SAAS,QAAgE;AACpF,WAAO,KAAK,iBAAiB,EAAE,GAAG,QAAQ,QAAQ,OAAO,CAAC;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,iBACd,aACsC;AACtC,WAAO,eAAe,iBAAiB,WAAW;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAgB,SAAS,QAAgE;AACvF,WAAO,eAAe,SAAS,MAAM;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAgB,QAAQ,QAAgF;AACtG,WAAO,KAAK,iBAAiB,EAAE,GAAG,QAAQ,QAAQ,MAAM,CAAC;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAgB,MAAM,QAAgE;AACpF,WAAO,KAAK,SAAS;AAAA,MACnB,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,IACf,CAAC;AAAA,EACH;AAAA,EAEA,aAAa,eAAe,aAAmE;AAC7F,WAAO,KAAK,iBAAiB,WAAW;AAAA,EAC1C;AAAA,EAEA,MAAgB,eACd,aACsC;AACtC,WAAO,KAAK,iBAAiB,WAAW;AAAA,EAC1C;AAAA,EAEA,OAAe,mCAA4C;AAvJ7D;AAwJI,UAAM,gBAAe,0BAAe,eAAf,mBAA2B,wBAA3B,4BAAiD;AACtE,YAAO,6CAAc,gCAA+B;AAAA,EACtD;AACF;","names":[]}
|