@firebase/app-check 0.11.3 → 0.11.4-eap-crashlytics.558ee841d

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.
@@ -17,6 +17,7 @@
17
17
  import { ErrorFactory } from '@firebase/util';
18
18
  export declare const enum AppCheckError {
19
19
  ALREADY_INITIALIZED = "already-initialized",
20
+ ALREADY_INTERNALLY_INITIALIZED = "already-internally-initialized",
20
21
  USE_BEFORE_ACTIVATION = "use-before-activation",
21
22
  FETCH_NETWORK_ERROR = "fetch-network-error",
22
23
  FETCH_PARSE_ERROR = "fetch-parse-error",
@@ -25,6 +26,7 @@ export declare const enum AppCheckError {
25
26
  STORAGE_GET = "storage-get",
26
27
  STORAGE_WRITE = "storage-set",
27
28
  RECAPTCHA_ERROR = "recaptcha-error",
29
+ NO_PROVIDER = "no-provider",
28
30
  INITIAL_THROTTLE = "initial-throttle",
29
31
  THROTTLED = "throttled"
30
32
  }
@@ -32,6 +34,9 @@ interface ErrorParams {
32
34
  [AppCheckError.ALREADY_INITIALIZED]: {
33
35
  appName: string;
34
36
  };
37
+ [AppCheckError.ALREADY_INTERNALLY_INITIALIZED]: {
38
+ initializerName: string;
39
+ };
35
40
  [AppCheckError.USE_BEFORE_ACTIVATION]: {
36
41
  appName: string;
37
42
  };
@@ -41,7 +41,7 @@ export declare class ReCaptchaV3Provider implements AppCheckProvider {
41
41
  * Returns an App Check token.
42
42
  * @internal
43
43
  */
44
- getToken(): Promise<AppCheckTokenInternal>;
44
+ getToken(isLimitedUse?: boolean): Promise<AppCheckTokenInternal>;
45
45
  /**
46
46
  * @internal
47
47
  */
@@ -75,7 +75,7 @@ export declare class ReCaptchaEnterpriseProvider implements AppCheckProvider {
75
75
  * Returns an App Check token.
76
76
  * @internal
77
77
  */
78
- getToken(): Promise<AppCheckTokenInternal>;
78
+ getToken(isLimitedUse?: boolean): Promise<AppCheckTokenInternal>;
79
79
  /**
80
80
  * @internal
81
81
  */
@@ -51,7 +51,7 @@ export interface AppCheckOptions {
51
51
  /**
52
52
  * A reCAPTCHA V3 provider, reCAPTCHA Enterprise provider, or custom provider.
53
53
  */
54
- provider: CustomProvider | ReCaptchaV3Provider | ReCaptchaEnterpriseProvider;
54
+ provider?: CustomProvider | ReCaptchaV3Provider | ReCaptchaEnterpriseProvider;
55
55
  /**
56
56
  * If set to true, enables automatic background refresh of App Check token.
57
57
  */
@@ -29,6 +29,7 @@ export interface AppCheckState {
29
29
  tokenRefresher?: Refresher;
30
30
  reCAPTCHAState?: ReCAPTCHAState;
31
31
  isTokenAutoRefreshEnabled?: boolean;
32
+ internallyInitializedBy?: string;
32
33
  }
33
34
  export interface ReCAPTCHAState {
34
35
  initialized: Deferred<GreCAPTCHA>;
@@ -44,7 +44,7 @@ export interface AppCheckProvider {
44
44
  * Returns an App Check token.
45
45
  * @internal
46
46
  */
47
- getToken: () => Promise<AppCheckTokenInternal>;
47
+ getToken: (isLimitedUse?: boolean) => Promise<AppCheckTokenInternal>;
48
48
  /**
49
49
  * @internal
50
50
  */
package/dist/index.cjs.js CHANGED
@@ -226,6 +226,9 @@ const ERRORS = {
226
226
  'different options. To avoid this error, call initializeAppCheck() with the ' +
227
227
  'same options as when it was originally called. This will return the ' +
228
228
  'already initialized instance.',
229
+ ["already-internally-initialized" /* AppCheckError.ALREADY_INTERNALLY_INITIALIZED */]: 'App Check has already been automatically initialized by {$initializerName} ' +
230
+ 'with default options. If you want to initialize App Check with custom options, ' +
231
+ 'call initializeAppCheck() with those options before initializing {$initializerName}.',
229
232
  ["use-before-activation" /* AppCheckError.USE_BEFORE_ACTIVATION */]: 'App Check is being used before initializeAppCheck() is called for FirebaseApp {$appName}. ' +
230
233
  'Call initializeAppCheck() before instantiating other Firebase services.',
231
234
  ["fetch-network-error" /* AppCheckError.FETCH_NETWORK_ERROR */]: 'Fetch failed to connect to a network. Check Internet connection. ' +
@@ -237,6 +240,8 @@ const ERRORS = {
237
240
  ["storage-get" /* AppCheckError.STORAGE_GET */]: 'Error thrown when reading from storage. Original error: {$originalErrorMessage}.',
238
241
  ["storage-set" /* AppCheckError.STORAGE_WRITE */]: 'Error thrown when writing to storage. Original error: {$originalErrorMessage}.',
239
242
  ["recaptcha-error" /* AppCheckError.RECAPTCHA_ERROR */]: 'ReCAPTCHA error.',
243
+ ["no-provider" /* AppCheckError.NO_PROVIDER */]: 'No attestation provider was passed to initializeAppCheck() and ' +
244
+ 'no ReCAPTCHA Enterprise site key was found in the Firebase config.',
240
245
  ["initial-throttle" /* AppCheckError.INITIAL_THROTTLE */]: `{$httpStatus} error. Attempts allowed again after {$time}`,
241
246
  ["throttled" /* AppCheckError.THROTTLED */]: `Requests throttled due to previous {$httpStatus} error. Attempts allowed again after {$time}`
242
247
  };
@@ -854,12 +859,14 @@ async function getLimitedUseToken$1(appCheck) {
854
859
  const { provider } = getStateReference(app);
855
860
  if (isDebugMode()) {
856
861
  const debugToken = await getDebugToken();
857
- const { token } = await exchangeToken(getExchangeDebugTokenRequest(app, debugToken), appCheck.heartbeatServiceProvider);
862
+ const request = getExchangeDebugTokenRequest(app, debugToken);
863
+ request.body['limited_use'] = true;
864
+ const { token } = await exchangeToken(request, appCheck.heartbeatServiceProvider);
858
865
  return { token };
859
866
  }
860
867
  else {
861
868
  // provider is definitely valid since we ensure AppCheck was activated
862
- const { token } = await provider.getToken();
869
+ const { token } = await provider.getToken(true /* isLimitedUse */);
863
870
  return { token };
864
871
  }
865
872
  }
@@ -1055,7 +1062,7 @@ function internalFactory(appCheck) {
1055
1062
  }
1056
1063
 
1057
1064
  const name = "@firebase/app-check";
1058
- const version = "0.11.3";
1065
+ const version = "0.11.4-eap-crashlytics.558ee841d";
1059
1066
 
1060
1067
  /**
1061
1068
  * @license
@@ -1189,7 +1196,8 @@ function loadReCAPTCHAV3Script(onload) {
1189
1196
  }
1190
1197
  function loadReCAPTCHAEnterpriseScript(onload) {
1191
1198
  const script = document.createElement('script');
1192
- script.src = RECAPTCHA_ENTERPRISE_URL;
1199
+ // This param is required when we plan to render a widget explicitly.
1200
+ script.src = RECAPTCHA_ENTERPRISE_URL + '?render=explicit';
1193
1201
  script.onload = onload;
1194
1202
  document.head.appendChild(script);
1195
1203
  }
@@ -1233,7 +1241,7 @@ class ReCaptchaV3Provider {
1233
1241
  * Returns an App Check token.
1234
1242
  * @internal
1235
1243
  */
1236
- async getToken() {
1244
+ async getToken(isLimitedUse = false) {
1237
1245
  throwIfThrottled(this._throttleData);
1238
1246
  // Top-level `getToken()` has already checked that App Check is initialized
1239
1247
  // and therefore this._app and this._heartbeatServiceProvider are available.
@@ -1247,7 +1255,11 @@ class ReCaptchaV3Provider {
1247
1255
  }
1248
1256
  let result;
1249
1257
  try {
1250
- result = await exchangeToken(getExchangeRecaptchaV3TokenRequest(this._app, attestedClaimsToken), this._heartbeatServiceProvider);
1258
+ const request = getExchangeRecaptchaV3TokenRequest(this._app, attestedClaimsToken);
1259
+ if (isLimitedUse) {
1260
+ request.body['limited_use'] = true;
1261
+ }
1262
+ result = await exchangeToken(request, this._heartbeatServiceProvider);
1251
1263
  }
1252
1264
  catch (e) {
1253
1265
  if (e.code?.includes("fetch-status-error" /* AppCheckError.FETCH_STATUS_ERROR */)) {
@@ -1310,7 +1322,7 @@ class ReCaptchaEnterpriseProvider {
1310
1322
  * Returns an App Check token.
1311
1323
  * @internal
1312
1324
  */
1313
- async getToken() {
1325
+ async getToken(isLimitedUse = false) {
1314
1326
  throwIfThrottled(this._throttleData);
1315
1327
  // Top-level `getToken()` has already checked that App Check is initialized
1316
1328
  // and therefore this._app and this._heartbeatServiceProvider are available.
@@ -1324,7 +1336,11 @@ class ReCaptchaEnterpriseProvider {
1324
1336
  }
1325
1337
  let result;
1326
1338
  try {
1327
- result = await exchangeToken(getExchangeRecaptchaEnterpriseTokenRequest(this._app, attestedClaimsToken), this._heartbeatServiceProvider);
1339
+ const request = getExchangeRecaptchaEnterpriseTokenRequest(this._app, attestedClaimsToken);
1340
+ if (isLimitedUse) {
1341
+ request.body['limited_use'] = true;
1342
+ }
1343
+ result = await exchangeToken(request, this._heartbeatServiceProvider);
1328
1344
  }
1329
1345
  catch (e) {
1330
1346
  if (e.code?.includes("fetch-status-error" /* AppCheckError.FETCH_STATUS_ERROR */)) {
@@ -1485,7 +1501,6 @@ function throwIfThrottled(throttleData) {
1485
1501
  */
1486
1502
  function initializeAppCheck(app$1 = app.getApp(), options) {
1487
1503
  app$1 = util.getModularInstance(app$1);
1488
- const provider = app._getProvider(app$1, 'app-check');
1489
1504
  // Ensure initializeDebugMode() is only called once.
1490
1505
  if (!getDebugState().initialized) {
1491
1506
  initializeDebugMode();
@@ -1498,22 +1513,53 @@ function initializeAppCheck(app$1 = app.getApp(), options) {
1498
1513
  // Not using logger because I don't think we ever want this accidentally hidden.
1499
1514
  console.log(`App Check debug token: ${token}. You will need to add it to your app's App Check settings in the Firebase console for it to work.`));
1500
1515
  }
1501
- if (provider.isInitialized()) {
1502
- const existingInstance = provider.getImmediate();
1503
- const initialOptions = provider.getOptions();
1504
- if (initialOptions.isTokenAutoRefreshEnabled ===
1505
- options.isTokenAutoRefreshEnabled &&
1506
- initialOptions.provider.isEqual(options.provider)) {
1516
+ let defaultProvider;
1517
+ /**
1518
+ * If user did not pass a provider, look for site key in project
1519
+ * config and create a default ReCaptchaEnterpriseProvider with it.
1520
+ */
1521
+ if (!options?.provider && app$1.options.recaptchaSiteKey) {
1522
+ defaultProvider = new ReCaptchaEnterpriseProvider(app$1.options.recaptchaSiteKey);
1523
+ }
1524
+ /**
1525
+ * If there's no passed provider and no siteKey in project config,
1526
+ * throw.
1527
+ */
1528
+ if (!options?.provider && !defaultProvider) {
1529
+ throw ERROR_FACTORY.create("no-provider" /* AppCheckError.NO_PROVIDER */);
1530
+ }
1531
+ const initOptions = {
1532
+ ...options,
1533
+ provider: options?.provider || defaultProvider
1534
+ };
1535
+ const componentProvider = app._getProvider(app$1, 'app-check');
1536
+ if (componentProvider.isInitialized()) {
1537
+ const existingInstance = componentProvider.getImmediate();
1538
+ const existingOptions = componentProvider.getOptions();
1539
+ /**
1540
+ * Check if all AppCheckOptions previously passed to initializeAppCheck
1541
+ * (`isTokenAutoRefreshEnabled` and `provider`) match those being passed
1542
+ * now. If so, return previous existing instance. Otherwise throw error.
1543
+ */
1544
+ if (existingOptions.isTokenAutoRefreshEnabled ===
1545
+ initOptions.isTokenAutoRefreshEnabled &&
1546
+ existingOptions.provider?.isEqual(initOptions.provider)) {
1507
1547
  return existingInstance;
1508
1548
  }
1509
1549
  else {
1550
+ if (typeof getStateReference(app$1).internallyInitializedBy === 'string') {
1551
+ throw ERROR_FACTORY.create("already-internally-initialized" /* AppCheckError.ALREADY_INTERNALLY_INITIALIZED */, {
1552
+ initializerName: getStateReference(app$1)
1553
+ .internallyInitializedBy
1554
+ });
1555
+ }
1510
1556
  throw ERROR_FACTORY.create("already-initialized" /* AppCheckError.ALREADY_INITIALIZED */, {
1511
1557
  appName: app$1.name
1512
1558
  });
1513
1559
  }
1514
1560
  }
1515
- const appCheck = provider.initialize({ options });
1516
- _activate(app$1, options.provider, options.isTokenAutoRefreshEnabled);
1561
+ const appCheck = componentProvider.initialize({ options: initOptions });
1562
+ _activate(app$1, initOptions.provider, initOptions.isTokenAutoRefreshEnabled);
1517
1563
  // If isTokenAutoRefreshEnabled is false, do not send any requests to the
1518
1564
  // exchange endpoint without an explicit call from the user either directly
1519
1565
  // or through another Firebase library (storage, functions, etc.)
@@ -1527,6 +1573,29 @@ function initializeAppCheck(app$1 = app.getApp(), options) {
1527
1573
  }
1528
1574
  return appCheck;
1529
1575
  }
1576
+ /**
1577
+ * Internal wrapper that sets a state variable flagging that this was
1578
+ * initialized under the hood by a product SDK.
1579
+ *
1580
+ * @internal
1581
+ */
1582
+ function _initializeAppCheckInternal(
1583
+ // String to be used in error message if there is a future conflict.
1584
+ // Example: "Firebase AI Logic"
1585
+ initializerName, app$1 = app.getApp(), options) {
1586
+ const componentProvider = app._getProvider(app$1, 'app-check');
1587
+ const previouslyInitialized = componentProvider.isInitialized();
1588
+ if (previouslyInitialized) {
1589
+ // Product SDKs should accept any previously initialized
1590
+ // App Check configuration without error.
1591
+ return componentProvider.getImmediate();
1592
+ }
1593
+ else {
1594
+ const appCheck = initializeAppCheck(app$1, options);
1595
+ getStateReference(app$1).internallyInitializedBy = initializerName;
1596
+ return appCheck;
1597
+ }
1598
+ }
1530
1599
  /**
1531
1600
  * Activate App Check
1532
1601
  * @param app - Firebase app to activate App Check for.
@@ -1697,6 +1766,7 @@ registerAppCheck();
1697
1766
  exports.CustomProvider = CustomProvider;
1698
1767
  exports.ReCaptchaEnterpriseProvider = ReCaptchaEnterpriseProvider;
1699
1768
  exports.ReCaptchaV3Provider = ReCaptchaV3Provider;
1769
+ exports._initializeAppCheckInternal = _initializeAppCheckInternal;
1700
1770
  exports.getLimitedUseToken = getLimitedUseToken;
1701
1771
  exports.getToken = getToken;
1702
1772
  exports.initializeAppCheck = initializeAppCheck;