@tern-secure/backend 1.2.0-canary.v20251125170702 → 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 (62) hide show
  1. package/dist/admin/index.js +3 -0
  2. package/dist/admin/index.js.map +1 -1
  3. package/dist/admin/index.mjs +4 -2
  4. package/dist/admin/index.mjs.map +1 -1
  5. package/dist/auth/constants.d.ts +6 -0
  6. package/dist/auth/constants.d.ts.map +1 -0
  7. package/dist/auth/credential.d.ts +27 -0
  8. package/dist/auth/credential.d.ts.map +1 -0
  9. package/dist/auth/getauth.d.ts +1 -0
  10. package/dist/auth/getauth.d.ts.map +1 -1
  11. package/dist/auth/index.js +234 -28
  12. package/dist/auth/index.js.map +1 -1
  13. package/dist/auth/index.mjs +3 -3
  14. package/dist/auth/utils.d.ts +3 -0
  15. package/dist/auth/utils.d.ts.map +1 -0
  16. package/dist/{chunk-MS6L7M3C.mjs → chunk-DJLDUW7J.mjs} +174 -12
  17. package/dist/chunk-DJLDUW7J.mjs.map +1 -0
  18. package/dist/{chunk-ASGV4MFO.mjs → chunk-GFH5CXQR.mjs} +2 -2
  19. package/dist/{chunk-DDUNOEIM.mjs → chunk-NXYWC6YO.mjs} +278 -116
  20. package/dist/chunk-NXYWC6YO.mjs.map +1 -0
  21. package/dist/{chunk-DFAJCSBJ.mjs → chunk-WIVOBOZR.mjs} +2 -1
  22. package/dist/chunk-WIVOBOZR.mjs.map +1 -0
  23. package/dist/constants.d.ts +1 -0
  24. package/dist/constants.d.ts.map +1 -1
  25. package/dist/fireRestApi/createFireApi.d.ts +2 -1
  26. package/dist/fireRestApi/createFireApi.d.ts.map +1 -1
  27. package/dist/fireRestApi/endpoints/AppCheckApi.d.ts +23 -0
  28. package/dist/fireRestApi/endpoints/AppCheckApi.d.ts.map +1 -0
  29. package/dist/fireRestApi/endpoints/TokenApi.d.ts +3 -1
  30. package/dist/fireRestApi/endpoints/TokenApi.d.ts.map +1 -1
  31. package/dist/fireRestApi/endpoints/UserData.d.ts.map +1 -1
  32. package/dist/fireRestApi/endpoints/index.d.ts +1 -0
  33. package/dist/fireRestApi/endpoints/index.d.ts.map +1 -1
  34. package/dist/fireRestApi/request.d.ts.map +1 -1
  35. package/dist/index.js +390 -36
  36. package/dist/index.js.map +1 -1
  37. package/dist/index.mjs +159 -12
  38. package/dist/index.mjs.map +1 -1
  39. package/dist/jwt/index.d.ts +1 -0
  40. package/dist/jwt/index.d.ts.map +1 -1
  41. package/dist/jwt/index.js +51 -19
  42. package/dist/jwt/index.js.map +1 -1
  43. package/dist/jwt/index.mjs +8 -132
  44. package/dist/jwt/index.mjs.map +1 -1
  45. package/dist/jwt/signJwt.d.ts +8 -0
  46. package/dist/jwt/signJwt.d.ts.map +1 -1
  47. package/dist/jwt/verifyJwt.d.ts.map +1 -1
  48. package/dist/tokens/authstate.d.ts.map +1 -1
  49. package/dist/tokens/c-authenticateRequestProcessor.d.ts +1 -0
  50. package/dist/tokens/c-authenticateRequestProcessor.d.ts.map +1 -1
  51. package/dist/tokens/request.d.ts.map +1 -1
  52. package/dist/tokens/types.d.ts +2 -1
  53. package/dist/tokens/types.d.ts.map +1 -1
  54. package/dist/tokens/verify.d.ts +2 -2
  55. package/dist/tokens/verify.d.ts.map +1 -1
  56. package/dist/utils/admin-init.d.ts +1 -0
  57. package/dist/utils/admin-init.d.ts.map +1 -1
  58. package/package.json +3 -3
  59. package/dist/chunk-DDUNOEIM.mjs.map +0 -1
  60. package/dist/chunk-DFAJCSBJ.mjs.map +0 -1
  61. package/dist/chunk-MS6L7M3C.mjs.map +0 -1
  62. /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) {
@@ -318,11 +396,14 @@ var SignUpApi = class extends AbstractAPI {
318
396
  var TokenApi = class extends AbstractAPI {
319
397
  async refreshToken(apiKey, params) {
320
398
  this.requireApiKey(apiKey);
321
- const { refresh_token, request_origin, ...restParams } = params;
399
+ const { refresh_token, request_origin, app_check_token, ...restParams } = params;
322
400
  const headers = {};
323
401
  if (request_origin) {
324
402
  headers["Referer"] = request_origin;
325
403
  }
404
+ if (app_check_token) {
405
+ headers["X-Firebase-AppCheck"] = app_check_token;
406
+ }
326
407
  const bodyParams = {
327
408
  grant_type: "refresh_token",
328
409
  refresh_token,
@@ -342,13 +423,23 @@ var TokenApi = class extends AbstractAPI {
342
423
  if (options?.referer) {
343
424
  headers["Referer"] = options.referer;
344
425
  }
345
- return this.request({
426
+ if (options?.appCheckToken) {
427
+ headers["X-Firebase-AppCheck"] = options.appCheckToken;
428
+ }
429
+ const response = await this.request({
346
430
  endpoint: "signInWithCustomToken",
347
431
  method: "POST",
348
432
  apiKey,
349
433
  bodyParams: params,
350
434
  headerParams: headers
351
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;
352
443
  }
353
444
  };
354
445
 
@@ -480,8 +571,18 @@ function createRequest(options) {
480
571
  ...body
481
572
  });
482
573
  }
483
- const isJSONResponse = res?.headers && res.headers?.get(constants.Headers.ContentType) === constants.ContentTypes.Json;
484
- 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
+ }
485
586
  if (!res.ok) {
486
587
  return {
487
588
  data: null,
@@ -562,6 +663,7 @@ function parseError(error) {
562
663
  function createFireApi(options) {
563
664
  const request = createRequest(options);
564
665
  return {
666
+ appCheck: new AppCheckApi(request),
565
667
  email: new EmailApi(request),
566
668
  password: new PasswordApi(request),
567
669
  signIn: new SignInApi(request),
@@ -615,6 +717,7 @@ var RequestProcessorContext = class {
615
717
  this.userAgent = this.getHeader(constants.Headers.UserAgent);
616
718
  this.secFetchDest = this.getHeader(constants.Headers.SecFetchDest);
617
719
  this.accept = this.getHeader(constants.Headers.Accept);
720
+ this.appCheckToken = this.getHeader(constants.Headers.AppCheckToken);
618
721
  }
619
722
  initCookieValues() {
620
723
  const isProduction = process.env.NODE_ENV === "production";
@@ -678,7 +781,7 @@ function isRequestForRefresh(error, context, request) {
678
781
  }
679
782
  async function authenticateRequest(request, options) {
680
783
  const context = createRequestProcessor(createTernSecureRequest(request), options);
681
- const { refreshTokenInCookie } = context;
784
+ const { refreshTokenInCookie, appCheckToken } = context;
682
785
  const { refreshExpiredIdToken } = getAuth(options);
683
786
  function checkSessionTimeout(authTimeValue) {
684
787
  const defaultMaxAgeSeconds = convertToSeconds("5 days");
@@ -701,7 +804,8 @@ async function authenticateRequest(request, options) {
701
804
  };
702
805
  }
703
806
  return await refreshExpiredIdToken(refreshTokenInCookie, {
704
- referer: context.ternUrl.origin
807
+ referer: context.ternUrl.origin,
808
+ appCheckToken
705
809
  });
706
810
  }
707
811
  async function handleRefresh() {
@@ -803,7 +907,24 @@ async function authenticateRequest(request, options) {
803
907
  if (errors) {
804
908
  throw errors[0];
805
909
  }
806
- 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);
807
928
  return signedInRequestState;
808
929
  } catch (err) {
809
930
  return handleError(err, "cookie");
@@ -817,7 +938,23 @@ async function authenticateRequest(request, options) {
817
938
  if (errors) {
818
939
  throw errors[0];
819
940
  }
820
- 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);
821
958
  return signedInRequestState;
822
959
  } catch (err) {
823
960
  return handleError(err, "header");
@@ -831,6 +968,16 @@ async function authenticateRequest(request, options) {
831
968
  if (isRequestForRefresh(err, context, request)) {
832
969
  const { data, error } = await handleRefresh();
833
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
+ }
834
981
  return signedIn(context, data.decoded, data.headers, data.token);
835
982
  }
836
983
  if (error?.cause?.reason) {