@tern-secure/backend 1.2.0-canary.v20251108045933 → 1.2.0-canary.v20251127221555

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/admin/index.d.ts +1 -0
  2. package/dist/admin/index.d.ts.map +1 -1
  3. package/dist/admin/index.js +40 -0
  4. package/dist/admin/index.js.map +1 -1
  5. package/dist/admin/index.mjs +40 -2
  6. package/dist/admin/index.mjs.map +1 -1
  7. package/dist/admin/user.d.ts +16 -0
  8. package/dist/admin/user.d.ts.map +1 -0
  9. package/dist/auth/constants.d.ts +6 -0
  10. package/dist/auth/constants.d.ts.map +1 -0
  11. package/dist/auth/credential.d.ts +27 -0
  12. package/dist/auth/credential.d.ts.map +1 -0
  13. package/dist/auth/getauth.d.ts +1 -0
  14. package/dist/auth/getauth.d.ts.map +1 -1
  15. package/dist/auth/index.js +234 -28
  16. package/dist/auth/index.js.map +1 -1
  17. package/dist/auth/index.mjs +3 -3
  18. package/dist/auth/utils.d.ts +3 -0
  19. package/dist/auth/utils.d.ts.map +1 -0
  20. package/dist/{chunk-MS6L7M3C.mjs → chunk-DJLDUW7J.mjs} +174 -12
  21. package/dist/chunk-DJLDUW7J.mjs.map +1 -0
  22. package/dist/{chunk-ASGV4MFO.mjs → chunk-GFH5CXQR.mjs} +2 -2
  23. package/dist/{chunk-DDUNOEIM.mjs → chunk-NXYWC6YO.mjs} +278 -116
  24. package/dist/chunk-NXYWC6YO.mjs.map +1 -0
  25. package/dist/{chunk-DFAJCSBJ.mjs → chunk-WIVOBOZR.mjs} +2 -1
  26. package/dist/chunk-WIVOBOZR.mjs.map +1 -0
  27. package/dist/constants.d.ts +1 -0
  28. package/dist/constants.d.ts.map +1 -1
  29. package/dist/fireRestApi/createFireApi.d.ts +4 -2
  30. package/dist/fireRestApi/createFireApi.d.ts.map +1 -1
  31. package/dist/fireRestApi/endpointUrl.d.ts +2 -1
  32. package/dist/fireRestApi/endpointUrl.d.ts.map +1 -1
  33. package/dist/fireRestApi/endpoints/AppCheckApi.d.ts +23 -0
  34. package/dist/fireRestApi/endpoints/AppCheckApi.d.ts.map +1 -0
  35. package/dist/fireRestApi/endpoints/SignInApi.d.ts +11 -0
  36. package/dist/fireRestApi/endpoints/SignInApi.d.ts.map +1 -0
  37. package/dist/fireRestApi/endpoints/TokenApi.d.ts +3 -1
  38. package/dist/fireRestApi/endpoints/TokenApi.d.ts.map +1 -1
  39. package/dist/fireRestApi/endpoints/UserData.d.ts.map +1 -1
  40. package/dist/fireRestApi/endpoints/index.d.ts +2 -0
  41. package/dist/fireRestApi/endpoints/index.d.ts.map +1 -1
  42. package/dist/fireRestApi/request.d.ts.map +1 -1
  43. package/dist/fireRestApi/resources/EmailAddress.d.ts +7 -0
  44. package/dist/fireRestApi/resources/EmailAddress.d.ts.map +1 -0
  45. package/dist/fireRestApi/resources/JSON.d.ts +4 -0
  46. package/dist/fireRestApi/resources/JSON.d.ts.map +1 -1
  47. package/dist/index.js +421 -43
  48. package/dist/index.js.map +1 -1
  49. package/dist/index.mjs +190 -19
  50. package/dist/index.mjs.map +1 -1
  51. package/dist/jwt/index.d.ts +1 -0
  52. package/dist/jwt/index.d.ts.map +1 -1
  53. package/dist/jwt/index.js +51 -19
  54. package/dist/jwt/index.js.map +1 -1
  55. package/dist/jwt/index.mjs +8 -132
  56. package/dist/jwt/index.mjs.map +1 -1
  57. package/dist/jwt/signJwt.d.ts +8 -0
  58. package/dist/jwt/signJwt.d.ts.map +1 -1
  59. package/dist/jwt/verifyJwt.d.ts.map +1 -1
  60. package/dist/tokens/authstate.d.ts.map +1 -1
  61. package/dist/tokens/c-authenticateRequestProcessor.d.ts +1 -0
  62. package/dist/tokens/c-authenticateRequestProcessor.d.ts.map +1 -1
  63. package/dist/tokens/request.d.ts.map +1 -1
  64. package/dist/tokens/types.d.ts +2 -1
  65. package/dist/tokens/types.d.ts.map +1 -1
  66. package/dist/tokens/verify.d.ts +2 -2
  67. package/dist/tokens/verify.d.ts.map +1 -1
  68. package/dist/utils/admin-init.d.ts +1 -0
  69. package/dist/utils/admin-init.d.ts.map +1 -1
  70. package/package.json +3 -3
  71. package/dist/chunk-DDUNOEIM.mjs.map +0 -1
  72. package/dist/chunk-DFAJCSBJ.mjs.map +0 -1
  73. package/dist/chunk-MS6L7M3C.mjs.map +0 -1
  74. /package/dist/{chunk-ASGV4MFO.mjs.map → chunk-GFH5CXQR.mjs.map} +0 -0
package/dist/index.mjs CHANGED
@@ -1,20 +1,20 @@
1
1
  import {
2
2
  createTernSecureRequest
3
- } from "./chunk-ASGV4MFO.mjs";
3
+ } from "./chunk-GFH5CXQR.mjs";
4
4
  import {
5
5
  getAuth,
6
6
  verifyToken
7
- } from "./chunk-MS6L7M3C.mjs";
7
+ } from "./chunk-DJLDUW7J.mjs";
8
8
  import {
9
9
  constants
10
- } from "./chunk-DFAJCSBJ.mjs";
10
+ } from "./chunk-WIVOBOZR.mjs";
11
11
  import {
12
12
  RefreshTokenErrorReason,
13
13
  TokenVerificationError,
14
14
  TokenVerificationErrorReason,
15
15
  mapJwtPayloadToDecodedIdToken,
16
16
  ternDecodeJwt
17
- } from "./chunk-DDUNOEIM.mjs";
17
+ } from "./chunk-NXYWC6YO.mjs";
18
18
 
19
19
  // src/createRedirect.ts
20
20
  var buildUrl = (_baseUrl, _targetUrl, _returnBackUrl) => {
@@ -201,6 +201,84 @@ var AbstractAPI = class {
201
201
  }
202
202
  };
203
203
 
204
+ // src/fireRestApi/endpoints/AppCheckApi.ts
205
+ function getSdkVersion() {
206
+ return "12.7.0";
207
+ }
208
+ var FIREBASE_APP_CHECK_CONFIG_HEADERS = {
209
+ "X-Firebase-Client": `fire-admin-node/${getSdkVersion()}`
210
+ };
211
+ var AppCheckApi = class extends AbstractAPI {
212
+ async exchangeCustomToken(params) {
213
+ const { projectId, appId, customToken, accessToken, limitedUse = false } = params;
214
+ if (!projectId || !appId) {
215
+ throw new Error("Project ID and App ID are required for App Check token exchange");
216
+ }
217
+ const endpoint = `https://firebaseappcheck.googleapis.com/v1beta/projects/${projectId}/apps/${appId}:exchangeCustomToken`;
218
+ const headers = {
219
+ "Content-Type": "application/json",
220
+ "Authorization": `Bearer ${accessToken}`
221
+ };
222
+ const body = {
223
+ customToken,
224
+ limitedUse
225
+ };
226
+ try {
227
+ const response = await fetch(endpoint, {
228
+ method: "POST",
229
+ headers,
230
+ body: JSON.stringify(body)
231
+ });
232
+ if (!response.ok) {
233
+ const errorText = await response.text();
234
+ throw new Error(`App Check token exchange failed: ${response.status} ${errorText}`);
235
+ }
236
+ const data = await response.json();
237
+ return {
238
+ token: data.token,
239
+ ttl: data.ttl
240
+ };
241
+ } catch (error) {
242
+ console.warn("[ternsecure - appcheck api]unexpected error:", error);
243
+ throw error;
244
+ }
245
+ }
246
+ async exchangeDebugToken(params) {
247
+ const { projectId, appId, customToken, accessToken, limitedUse = false } = params;
248
+ if (!projectId || !appId) {
249
+ throw new Error("Project ID and App ID are required for App Check token exchange");
250
+ }
251
+ const endpoint = `https://firebaseappcheck.googleapis.com/v1beta/projects/${projectId}/apps/${appId}:exchangeDebugToken`;
252
+ const headers = {
253
+ ...FIREBASE_APP_CHECK_CONFIG_HEADERS,
254
+ "Authorization": `Bearer ${accessToken}`
255
+ };
256
+ const body = {
257
+ customToken,
258
+ limitedUse
259
+ };
260
+ try {
261
+ const response = await fetch(endpoint, {
262
+ method: "POST",
263
+ headers,
264
+ body: JSON.stringify(body)
265
+ });
266
+ if (!response.ok) {
267
+ const errorText = await response.text();
268
+ throw new Error(`App Check token exchange failed: ${response.status} ${errorText}`);
269
+ }
270
+ const data = await response.json();
271
+ return {
272
+ token: data.token,
273
+ ttl: data.ttl
274
+ };
275
+ } catch (error) {
276
+ console.warn("[ternsecure - appcheck api]unexpected error:", error);
277
+ throw error;
278
+ }
279
+ }
280
+ };
281
+
204
282
  // src/fireRestApi/endpoints/EmailApi.ts
205
283
  var EmailApi = class extends AbstractAPI {
206
284
  async verifyEmailVerification(apiKey, params) {
@@ -254,6 +332,30 @@ var PasswordApi = class extends AbstractAPI {
254
332
  }
255
333
  };
256
334
 
335
+ // src/fireRestApi/endpoints/SignInApi.ts
336
+ var SignInApi = class extends AbstractAPI {
337
+ async resetPasswordEmail(apiKey, params) {
338
+ try {
339
+ this.requireApiKey(apiKey);
340
+ const { ...restParams } = params;
341
+ const response = await this.request({
342
+ endpoint: "sendOobCode",
343
+ method: "POST",
344
+ apiKey,
345
+ bodyParams: restParams
346
+ });
347
+ if (response.errors) {
348
+ const errorMessage = response.errors[0]?.message || "Failed to send reset password email";
349
+ throw new Error(errorMessage);
350
+ }
351
+ return response.data;
352
+ } catch (error) {
353
+ const contextualMessage = `Failed to send reset password email: ${error instanceof Error ? error.message : "Unknown error"}`;
354
+ throw new Error(contextualMessage);
355
+ }
356
+ }
357
+ };
358
+
257
359
  // src/fireRestApi/endpoints/SignInTokenApi.ts
258
360
  var SignInTokenApi = class extends AbstractAPI {
259
361
  async createCustomToken(apiKey, params) {
@@ -294,11 +396,14 @@ var SignUpApi = class extends AbstractAPI {
294
396
  var TokenApi = class extends AbstractAPI {
295
397
  async refreshToken(apiKey, params) {
296
398
  this.requireApiKey(apiKey);
297
- const { refresh_token, request_origin, ...restParams } = params;
399
+ const { refresh_token, request_origin, app_check_token, ...restParams } = params;
298
400
  const headers = {};
299
401
  if (request_origin) {
300
402
  headers["Referer"] = request_origin;
301
403
  }
404
+ if (app_check_token) {
405
+ headers["X-Firebase-AppCheck"] = app_check_token;
406
+ }
302
407
  const bodyParams = {
303
408
  grant_type: "refresh_token",
304
409
  refresh_token,
@@ -318,13 +423,23 @@ var TokenApi = class extends AbstractAPI {
318
423
  if (options?.referer) {
319
424
  headers["Referer"] = options.referer;
320
425
  }
321
- return this.request({
426
+ if (options?.appCheckToken) {
427
+ headers["X-Firebase-AppCheck"] = options.appCheckToken;
428
+ }
429
+ const response = await this.request({
322
430
  endpoint: "signInWithCustomToken",
323
431
  method: "POST",
324
432
  apiKey,
325
433
  bodyParams: params,
326
434
  headerParams: headers
327
435
  });
436
+ if (response.errors) {
437
+ throw new Error(response.errors[0].message);
438
+ }
439
+ if (!response.data) {
440
+ throw new Error("No data received from Firebase token exchange");
441
+ }
442
+ return response.data;
328
443
  }
329
444
  };
330
445
 
@@ -386,6 +501,9 @@ var signInWithPassword = (apiKey) => {
386
501
  var signUpEndpoint = (apiKey) => {
387
502
  return `https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${apiKey}`;
388
503
  };
504
+ var sendOobCode = (apiKey) => {
505
+ return `https://identitytoolkit.googleapis.com/v1/accounts:sendOobCode?key=${apiKey}`;
506
+ };
389
507
  var getCustomTokenEndpoint = (apiKey) => {
390
508
  if (useEmulator() && FIREBASE_AUTH_EMULATOR_HOST) {
391
509
  let protocol = "http://";
@@ -396,9 +514,6 @@ var getCustomTokenEndpoint = (apiKey) => {
396
514
  }
397
515
  return `https://identitytoolkit.googleapis.com/v1/accounts:signInWithCustomToken?key=${apiKey}`;
398
516
  };
399
- var passwordResetEndpoint = (apiKey) => {
400
- return `https://identitytoolkit.googleapis.com/v1/accounts:resetPassword?key=${apiKey}`;
401
- };
402
517
 
403
518
  // src/fireRestApi/request.ts
404
519
  var FIREBASE_ENDPOINT_MAP = {
@@ -406,8 +521,8 @@ var FIREBASE_ENDPOINT_MAP = {
406
521
  signInWithPassword,
407
522
  signUp: signUpEndpoint,
408
523
  signInWithCustomToken: getCustomTokenEndpoint,
409
- passwordReset: passwordResetEndpoint,
410
- sendOobCode: signInWithPassword,
524
+ passwordReset: sendOobCode,
525
+ sendOobCode,
411
526
  lookup: lookupEndpoint
412
527
  };
413
528
  function createRequest(options) {
@@ -456,8 +571,18 @@ function createRequest(options) {
456
571
  ...body
457
572
  });
458
573
  }
459
- const isJSONResponse = res?.headers && res.headers?.get(constants.Headers.ContentType) === constants.ContentTypes.Json;
460
- const responseBody = await (isJSONResponse ? res.json() : res.text());
574
+ const isJSONResponse = res?.headers && res.headers?.get(constants.Headers.ContentType)?.includes(constants.ContentTypes.Json);
575
+ let responseBody;
576
+ try {
577
+ const text = await res.text();
578
+ try {
579
+ responseBody = JSON.parse(text);
580
+ } catch {
581
+ responseBody = text;
582
+ }
583
+ } catch (e) {
584
+ responseBody = null;
585
+ }
461
586
  if (!res.ok) {
462
587
  return {
463
588
  data: null,
@@ -538,9 +663,11 @@ function parseError(error) {
538
663
  function createFireApi(options) {
539
664
  const request = createRequest(options);
540
665
  return {
666
+ appCheck: new AppCheckApi(request),
541
667
  email: new EmailApi(request),
542
668
  password: new PasswordApi(request),
543
- signIn: new SignInTokenApi(request),
669
+ signIn: new SignInApi(request),
670
+ signInToken: new SignInTokenApi(request),
544
671
  signUp: new SignUpApi(request),
545
672
  tokens: new TokenApi(request),
546
673
  userData: new UserData(request)
@@ -590,6 +717,7 @@ var RequestProcessorContext = class {
590
717
  this.userAgent = this.getHeader(constants.Headers.UserAgent);
591
718
  this.secFetchDest = this.getHeader(constants.Headers.SecFetchDest);
592
719
  this.accept = this.getHeader(constants.Headers.Accept);
720
+ this.appCheckToken = this.getHeader(constants.Headers.AppCheckToken);
593
721
  }
594
722
  initCookieValues() {
595
723
  const isProduction = process.env.NODE_ENV === "production";
@@ -653,14 +781,13 @@ function isRequestForRefresh(error, context, request) {
653
781
  }
654
782
  async function authenticateRequest(request, options) {
655
783
  const context = createRequestProcessor(createTernSecureRequest(request), options);
656
- const { refreshTokenInCookie } = context;
784
+ const { refreshTokenInCookie, appCheckToken } = context;
657
785
  const { refreshExpiredIdToken } = getAuth(options);
658
786
  function checkSessionTimeout(authTimeValue) {
659
787
  const defaultMaxAgeSeconds = convertToSeconds("5 days");
660
788
  const REAUTH_PERIOD_SECONDS = context.session?.maxAge ? convertToSeconds(context.session.maxAge) : defaultMaxAgeSeconds;
661
789
  const currentTime = Math.floor(Date.now() / 1e3);
662
790
  const authAge = currentTime - authTimeValue;
663
- console.log("Current time:", currentTime, "Auth age:", authAge, "Reauth period (s):", REAUTH_PERIOD_SECONDS);
664
791
  if (authTimeValue > 0 && authAge > REAUTH_PERIOD_SECONDS) {
665
792
  return signedOut(context, AuthErrorReason.AuthTimeout, "Authentication expired");
666
793
  }
@@ -677,7 +804,8 @@ async function authenticateRequest(request, options) {
677
804
  };
678
805
  }
679
806
  return await refreshExpiredIdToken(refreshTokenInCookie, {
680
- referer: context.ternUrl.origin
807
+ referer: context.ternUrl.origin,
808
+ appCheckToken
681
809
  });
682
810
  }
683
811
  async function handleRefresh() {
@@ -779,7 +907,24 @@ async function authenticateRequest(request, options) {
779
907
  if (errors) {
780
908
  throw errors[0];
781
909
  }
782
- const signedInRequestState = signedIn(context, data, void 0, context.idTokenInCookie);
910
+ const { exchangeAppCheckToken } = getAuth(options);
911
+ let appCheckTokenValue;
912
+ try {
913
+ const idToken = context.idTokenInCookie || "";
914
+ const appCheckResult = await exchangeAppCheckToken(idToken);
915
+ console.log("[authenticateRequest] App Check exchange result:", appCheckResult);
916
+ if (appCheckResult.data?.token) {
917
+ appCheckTokenValue = appCheckResult.data.token;
918
+ }
919
+ } catch (error) {
920
+ console.warn("App Check token exchange failed:", error);
921
+ }
922
+ const headers = new Headers();
923
+ headers.set(
924
+ constants.Headers.AppCheckToken,
925
+ appCheckTokenValue || ""
926
+ );
927
+ const signedInRequestState = signedIn(context, data, headers, context.idTokenInCookie);
783
928
  return signedInRequestState;
784
929
  } catch (err) {
785
930
  return handleError(err, "cookie");
@@ -793,7 +938,23 @@ async function authenticateRequest(request, options) {
793
938
  if (errors) {
794
939
  throw errors[0];
795
940
  }
796
- const signedInRequestState = signedIn(context, data, void 0, sessionTokenInHeader);
941
+ const { exchangeAppCheckToken } = getAuth(options);
942
+ let appCheckTokenValue;
943
+ try {
944
+ const token = sessionTokenInHeader || "";
945
+ const appCheckResult = await exchangeAppCheckToken(token);
946
+ if (appCheckResult.data?.token) {
947
+ appCheckTokenValue = appCheckResult.data.token;
948
+ }
949
+ } catch (error) {
950
+ console.warn("App Check token exchange failed:", error);
951
+ }
952
+ const headers = new Headers();
953
+ headers.set(
954
+ constants.Headers.AppCheckToken,
955
+ appCheckTokenValue || ""
956
+ );
957
+ const signedInRequestState = signedIn(context, data, headers, sessionTokenInHeader);
797
958
  return signedInRequestState;
798
959
  } catch (err) {
799
960
  return handleError(err, "header");
@@ -807,6 +968,16 @@ async function authenticateRequest(request, options) {
807
968
  if (isRequestForRefresh(err, context, request)) {
808
969
  const { data, error } = await handleRefresh();
809
970
  if (data) {
971
+ const { exchangeAppCheckToken } = getAuth(options);
972
+ let appCheckTokenValue;
973
+ try {
974
+ const appCheckResult = await exchangeAppCheckToken(data.token);
975
+ if (appCheckResult.data?.token) {
976
+ appCheckTokenValue = appCheckResult.data.token;
977
+ }
978
+ } catch (error2) {
979
+ console.warn("App Check token exchange failed in error handler:", error2);
980
+ }
810
981
  return signedIn(context, data.decoded, data.headers, data.token);
811
982
  }
812
983
  if (error?.cause?.reason) {