@tern-secure/backend 1.2.0-canary.v20251127235234 → 1.2.0-canary.v20251202164451

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 (91) hide show
  1. package/dist/adapters/index.d.ts +1 -1
  2. package/dist/adapters/index.d.ts.map +1 -1
  3. package/dist/adapters/types.d.ts +42 -0
  4. package/dist/adapters/types.d.ts.map +1 -1
  5. package/dist/admin/index.d.ts +1 -1
  6. package/dist/admin/index.d.ts.map +1 -1
  7. package/dist/admin/index.js +8 -1
  8. package/dist/admin/index.js.map +1 -1
  9. package/dist/admin/index.mjs +24 -598
  10. package/dist/admin/index.mjs.map +1 -1
  11. package/dist/app-check/AppCheckApi.d.ts +14 -0
  12. package/dist/app-check/AppCheckApi.d.ts.map +1 -0
  13. package/dist/app-check/generator.d.ts +9 -0
  14. package/dist/app-check/generator.d.ts.map +1 -0
  15. package/dist/app-check/index.d.ts +18 -0
  16. package/dist/app-check/index.d.ts.map +1 -0
  17. package/dist/app-check/index.js +1135 -0
  18. package/dist/app-check/index.js.map +1 -0
  19. package/dist/app-check/index.mjs +13 -0
  20. package/dist/app-check/index.mjs.map +1 -0
  21. package/dist/app-check/serverAppCheck.d.ts +33 -0
  22. package/dist/app-check/serverAppCheck.d.ts.map +1 -0
  23. package/dist/app-check/types.d.ts +21 -0
  24. package/dist/app-check/types.d.ts.map +1 -0
  25. package/dist/app-check/verifier.d.ts +16 -0
  26. package/dist/app-check/verifier.d.ts.map +1 -0
  27. package/dist/auth/credential.d.ts +5 -5
  28. package/dist/auth/credential.d.ts.map +1 -1
  29. package/dist/auth/getauth.d.ts +2 -1
  30. package/dist/auth/getauth.d.ts.map +1 -1
  31. package/dist/auth/index.d.ts +2 -0
  32. package/dist/auth/index.d.ts.map +1 -1
  33. package/dist/auth/index.js +902 -394
  34. package/dist/auth/index.js.map +1 -1
  35. package/dist/auth/index.mjs +5 -3
  36. package/dist/chunk-34QENCWP.mjs +784 -0
  37. package/dist/chunk-34QENCWP.mjs.map +1 -0
  38. package/dist/{chunk-NXYWC6YO.mjs → chunk-TUYCJY35.mjs} +182 -6
  39. package/dist/chunk-TUYCJY35.mjs.map +1 -0
  40. package/dist/chunk-UCSJDX6Y.mjs +778 -0
  41. package/dist/chunk-UCSJDX6Y.mjs.map +1 -0
  42. package/dist/constants.d.ts +10 -1
  43. package/dist/constants.d.ts.map +1 -1
  44. package/dist/fireRestApi/endpoints/AppCheckApi.d.ts.map +1 -1
  45. package/dist/index.d.ts +4 -1
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +1275 -856
  48. package/dist/index.js.map +1 -1
  49. package/dist/index.mjs +97 -137
  50. package/dist/index.mjs.map +1 -1
  51. package/dist/jwt/crypto-signer.d.ts +21 -0
  52. package/dist/jwt/crypto-signer.d.ts.map +1 -0
  53. package/dist/jwt/index.d.ts +2 -1
  54. package/dist/jwt/index.d.ts.map +1 -1
  55. package/dist/jwt/index.js +119 -2
  56. package/dist/jwt/index.js.map +1 -1
  57. package/dist/jwt/index.mjs +7 -3
  58. package/dist/jwt/signJwt.d.ts +8 -2
  59. package/dist/jwt/signJwt.d.ts.map +1 -1
  60. package/dist/jwt/types.d.ts +6 -0
  61. package/dist/jwt/types.d.ts.map +1 -1
  62. package/dist/jwt/verifyJwt.d.ts +7 -1
  63. package/dist/jwt/verifyJwt.d.ts.map +1 -1
  64. package/dist/tokens/authstate.d.ts +2 -0
  65. package/dist/tokens/authstate.d.ts.map +1 -1
  66. package/dist/tokens/c-authenticateRequestProcessor.d.ts +2 -2
  67. package/dist/tokens/c-authenticateRequestProcessor.d.ts.map +1 -1
  68. package/dist/tokens/keys.d.ts.map +1 -1
  69. package/dist/tokens/request.d.ts.map +1 -1
  70. package/dist/tokens/types.d.ts +6 -4
  71. package/dist/tokens/types.d.ts.map +1 -1
  72. package/dist/utils/config.d.ts.map +1 -1
  73. package/dist/{auth/utils.d.ts → utils/fetcher.d.ts} +2 -1
  74. package/dist/utils/fetcher.d.ts.map +1 -0
  75. package/dist/utils/mapDecode.d.ts +2 -1
  76. package/dist/utils/mapDecode.d.ts.map +1 -1
  77. package/dist/utils/token-generator.d.ts +4 -0
  78. package/dist/utils/token-generator.d.ts.map +1 -0
  79. package/package.json +13 -3
  80. package/dist/auth/constants.d.ts +0 -6
  81. package/dist/auth/constants.d.ts.map +0 -1
  82. package/dist/auth/utils.d.ts.map +0 -1
  83. package/dist/chunk-DJLDUW7J.mjs +0 -414
  84. package/dist/chunk-DJLDUW7J.mjs.map +0 -1
  85. package/dist/chunk-GFH5CXQR.mjs +0 -71
  86. package/dist/chunk-GFH5CXQR.mjs.map +0 -1
  87. package/dist/chunk-NXYWC6YO.mjs.map +0 -1
  88. package/dist/chunk-WIVOBOZR.mjs +0 -86
  89. package/dist/chunk-WIVOBOZR.mjs.map +0 -1
  90. package/dist/utils/gemini_admin-init.d.ts +0 -10
  91. package/dist/utils/gemini_admin-init.d.ts.map +0 -1
@@ -0,0 +1,1135 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/app-check/index.ts
31
+ var app_check_exports = {};
32
+ __export(app_check_exports, {
33
+ AppCheck: () => AppCheck,
34
+ ServerAppCheckManager: () => ServerAppCheckManager,
35
+ getAppCheck: () => getAppCheck
36
+ });
37
+ module.exports = __toCommonJS(app_check_exports);
38
+
39
+ // src/jwt/customJwt.ts
40
+ var import_jose = require("jose");
41
+
42
+ // src/jwt/verifyJwt.ts
43
+ var import_jose3 = require("jose");
44
+
45
+ // src/utils/errors.ts
46
+ var TokenVerificationErrorReason = {
47
+ TokenExpired: "token-expired",
48
+ TokenInvalid: "token-invalid",
49
+ TokenInvalidAlgorithm: "token-invalid-algorithm",
50
+ TokenInvalidAuthorizedParties: "token-invalid-authorized-parties",
51
+ TokenInvalidSignature: "token-invalid-signature",
52
+ TokenNotActiveYet: "token-not-active-yet",
53
+ TokenIatInTheFuture: "token-iat-in-the-future",
54
+ TokenVerificationFailed: "token-verification-failed",
55
+ InvalidSecretKey: "secret-key-invalid",
56
+ LocalJWKMissing: "jwk-local-missing",
57
+ RemoteJWKFailedToLoad: "jwk-remote-failed-to-load",
58
+ RemoteJWKInvalid: "jwk-remote-invalid",
59
+ RemoteJWKMissing: "jwk-remote-missing",
60
+ JWKFailedToResolve: "jwk-failed-to-resolve",
61
+ JWKKidMismatch: "jwk-kid-mismatch"
62
+ };
63
+ var TokenVerificationError = class _TokenVerificationError extends Error {
64
+ reason;
65
+ tokenCarrier;
66
+ constructor({
67
+ message,
68
+ reason
69
+ }) {
70
+ super(message);
71
+ Object.setPrototypeOf(this, _TokenVerificationError.prototype);
72
+ this.reason = reason;
73
+ this.message = message;
74
+ }
75
+ getFullMessage() {
76
+ return `${[this.message].filter((m) => m).join(" ")} (reason=${this.reason}, token-carrier=${this.tokenCarrier})`;
77
+ }
78
+ };
79
+
80
+ // src/utils/mapDecode.ts
81
+ function mapJwtPayloadToDecodedAppCheckToken(payload) {
82
+ const decodedAppCheckToken = payload;
83
+ decodedAppCheckToken.app_id = decodedAppCheckToken.sub;
84
+ return decodedAppCheckToken;
85
+ }
86
+
87
+ // src/utils/rfc4648.ts
88
+ var base64url = {
89
+ parse(string, opts) {
90
+ return parse(string, base64UrlEncoding, opts);
91
+ },
92
+ stringify(data, opts) {
93
+ return stringify(data, base64UrlEncoding, opts);
94
+ }
95
+ };
96
+ var base64UrlEncoding = {
97
+ chars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
98
+ bits: 6
99
+ };
100
+ function parse(string, encoding, opts = {}) {
101
+ if (!encoding.codes) {
102
+ encoding.codes = {};
103
+ for (let i = 0; i < encoding.chars.length; ++i) {
104
+ encoding.codes[encoding.chars[i]] = i;
105
+ }
106
+ }
107
+ if (!opts.loose && string.length * encoding.bits & 7) {
108
+ throw new SyntaxError("Invalid padding");
109
+ }
110
+ let end = string.length;
111
+ while (string[end - 1] === "=") {
112
+ --end;
113
+ if (!opts.loose && !((string.length - end) * encoding.bits & 7)) {
114
+ throw new SyntaxError("Invalid padding");
115
+ }
116
+ }
117
+ const out = new (opts.out ?? Uint8Array)(end * encoding.bits / 8 | 0);
118
+ let bits = 0;
119
+ let buffer = 0;
120
+ let written = 0;
121
+ for (let i = 0; i < end; ++i) {
122
+ const value = encoding.codes[string[i]];
123
+ if (value === void 0) {
124
+ throw new SyntaxError("Invalid character " + string[i]);
125
+ }
126
+ buffer = buffer << encoding.bits | value;
127
+ bits += encoding.bits;
128
+ if (bits >= 8) {
129
+ bits -= 8;
130
+ out[written++] = 255 & buffer >> bits;
131
+ }
132
+ }
133
+ if (bits >= encoding.bits || 255 & buffer << 8 - bits) {
134
+ throw new SyntaxError("Unexpected end of data");
135
+ }
136
+ return out;
137
+ }
138
+ function stringify(data, encoding, opts = {}) {
139
+ const { pad = true } = opts;
140
+ const mask = (1 << encoding.bits) - 1;
141
+ let out = "";
142
+ let bits = 0;
143
+ let buffer = 0;
144
+ for (let i = 0; i < data.length; ++i) {
145
+ buffer = buffer << 8 | 255 & data[i];
146
+ bits += 8;
147
+ while (bits > encoding.bits) {
148
+ bits -= encoding.bits;
149
+ out += encoding.chars[mask & buffer >> bits];
150
+ }
151
+ }
152
+ if (bits) {
153
+ out += encoding.chars[mask & buffer << encoding.bits - bits];
154
+ }
155
+ if (pad) {
156
+ while (out.length * encoding.bits & 7) {
157
+ out += "=";
158
+ }
159
+ }
160
+ return out;
161
+ }
162
+
163
+ // src/jwt/cryptoKeys.ts
164
+ var import_jose2 = require("jose");
165
+
166
+ // src/jwt/algorithms.ts
167
+ var algToHash = {
168
+ RS256: "SHA-256",
169
+ RS384: "SHA-384",
170
+ RS512: "SHA-512"
171
+ };
172
+ var algs = Object.keys(algToHash);
173
+
174
+ // src/jwt/verifyContent.ts
175
+ var verifyHeaderKid = (kid) => {
176
+ if (typeof kid === "undefined") {
177
+ return;
178
+ }
179
+ if (typeof kid !== "string") {
180
+ throw new TokenVerificationError({
181
+ reason: TokenVerificationErrorReason.TokenInvalid,
182
+ message: `Invalid JWT kid ${JSON.stringify(kid)}. Expected a string.`
183
+ });
184
+ }
185
+ };
186
+ var verifySubClaim = (sub) => {
187
+ if (typeof sub !== "string") {
188
+ throw new TokenVerificationError({
189
+ reason: TokenVerificationErrorReason.TokenVerificationFailed,
190
+ message: `Subject claim (sub) is required and must be a string. Received ${JSON.stringify(sub)}.`
191
+ });
192
+ }
193
+ };
194
+ var verifyExpirationClaim = (exp, clockSkewInMs) => {
195
+ if (typeof exp !== "number") {
196
+ throw new TokenVerificationError({
197
+ reason: TokenVerificationErrorReason.TokenVerificationFailed,
198
+ message: `Invalid JWT expiry date (exp) claim ${JSON.stringify(exp)}. Expected a number.`
199
+ });
200
+ }
201
+ const currentDate = new Date(Date.now());
202
+ const expiryDate = /* @__PURE__ */ new Date(0);
203
+ expiryDate.setUTCSeconds(exp);
204
+ const expired = expiryDate.getTime() <= currentDate.getTime() - clockSkewInMs;
205
+ if (expired) {
206
+ throw new TokenVerificationError({
207
+ reason: TokenVerificationErrorReason.TokenExpired,
208
+ message: `JWT is expired. Expiry date: ${expiryDate.toUTCString()}, Current date: ${currentDate.toUTCString()}.`
209
+ });
210
+ }
211
+ };
212
+ var verifyIssuedAtClaim = (iat, clockSkewInMs) => {
213
+ if (typeof iat === "undefined") {
214
+ return;
215
+ }
216
+ if (typeof iat !== "number") {
217
+ throw new TokenVerificationError({
218
+ reason: TokenVerificationErrorReason.TokenVerificationFailed,
219
+ message: `Invalid JWT issued at date claim (iat) ${JSON.stringify(iat)}. Expected a number.`
220
+ });
221
+ }
222
+ const currentDate = new Date(Date.now());
223
+ const issuedAtDate = /* @__PURE__ */ new Date(0);
224
+ issuedAtDate.setUTCSeconds(iat);
225
+ const postIssued = issuedAtDate.getTime() > currentDate.getTime() + clockSkewInMs;
226
+ if (postIssued) {
227
+ throw new TokenVerificationError({
228
+ reason: TokenVerificationErrorReason.TokenIatInTheFuture,
229
+ message: `JWT issued at date claim (iat) is in the future. Issued at date: ${issuedAtDate.toUTCString()}; Current date: ${currentDate.toUTCString()};`
230
+ });
231
+ }
232
+ };
233
+
234
+ // src/jwt/verifyJwt.ts
235
+ var DEFAULT_CLOCK_SKEW_IN_MS = 5 * 1e3;
236
+ function ternDecodeJwt(token) {
237
+ try {
238
+ const header = (0, import_jose3.decodeProtectedHeader)(token);
239
+ const payload = (0, import_jose3.decodeJwt)(token);
240
+ const tokenParts = (token || "").toString().split(".");
241
+ if (tokenParts.length !== 3) {
242
+ return {
243
+ errors: [
244
+ new TokenVerificationError({
245
+ reason: TokenVerificationErrorReason.TokenInvalid,
246
+ message: "Invalid JWT format"
247
+ })
248
+ ]
249
+ };
250
+ }
251
+ const [rawHeader, rawPayload, rawSignature] = tokenParts;
252
+ const signature = base64url.parse(rawSignature, { loose: true });
253
+ const data = {
254
+ header,
255
+ payload,
256
+ signature,
257
+ raw: {
258
+ header: rawHeader,
259
+ payload: rawPayload,
260
+ signature: rawSignature,
261
+ text: token
262
+ }
263
+ };
264
+ return { data };
265
+ } catch (error) {
266
+ return {
267
+ errors: [
268
+ new TokenVerificationError({
269
+ reason: TokenVerificationErrorReason.TokenInvalid,
270
+ message: `${error.message || "Invalid Token or Protected Header formatting"} (Token length: ${token?.length}, First 10 chars: ${token?.substring(0, 10)}...)`
271
+ })
272
+ ]
273
+ };
274
+ }
275
+ }
276
+ async function verifyAppCheckSignature(jwt, getPublicKey2) {
277
+ const { header, raw } = jwt;
278
+ const joseAlgorithm = header.alg || "RS256";
279
+ try {
280
+ const key = await getPublicKey2();
281
+ const { payload } = await (0, import_jose3.jwtVerify)(raw.text, key);
282
+ return { data: payload };
283
+ } catch (error) {
284
+ return {
285
+ errors: [
286
+ new TokenVerificationError({
287
+ reason: TokenVerificationErrorReason.TokenInvalidSignature,
288
+ message: error.message
289
+ })
290
+ ]
291
+ };
292
+ }
293
+ }
294
+ async function verifyAppCheckJwt(token, options) {
295
+ const { key: getPublicKey2 } = options;
296
+ const clockSkew = options.clockSkewInMs || DEFAULT_CLOCK_SKEW_IN_MS;
297
+ const { data: decoded, errors } = ternDecodeJwt(token);
298
+ if (errors) {
299
+ return { errors };
300
+ }
301
+ const { header, payload } = decoded;
302
+ try {
303
+ verifyHeaderKid(header.kid);
304
+ verifySubClaim(payload.sub);
305
+ verifyExpirationClaim(payload.exp, clockSkew);
306
+ verifyIssuedAtClaim(payload.iat, clockSkew);
307
+ } catch (error) {
308
+ return { errors: [error] };
309
+ }
310
+ const { data: verifiedPayload, errors: signatureErrors } = await verifyAppCheckSignature(
311
+ decoded,
312
+ getPublicKey2
313
+ );
314
+ if (signatureErrors) {
315
+ return {
316
+ errors: [
317
+ new TokenVerificationError({
318
+ reason: TokenVerificationErrorReason.TokenInvalidSignature,
319
+ message: "Token signature verification failed."
320
+ })
321
+ ]
322
+ };
323
+ }
324
+ const decodedAppCheckToken = mapJwtPayloadToDecodedAppCheckToken(verifiedPayload);
325
+ return { data: decodedAppCheckToken };
326
+ }
327
+
328
+ // src/constants.ts
329
+ var FIREBASE_APP_CHECK_AUDIENCE = "https://firebaseappcheck.googleapis.com/google.firebase.appcheck.v1.TokenExchangeService";
330
+ var MAX_CACHE_LAST_UPDATED_AT_SECONDS = 5 * 60;
331
+ var DEFAULT_CACHE_DURATION = 3600 * 1e3;
332
+ var TOKEN_EXPIRY_THRESHOLD_MILLIS = 5 * 60 * 1e3;
333
+ var GOOGLE_TOKEN_AUDIENCE = "https://accounts.google.com/o/oauth2/token";
334
+ var GOOGLE_AUTH_TOKEN_HOST = "accounts.google.com";
335
+ var GOOGLE_AUTH_TOKEN_PATH = "/o/oauth2/token";
336
+ var ONE_HOUR_IN_SECONDS = 60 * 60;
337
+ var ONE_MINUTE_IN_SECONDS = 60;
338
+ var ONE_MINUTE_IN_MILLIS = ONE_MINUTE_IN_SECONDS * 1e3;
339
+ var ONE_DAY_IN_MILLIS = 24 * 60 * 60 * 1e3;
340
+ var Attributes = {
341
+ AuthToken: "__ternsecureAuthToken",
342
+ AuthSignature: "__ternsecureAuthSignature",
343
+ AuthStatus: "__ternsecureAuthStatus",
344
+ AuthReason: "__ternsecureAuthReason",
345
+ AuthMessage: "__ternsecureAuthMessage",
346
+ TernSecureUrl: "__ternsecureUrl"
347
+ };
348
+ var Cookies = {
349
+ Session: "__session",
350
+ CsrfToken: "__terncf",
351
+ IdToken: "TernSecure_[DEFAULT]",
352
+ Refresh: "TernSecureID_[DEFAULT]",
353
+ Custom: "__custom",
354
+ TernAut: "tern_aut",
355
+ Handshake: "__ternsecure_handshake",
356
+ DevBrowser: "__ternsecure_db_jwt",
357
+ RedirectCount: "__ternsecure_redirect_count",
358
+ HandshakeNonce: "__ternsecure_handshake_nonce"
359
+ };
360
+ var QueryParameters = {
361
+ TernSynced: "__tern_synced",
362
+ SuffixedCookies: "suffixed_cookies",
363
+ TernRedirectUrl: "__tern_redirect_url",
364
+ // use the reference to Cookies to indicate that it's the same value
365
+ DevBrowser: Cookies.DevBrowser,
366
+ Handshake: Cookies.Handshake,
367
+ HandshakeHelp: "__tern_help",
368
+ LegacyDevBrowser: "__dev_session",
369
+ HandshakeReason: "__tern_hs_reason",
370
+ HandshakeNonce: Cookies.HandshakeNonce
371
+ };
372
+ var Headers2 = {
373
+ Accept: "accept",
374
+ AppCheckToken: "x-ternsecure-appcheck",
375
+ AuthMessage: "x-ternsecure-auth-message",
376
+ Authorization: "authorization",
377
+ AuthReason: "x-ternsecure-auth-reason",
378
+ AuthSignature: "x-ternsecure-auth-signature",
379
+ AuthStatus: "x-ternsecure-auth-status",
380
+ AuthToken: "x-ternsecure-auth-token",
381
+ CacheControl: "cache-control",
382
+ TernSecureRedirectTo: "x-ternsecure-redirect-to",
383
+ TernSecureRequestData: "x-ternsecure-request-data",
384
+ TernSecureUrl: "x-ternsecure-url",
385
+ CloudFrontForwardedProto: "cloudfront-forwarded-proto",
386
+ ContentType: "content-type",
387
+ ContentSecurityPolicy: "content-security-policy",
388
+ ContentSecurityPolicyReportOnly: "content-security-policy-report-only",
389
+ EnableDebug: "x-ternsecure-debug",
390
+ ForwardedHost: "x-forwarded-host",
391
+ ForwardedPort: "x-forwarded-port",
392
+ ForwardedProto: "x-forwarded-proto",
393
+ Host: "host",
394
+ Location: "location",
395
+ Nonce: "x-nonce",
396
+ Origin: "origin",
397
+ Referrer: "referer",
398
+ SecFetchDest: "sec-fetch-dest",
399
+ UserAgent: "user-agent",
400
+ ReportingEndpoints: "reporting-endpoints"
401
+ };
402
+ var ContentTypes = {
403
+ Json: "application/json"
404
+ };
405
+ var constants = {
406
+ Attributes,
407
+ Cookies,
408
+ Headers: Headers2,
409
+ ContentTypes,
410
+ QueryParameters
411
+ };
412
+
413
+ // src/utils/config.ts
414
+ var loadAdminConfig = () => ({
415
+ projectId: process.env.FIREBASE_PROJECT_ID || "",
416
+ clientEmail: process.env.FIREBASE_CLIENT_EMAIL || "",
417
+ privateKey: process.env.FIREBASE_PRIVATE_KEY || ""
418
+ });
419
+ var validateAdminConfig = (config) => {
420
+ const requiredFields = [
421
+ "projectId",
422
+ "clientEmail",
423
+ "privateKey"
424
+ ];
425
+ const errors = [];
426
+ requiredFields.forEach((field) => {
427
+ if (!config[field]) {
428
+ errors.push(`Missing required field: FIREBASE_${String(field).toUpperCase()}`);
429
+ }
430
+ });
431
+ return {
432
+ isValid: errors.length === 0,
433
+ errors,
434
+ config
435
+ };
436
+ };
437
+ var initializeAdminConfig = () => {
438
+ const config = loadAdminConfig();
439
+ const validationResult = validateAdminConfig(config);
440
+ if (!validationResult.isValid) {
441
+ throw new Error(
442
+ `Firebase Admin configuration validation failed:
443
+ ${validationResult.errors.join("\n")}`
444
+ );
445
+ }
446
+ return config;
447
+ };
448
+
449
+ // src/jwt/guardReturn.ts
450
+ function createJwtGuard(decodedFn) {
451
+ return (...args) => {
452
+ const { data, errors } = decodedFn(...args);
453
+ if (errors) {
454
+ throw errors[0];
455
+ }
456
+ return data;
457
+ };
458
+ }
459
+
460
+ // src/jwt/jwt.ts
461
+ var import_jose4 = require("jose");
462
+
463
+ // src/jwt/signJwt.ts
464
+ var import_jose5 = require("jose");
465
+
466
+ // src/utils/fetcher.ts
467
+ async function getDetailFromResponse(response) {
468
+ const json = await response.json();
469
+ if (!json) {
470
+ return "Missing error payload";
471
+ }
472
+ let detail = typeof json.error === "string" ? json.error : json.error?.message ?? "Missing error payload";
473
+ if (json.error_description) {
474
+ detail += " (" + json.error_description + ")";
475
+ }
476
+ return detail;
477
+ }
478
+ async function fetchText(url, init) {
479
+ return (await fetchAny(url, init)).text();
480
+ }
481
+ async function fetchJson(url, init) {
482
+ return (await fetchAny(url, init)).json();
483
+ }
484
+ async function fetchAny(url, init) {
485
+ const response = await fetch(url, init);
486
+ if (!response.ok) {
487
+ throw new Error(await getDetailFromResponse(response));
488
+ }
489
+ return response;
490
+ }
491
+
492
+ // src/jwt/types.ts
493
+ var ALGORITHM_RS256 = "RS256";
494
+
495
+ // src/jwt/signJwt.ts
496
+ async function ternSignJwt(opts) {
497
+ const { payload, privateKey, keyId } = opts;
498
+ let key;
499
+ try {
500
+ key = await (0, import_jose5.importPKCS8)(privateKey, ALGORITHM_RS256);
501
+ } catch (error) {
502
+ throw new TokenVerificationError({
503
+ message: `Failed to import private key: ${error.message}`,
504
+ reason: TokenVerificationErrorReason.TokenInvalid
505
+ });
506
+ }
507
+ return new import_jose5.SignJWT(payload).setProtectedHeader({ alg: ALGORITHM_RS256, kid: keyId }).sign(key);
508
+ }
509
+ function formatBase64(value) {
510
+ return value.replace(/\//g, "_").replace(/\+/g, "-").replace(/=+$/, "");
511
+ }
512
+ function encodeSegment(segment) {
513
+ const value = JSON.stringify(segment);
514
+ return formatBase64(import_jose5.base64url.encode(value));
515
+ }
516
+ async function ternSignBlob({
517
+ payload,
518
+ serviceAccountId,
519
+ accessToken
520
+ }) {
521
+ const url = `https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${serviceAccountId}:signBlob`;
522
+ const header = {
523
+ alg: ALGORITHM_RS256,
524
+ typ: "JWT"
525
+ };
526
+ const token = `${encodeSegment(header)}.${encodeSegment(payload)}`;
527
+ const request = {
528
+ method: "POST",
529
+ headers: {
530
+ Authorization: `Bearer ${accessToken}`
531
+ },
532
+ body: JSON.stringify({ payload: import_jose5.base64url.encode(token) })
533
+ };
534
+ const response = await fetchAny(url, request);
535
+ const blob = await response.blob();
536
+ const key = await blob.text();
537
+ const { signedBlob } = JSON.parse(key);
538
+ return `${token}.${formatBase64(signedBlob)}`;
539
+ }
540
+
541
+ // src/jwt/crypto-signer.ts
542
+ var ServiceAccountSigner = class {
543
+ constructor(credential, tenantId) {
544
+ this.credential = credential;
545
+ this.tenantId = tenantId;
546
+ }
547
+ async getAccountId() {
548
+ return Promise.resolve(this.credential.clientEmail);
549
+ }
550
+ async sign(payload) {
551
+ if (this.tenantId) {
552
+ payload.tenant_id = this.tenantId;
553
+ }
554
+ return ternSignJwt({ payload, privateKey: this.credential.privateKey });
555
+ }
556
+ };
557
+ var IAMSigner = class {
558
+ algorithm = ALGORITHM_RS256;
559
+ credential;
560
+ tenantId;
561
+ serviceAccountId;
562
+ constructor(credential, tenantId, serviceAccountId) {
563
+ this.credential = credential;
564
+ this.tenantId = tenantId;
565
+ this.serviceAccountId = serviceAccountId;
566
+ }
567
+ async sign(payload) {
568
+ if (this.tenantId) {
569
+ payload.tenant_id = this.tenantId;
570
+ }
571
+ const serviceAccount = await this.getAccountId();
572
+ const accessToken = await this.credential.getAccessToken();
573
+ return ternSignBlob({
574
+ accessToken: accessToken.accessToken,
575
+ serviceAccountId: serviceAccount,
576
+ payload
577
+ });
578
+ }
579
+ async getAccountId() {
580
+ if (this.serviceAccountId) {
581
+ return this.serviceAccountId;
582
+ }
583
+ const token = await this.credential.getAccessToken();
584
+ const url = "http://metadata/computeMetadata/v1/instance/service-accounts/default/email";
585
+ const request = {
586
+ method: "GET",
587
+ headers: {
588
+ "Metadata-Flavor": "Google",
589
+ Authorization: `Bearer ${token.accessToken}`
590
+ }
591
+ };
592
+ return this.serviceAccountId = await fetchText(url, request);
593
+ }
594
+ };
595
+
596
+ // src/jwt/index.ts
597
+ var ternDecodeJwt2 = createJwtGuard(ternDecodeJwt);
598
+
599
+ // src/auth/credential.ts
600
+ var accessTokenCache = /* @__PURE__ */ new Map();
601
+ async function requestAccessToken(urlString, init) {
602
+ const json = await fetchJson(urlString, init);
603
+ if (!json.access_token || !json.expires_in) {
604
+ throw new Error("Invalid access token response");
605
+ }
606
+ return {
607
+ accessToken: json.access_token,
608
+ expirationTime: Date.now() + json.expires_in * 1e3
609
+ };
610
+ }
611
+ var ServiceAccountManager = class {
612
+ projectId;
613
+ privateKey;
614
+ clientEmail;
615
+ constructor(serviceAccount) {
616
+ this.projectId = serviceAccount.projectId;
617
+ this.privateKey = serviceAccount.privateKey;
618
+ this.clientEmail = serviceAccount.clientEmail;
619
+ }
620
+ fetchAccessToken = async (url) => {
621
+ const token = await this.createJwt();
622
+ const postData = "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=" + token;
623
+ return requestAccessToken(url, {
624
+ method: "POST",
625
+ headers: {
626
+ "Content-Type": "application/x-www-form-urlencoded",
627
+ Authorization: `Bearer ${token}`,
628
+ Accept: "application/json"
629
+ },
630
+ body: postData
631
+ });
632
+ };
633
+ fetchAndCacheAccessToken = async (url) => {
634
+ const accessToken = await this.fetchAccessToken(url);
635
+ accessTokenCache.set(this.projectId, accessToken);
636
+ return accessToken;
637
+ };
638
+ getAccessToken = async (refresh) => {
639
+ const url = `https://${GOOGLE_AUTH_TOKEN_HOST}${GOOGLE_AUTH_TOKEN_PATH}`;
640
+ if (refresh) {
641
+ return this.fetchAndCacheAccessToken(url);
642
+ }
643
+ const cachedResponse = accessTokenCache.get(this.projectId);
644
+ if (!cachedResponse || cachedResponse.expirationTime - Date.now() <= TOKEN_EXPIRY_THRESHOLD_MILLIS) {
645
+ return this.fetchAndCacheAccessToken(url);
646
+ }
647
+ return cachedResponse;
648
+ };
649
+ createJwt = async () => {
650
+ const iat = Math.floor(Date.now() / 1e3);
651
+ const payload = {
652
+ aud: GOOGLE_TOKEN_AUDIENCE,
653
+ iat,
654
+ exp: iat + ONE_HOUR_IN_SECONDS,
655
+ iss: this.clientEmail,
656
+ sub: this.clientEmail,
657
+ scope: [
658
+ "https://www.googleapis.com/auth/cloud-platform",
659
+ "https://www.googleapis.com/auth/firebase.database",
660
+ "https://www.googleapis.com/auth/firebase.messaging",
661
+ "https://www.googleapis.com/auth/identitytoolkit",
662
+ "https://www.googleapis.com/auth/userinfo.email"
663
+ ].join(" ")
664
+ };
665
+ return ternSignJwt({
666
+ payload,
667
+ privateKey: this.privateKey
668
+ });
669
+ };
670
+ };
671
+
672
+ // src/utils/token-generator.ts
673
+ function cryptoSignerFromCredential(credential, tenantId, serviceAccountId) {
674
+ if (credential instanceof ServiceAccountManager) {
675
+ return new ServiceAccountSigner(credential, tenantId);
676
+ }
677
+ return new IAMSigner(credential, tenantId, serviceAccountId);
678
+ }
679
+
680
+ // src/app-check/AppCheckApi.ts
681
+ function getSdkVersion() {
682
+ return "12.7.0";
683
+ }
684
+ var FIREBASE_APP_CHECK_CONFIG_HEADERS = {
685
+ "X-Firebase-Client": `fire-admin-node/${getSdkVersion()}`
686
+ };
687
+ var AppCheckApi = class {
688
+ constructor(credential) {
689
+ this.credential = credential;
690
+ }
691
+ async exchangeToken(params) {
692
+ const { projectId, appId, customToken, limitedUse = false } = params;
693
+ const token = await this.credential.getAccessToken(false);
694
+ if (!projectId || !appId) {
695
+ throw new Error("Project ID and App ID are required for App Check token exchange");
696
+ }
697
+ const endpoint = `https://firebaseappcheck.googleapis.com/v1/projects/${projectId}/apps/${appId}:exchangeCustomToken`;
698
+ const headers = {
699
+ "Content-Type": "application/json",
700
+ "Authorization": `Bearer ${token.accessToken}`
701
+ };
702
+ try {
703
+ const response = await fetch(endpoint, {
704
+ method: "POST",
705
+ headers,
706
+ body: JSON.stringify({ customToken, limitedUse })
707
+ });
708
+ if (!response.ok) {
709
+ const errorText = await response.text();
710
+ throw new Error(`App Check token exchange failed: ${response.status} ${errorText}`);
711
+ }
712
+ const data = await response.json();
713
+ return {
714
+ token: data.token,
715
+ ttl: data.ttl
716
+ };
717
+ } catch (error) {
718
+ console.warn("[ternsecure - appcheck api]unexpected error:", error);
719
+ throw error;
720
+ }
721
+ }
722
+ async exchangeDebugToken(params) {
723
+ const { projectId, appId, customToken, accessToken, limitedUse = false } = params;
724
+ if (!projectId || !appId) {
725
+ throw new Error("Project ID and App ID are required for App Check token exchange");
726
+ }
727
+ const endpoint = `https://firebaseappcheck.googleapis.com/v1beta/projects/${projectId}/apps/${appId}:exchangeDebugToken`;
728
+ const headers = {
729
+ ...FIREBASE_APP_CHECK_CONFIG_HEADERS,
730
+ "Authorization": `Bearer ${accessToken}`
731
+ };
732
+ const body = {
733
+ customToken,
734
+ limitedUse
735
+ };
736
+ try {
737
+ const response = await fetch(endpoint, {
738
+ method: "POST",
739
+ headers,
740
+ body: JSON.stringify(body)
741
+ });
742
+ if (!response.ok) {
743
+ const errorText = await response.text();
744
+ throw new Error(`App Check token exchange failed: ${response.status} ${errorText}`);
745
+ }
746
+ const data = await response.json();
747
+ return {
748
+ token: data.token,
749
+ ttl: data.ttl
750
+ };
751
+ } catch (error) {
752
+ console.warn("[ternsecure - appcheck api]unexpected error:", error);
753
+ throw error;
754
+ }
755
+ }
756
+ };
757
+
758
+ // src/app-check/generator.ts
759
+ function transformMillisecondsToSecondsString(milliseconds) {
760
+ let duration;
761
+ const seconds = Math.floor(milliseconds / 1e3);
762
+ const nanos = Math.floor((milliseconds - seconds * 1e3) * 1e6);
763
+ if (nanos > 0) {
764
+ let nanoString = nanos.toString();
765
+ while (nanoString.length < 9) {
766
+ nanoString = "0" + nanoString;
767
+ }
768
+ duration = `${seconds}.${nanoString}s`;
769
+ } else {
770
+ duration = `${seconds}s`;
771
+ }
772
+ return duration;
773
+ }
774
+ var AppCheckTokenGenerator = class {
775
+ signer;
776
+ constructor(signer) {
777
+ this.signer = signer;
778
+ }
779
+ async createCustomToken(appId, options) {
780
+ if (!appId) {
781
+ throw new Error(
782
+ "appId is invalid"
783
+ );
784
+ }
785
+ let customOptions = {};
786
+ if (typeof options !== "undefined") {
787
+ customOptions = this.validateTokenOptions(options);
788
+ }
789
+ const account = await this.signer.getAccountId();
790
+ const iat = Math.floor(Date.now() / 1e3);
791
+ const body = {
792
+ iss: account,
793
+ sub: account,
794
+ app_id: appId,
795
+ aud: FIREBASE_APP_CHECK_AUDIENCE,
796
+ exp: iat + ONE_MINUTE_IN_SECONDS * 5,
797
+ iat,
798
+ ...customOptions
799
+ };
800
+ return this.signer.sign(body);
801
+ }
802
+ validateTokenOptions(options) {
803
+ if (typeof options.ttlMillis !== "undefined") {
804
+ if (options.ttlMillis < ONE_MINUTE_IN_MILLIS * 30 || options.ttlMillis > ONE_DAY_IN_MILLIS * 7) {
805
+ throw new Error(
806
+ "ttlMillis must be a duration in milliseconds between 30 minutes and 7 days (inclusive)."
807
+ );
808
+ }
809
+ return { ttl: transformMillisecondsToSecondsString(options.ttlMillis) };
810
+ }
811
+ return {};
812
+ }
813
+ };
814
+
815
+ // src/app-check/serverAppCheck.ts
816
+ var import_redis = require("@upstash/redis");
817
+
818
+ // src/admin/sessionTernSecure.ts
819
+ var import_errors6 = require("@tern-secure/shared/errors");
820
+
821
+ // src/utils/admin-init.ts
822
+ var import_firebase_admin = __toESM(require("firebase-admin"));
823
+ var import_app_check2 = require("firebase-admin/app-check");
824
+ if (!import_firebase_admin.default.apps.length) {
825
+ try {
826
+ const config = initializeAdminConfig();
827
+ import_firebase_admin.default.initializeApp({
828
+ credential: import_firebase_admin.default.credential.cert({
829
+ ...config,
830
+ privateKey: config.privateKey.replace(/\\n/g, "\n")
831
+ })
832
+ });
833
+ } catch (error) {
834
+ console.error("Firebase admin initialization error", error);
835
+ }
836
+ }
837
+ var adminTernSecureAuth = import_firebase_admin.default.auth();
838
+ var adminTernSecureDb = import_firebase_admin.default.firestore();
839
+ var TernSecureTenantManager = import_firebase_admin.default.auth().tenantManager();
840
+ var appCheckAdmin = (0, import_app_check2.getAppCheck)();
841
+
842
+ // src/admin/sessionTernSecure.ts
843
+ var DEFAULT_COOKIE_CONFIG = {
844
+ DEFAULT_EXPIRES_IN_MS: 5 * 60 * 1e3,
845
+ // 5 minutes
846
+ DEFAULT_EXPIRES_IN_SECONDS: 5 * 60,
847
+ REVOKE_REFRESH_TOKENS_ON_SIGNOUT: true
848
+ };
849
+ var DEFAULT_COOKIE_OPTIONS = {
850
+ httpOnly: true,
851
+ secure: process.env.NODE_ENV === "production",
852
+ sameSite: "strict",
853
+ path: "/"
854
+ };
855
+
856
+ // src/admin/nextSessionTernSecure.ts
857
+ var import_cookie = require("@tern-secure/shared/cookie");
858
+ var import_errors7 = require("@tern-secure/shared/errors");
859
+ var import_headers = require("next/headers");
860
+ var SESSION_CONSTANTS = {
861
+ COOKIE_NAME: constants.Cookies.Session,
862
+ DEFAULT_EXPIRES_IN_MS: 60 * 60 * 24 * 5 * 1e3,
863
+ // 5 days
864
+ DEFAULT_EXPIRES_IN_SECONDS: 60 * 60 * 24 * 5,
865
+ REVOKE_REFRESH_TOKENS_ON_SIGNOUT: true
866
+ };
867
+
868
+ // src/tokens/ternSecureRequest.ts
869
+ var import_cookie2 = require("cookie");
870
+
871
+ // src/admin/user.ts
872
+ var import_errors8 = require("@tern-secure/shared/errors");
873
+
874
+ // src/app-check/serverAppCheck.ts
875
+ var ServerAppCheckManager = class _ServerAppCheckManager {
876
+ static instances = /* @__PURE__ */ new Map();
877
+ memoryCache = /* @__PURE__ */ new Map();
878
+ redisClient = null;
879
+ options;
880
+ pendingTokens = /* @__PURE__ */ new Map();
881
+ constructor(options) {
882
+ const defaultOptions = {
883
+ strategy: "memory",
884
+ ttlMillis: 36e5,
885
+ // 1 hour
886
+ refreshBufferMillis: 3e5,
887
+ // 5 minutes
888
+ keyPrefix: "appcheck:token:",
889
+ skipInMemoryFirst: false
890
+ };
891
+ this.options = { ...defaultOptions, ...options };
892
+ if (this.options.strategy === "redis" && this.options.redis) {
893
+ void this.initializeRedis(this.options.redis);
894
+ }
895
+ }
896
+ initializeRedis = (config) => {
897
+ if (!config) {
898
+ throw new Error('[AppCheck] Redis configuration is required when strategy is "redis"');
899
+ }
900
+ try {
901
+ this.redisClient = new import_redis.Redis({
902
+ url: config.url,
903
+ token: config.token
904
+ });
905
+ console.info("[AppCheck] Redis client initialized for token caching");
906
+ } catch (error) {
907
+ console.error("[AppCheck] Failed to initialize Redis client:", error);
908
+ throw new Error('[AppCheck] Redis initialization failed. Install "@upstash/redis" package.');
909
+ }
910
+ };
911
+ static getInstance(options) {
912
+ const key = options?.strategy || "memory";
913
+ if (!_ServerAppCheckManager.instances.has(key)) {
914
+ _ServerAppCheckManager.instances.set(key, new _ServerAppCheckManager(options));
915
+ }
916
+ const instance = _ServerAppCheckManager.instances.get(key);
917
+ if (!instance) {
918
+ throw new Error("[AppCheck] Failed to get instance");
919
+ }
920
+ return instance;
921
+ }
922
+ buildCacheKey(appId) {
923
+ return `${this.options.keyPrefix}${appId}`;
924
+ }
925
+ getCachedToken = async (appId) => {
926
+ if (this.options.strategy === "memory") {
927
+ return this.memoryCache.get(appId) || null;
928
+ }
929
+ if (this.options.strategy === "redis") {
930
+ if (!this.options.skipInMemoryFirst) {
931
+ const memCached = this.memoryCache.get(appId);
932
+ if (memCached) {
933
+ return memCached;
934
+ }
935
+ }
936
+ if (this.redisClient) {
937
+ try {
938
+ const key = this.buildCacheKey(appId);
939
+ const cached = await this.redisClient.get(key);
940
+ if (cached) {
941
+ const parsed = typeof cached === "string" ? JSON.parse(cached) : cached;
942
+ if (!this.options.skipInMemoryFirst) {
943
+ this.memoryCache.set(appId, parsed);
944
+ }
945
+ return parsed;
946
+ }
947
+ } catch (error) {
948
+ console.error("[AppCheck] Redis get error:", error);
949
+ }
950
+ }
951
+ }
952
+ return null;
953
+ };
954
+ setCachedToken = async (appId, token, expiresAt) => {
955
+ const cachedToken = { token, expiresAt };
956
+ this.memoryCache.set(appId, cachedToken);
957
+ if (this.options.strategy === "memory") {
958
+ return;
959
+ }
960
+ if (this.options.strategy === "redis" && this.redisClient) {
961
+ try {
962
+ const key = this.buildCacheKey(appId);
963
+ const ttl = expiresAt - Date.now();
964
+ await this.redisClient.set(key, JSON.stringify(cachedToken), {
965
+ px: ttl
966
+ // Expiry in milliseconds (lowercase for Upstash)
967
+ });
968
+ } catch (error) {
969
+ console.error("[AppCheck] Redis set error:", error);
970
+ }
971
+ }
972
+ };
973
+ getOrGenerateToken = async (appId) => {
974
+ const cached = await this.getCachedToken(appId);
975
+ const now = Date.now();
976
+ if (cached && cached.expiresAt > now + this.options.refreshBufferMillis) {
977
+ return cached.token;
978
+ }
979
+ const pending = this.pendingTokens.get(appId);
980
+ if (pending) {
981
+ return pending;
982
+ }
983
+ const tokenPromise = this.generateAndCacheToken(appId);
984
+ this.pendingTokens.set(appId, tokenPromise);
985
+ try {
986
+ const token = await tokenPromise;
987
+ return token;
988
+ } finally {
989
+ this.pendingTokens.delete(appId);
990
+ }
991
+ };
992
+ /**
993
+ * Generate and cache a new token
994
+ */
995
+ generateAndCacheToken = async (appId) => {
996
+ try {
997
+ const now = Date.now();
998
+ const appCheckToken = await appCheckAdmin.createToken(appId, {
999
+ ttlMillis: this.options.ttlMillis
1000
+ });
1001
+ const expiresAt = now + this.options.ttlMillis;
1002
+ await this.setCachedToken(appId, appCheckToken.token, expiresAt);
1003
+ return appCheckToken.token;
1004
+ } catch (error) {
1005
+ console.error("[AppCheck] Failed to generate token:", error);
1006
+ return null;
1007
+ }
1008
+ };
1009
+ clearCache = async (appId) => {
1010
+ if (appId) {
1011
+ this.memoryCache.delete(appId);
1012
+ } else {
1013
+ this.memoryCache.clear();
1014
+ }
1015
+ if (this.options.strategy === "redis" && this.redisClient) {
1016
+ try {
1017
+ if (appId) {
1018
+ const key = this.buildCacheKey(appId);
1019
+ await this.redisClient.del(key);
1020
+ }
1021
+ } catch (error) {
1022
+ console.error("[AppCheck] Redis delete error:", error);
1023
+ }
1024
+ }
1025
+ };
1026
+ getCacheStats() {
1027
+ const now = Date.now();
1028
+ const entries = Array.from(this.memoryCache.entries()).map(([appId, cached]) => ({
1029
+ appId,
1030
+ expiresIn: Math.max(0, cached.expiresAt - now)
1031
+ }));
1032
+ return {
1033
+ strategy: this.options.strategy,
1034
+ memorySize: this.memoryCache.size,
1035
+ entries
1036
+ };
1037
+ }
1038
+ /**
1039
+ * Close Redis connection
1040
+ */
1041
+ disconnect() {
1042
+ if (this.redisClient) {
1043
+ this.redisClient = null;
1044
+ }
1045
+ }
1046
+ };
1047
+
1048
+ // src/app-check/verifier.ts
1049
+ var import_jose6 = require("jose");
1050
+ var getPublicKey = async (header, keyURL) => {
1051
+ const jswksUrl = new URL(keyURL);
1052
+ const getKey = (0, import_jose6.createRemoteJWKSet)(jswksUrl);
1053
+ return getKey(header);
1054
+ };
1055
+ var verifyAppCheckToken = async (token, options) => {
1056
+ const { data: decodedResult, errors } = ternDecodeJwt(token);
1057
+ if (errors) {
1058
+ throw errors[0];
1059
+ }
1060
+ const { header } = decodedResult;
1061
+ const { kid } = header;
1062
+ if (!kid) {
1063
+ return {
1064
+ errors: [
1065
+ new TokenVerificationError({
1066
+ reason: TokenVerificationErrorReason.TokenInvalid,
1067
+ message: 'JWT "kid" header is missing.'
1068
+ })
1069
+ ]
1070
+ };
1071
+ }
1072
+ try {
1073
+ const getPublicKeyForToken = () => getPublicKey(header, options.keyURL || "");
1074
+ return await verifyAppCheckJwt(token, { ...options, key: getPublicKeyForToken });
1075
+ } catch (error) {
1076
+ if (error instanceof TokenVerificationError) {
1077
+ return { errors: [error] };
1078
+ }
1079
+ return {
1080
+ errors: [error]
1081
+ };
1082
+ }
1083
+ };
1084
+ var AppcheckTokenVerifier = class {
1085
+ constructor(credential) {
1086
+ this.credential = credential;
1087
+ }
1088
+ verifyToken = async (token, projectId, options) => {
1089
+ const { data, errors } = await verifyAppCheckToken(token, options);
1090
+ if (errors) {
1091
+ throw errors[0];
1092
+ }
1093
+ return data;
1094
+ };
1095
+ };
1096
+
1097
+ // src/app-check/index.ts
1098
+ var JWKS_URL = "https://firebaseappcheck.googleapis.com/v1/jwks";
1099
+ var AppCheck = class {
1100
+ client;
1101
+ tokenGenerator;
1102
+ appCheckTokenVerifier;
1103
+ limitedUse;
1104
+ constructor(credential, tenantId, limitedUse) {
1105
+ this.client = new AppCheckApi(credential);
1106
+ this.tokenGenerator = new AppCheckTokenGenerator(
1107
+ cryptoSignerFromCredential(credential, tenantId)
1108
+ );
1109
+ this.appCheckTokenVerifier = new AppcheckTokenVerifier(credential);
1110
+ this.limitedUse = limitedUse;
1111
+ }
1112
+ createToken = (projectId, appId, options) => {
1113
+ return this.tokenGenerator.createCustomToken(appId, options).then((customToken) => {
1114
+ return this.client.exchangeToken({ customToken, projectId, appId });
1115
+ });
1116
+ };
1117
+ verifyToken = async (appCheckToken, projectId, options) => {
1118
+ return this.appCheckTokenVerifier.verifyToken(appCheckToken, projectId, { keyURL: JWKS_URL, ...options }).then((decodedToken) => {
1119
+ return {
1120
+ appId: decodedToken.app_id,
1121
+ token: decodedToken
1122
+ };
1123
+ });
1124
+ };
1125
+ };
1126
+ function getAppCheck(serviceAccount, tenantId, limitedUse) {
1127
+ return new AppCheck(new ServiceAccountManager(serviceAccount), tenantId, limitedUse);
1128
+ }
1129
+ // Annotate the CommonJS export names for ESM import in node:
1130
+ 0 && (module.exports = {
1131
+ AppCheck,
1132
+ ServerAppCheckManager,
1133
+ getAppCheck
1134
+ });
1135
+ //# sourceMappingURL=index.js.map