@firebase/app-check 0.4.2-pr5646.6d9dd3616 → 0.5.0

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.
@@ -56,6 +56,7 @@ function getDebugState() {
56
56
  */
57
57
  const BASE_ENDPOINT = 'https://content-firebaseappcheck.googleapis.com/v1beta';
58
58
  const EXCHANGE_RECAPTCHA_TOKEN_METHOD = 'exchangeRecaptchaToken';
59
+ const EXCHANGE_RECAPTCHA_ENTERPRISE_TOKEN_METHOD = 'exchangeRecaptchaEnterpriseToken';
59
60
  const EXCHANGE_DEBUG_TOKEN_METHOD = 'exchangeDebugToken';
60
61
  const TOKEN_REFRESH_TIME = {
61
62
  /**
@@ -233,7 +234,11 @@ const ERROR_FACTORY = new ErrorFactory('appCheck', 'AppCheck', ERRORS);
233
234
  * See the License for the specific language governing permissions and
234
235
  * limitations under the License.
235
236
  */
236
- function getRecaptcha() {
237
+ function getRecaptcha(isEnterprise = false) {
238
+ var _a;
239
+ if (isEnterprise) {
240
+ return (_a = self.grecaptcha) === null || _a === void 0 ? void 0 : _a.enterprise;
241
+ }
237
242
  return self.grecaptcha;
238
243
  }
239
244
  function ensureActivated(app) {
@@ -326,13 +331,21 @@ async function exchangeToken({ url, body }, platformLoggerProvider) {
326
331
  issuedAtTimeMillis: now
327
332
  };
328
333
  }
329
- function getExchangeRecaptchaTokenRequest(app, reCAPTCHAToken) {
334
+ function getExchangeRecaptchaV3TokenRequest(app, reCAPTCHAToken) {
330
335
  const { projectId, appId, apiKey } = app.options;
331
336
  return {
332
337
  url: `${BASE_ENDPOINT}/projects/${projectId}/apps/${appId}:${EXCHANGE_RECAPTCHA_TOKEN_METHOD}?key=${apiKey}`,
333
338
  body: {
334
- // eslint-disable-next-line
335
- recaptcha_token: reCAPTCHAToken
339
+ 'recaptcha_token': reCAPTCHAToken
340
+ }
341
+ };
342
+ }
343
+ function getExchangeRecaptchaEnterpriseTokenRequest(app, reCAPTCHAToken) {
344
+ const { projectId, appId, apiKey } = app.options;
345
+ return {
346
+ url: `${BASE_ENDPOINT}/projects/${projectId}/apps/${appId}:${EXCHANGE_RECAPTCHA_ENTERPRISE_TOKEN_METHOD}?key=${apiKey}`,
347
+ body: {
348
+ 'recaptcha_enterprise_token': reCAPTCHAToken
336
349
  }
337
350
  };
338
351
  }
@@ -890,7 +903,7 @@ function internalFactory(appCheck) {
890
903
  }
891
904
 
892
905
  const name = "@firebase/app-check";
893
- const version = "0.4.2-pr5646.6d9dd3616";
906
+ const version = "0.5.0";
894
907
 
895
908
  /**
896
909
  * @license
@@ -909,38 +922,72 @@ const version = "0.4.2-pr5646.6d9dd3616";
909
922
  * limitations under the License.
910
923
  */
911
924
  const RECAPTCHA_URL = 'https://www.google.com/recaptcha/api.js';
912
- function initialize(app, siteKey) {
925
+ const RECAPTCHA_ENTERPRISE_URL = 'https://www.google.com/recaptcha/enterprise.js';
926
+ function initializeV3(app, siteKey) {
913
927
  const state = getState(app);
914
928
  const initialized = new Deferred();
915
929
  setState(app, Object.assign(Object.assign({}, state), { reCAPTCHAState: { initialized } }));
916
- const divId = `fire_app_check_${app.name}`;
917
- const invisibleDiv = document.createElement('div');
918
- invisibleDiv.id = divId;
919
- invisibleDiv.style.display = 'none';
920
- document.body.appendChild(invisibleDiv);
921
- const grecaptcha = getRecaptcha();
930
+ const divId = makeDiv(app);
931
+ const grecaptcha = getRecaptcha(false);
922
932
  if (!grecaptcha) {
923
- loadReCAPTCHAScript(() => {
924
- const grecaptcha = getRecaptcha();
933
+ loadReCAPTCHAV3Script(() => {
934
+ const grecaptcha = getRecaptcha(false);
925
935
  if (!grecaptcha) {
926
936
  // it shouldn't happen.
927
937
  throw new Error('no recaptcha');
928
938
  }
929
- grecaptcha.ready(() => {
930
- // Invisible widgets allow us to set a different siteKey for each widget, so we use them to support multiple apps
931
- renderInvisibleWidget(app, siteKey, grecaptcha, divId);
932
- initialized.resolve(grecaptcha);
933
- });
939
+ queueWidgetRender(app, siteKey, grecaptcha, divId, initialized);
934
940
  });
935
941
  }
936
942
  else {
937
- grecaptcha.ready(() => {
938
- renderInvisibleWidget(app, siteKey, grecaptcha, divId);
939
- initialized.resolve(grecaptcha);
943
+ queueWidgetRender(app, siteKey, grecaptcha, divId, initialized);
944
+ }
945
+ return initialized.promise;
946
+ }
947
+ function initializeEnterprise(app, siteKey) {
948
+ const state = getState(app);
949
+ const initialized = new Deferred();
950
+ setState(app, Object.assign(Object.assign({}, state), { reCAPTCHAState: { initialized } }));
951
+ const divId = makeDiv(app);
952
+ const grecaptcha = getRecaptcha(true);
953
+ if (!grecaptcha) {
954
+ loadReCAPTCHAEnterpriseScript(() => {
955
+ const grecaptcha = getRecaptcha(true);
956
+ if (!grecaptcha) {
957
+ // it shouldn't happen.
958
+ throw new Error('no recaptcha');
959
+ }
960
+ queueWidgetRender(app, siteKey, grecaptcha, divId, initialized);
940
961
  });
941
962
  }
963
+ else {
964
+ queueWidgetRender(app, siteKey, grecaptcha, divId, initialized);
965
+ }
942
966
  return initialized.promise;
943
967
  }
968
+ /**
969
+ * Add listener to render the widget and resolve the promise when
970
+ * the grecaptcha.ready() event fires.
971
+ */
972
+ function queueWidgetRender(app, siteKey, grecaptcha, container, initialized) {
973
+ grecaptcha.ready(() => {
974
+ // Invisible widgets allow us to set a different siteKey for each widget,
975
+ // so we use them to support multiple apps
976
+ renderInvisibleWidget(app, siteKey, grecaptcha, container);
977
+ initialized.resolve(grecaptcha);
978
+ });
979
+ }
980
+ /**
981
+ * Add invisible div to page.
982
+ */
983
+ function makeDiv(app) {
984
+ const divId = `fire_app_check_${app.name}`;
985
+ const invisibleDiv = document.createElement('div');
986
+ invisibleDiv.id = divId;
987
+ invisibleDiv.style.display = 'none';
988
+ document.body.appendChild(invisibleDiv);
989
+ return divId;
990
+ }
944
991
  async function getToken$1(app) {
945
992
  ensureActivated(app);
946
993
  // ensureActivated() guarantees that reCAPTCHAState is set
@@ -972,9 +1019,15 @@ function renderInvisibleWidget(app, siteKey, grecaptcha, container) {
972
1019
  setState(app, Object.assign(Object.assign({}, state), { reCAPTCHAState: Object.assign(Object.assign({}, state.reCAPTCHAState), { // state.reCAPTCHAState is set in the initialize()
973
1020
  widgetId }) }));
974
1021
  }
975
- function loadReCAPTCHAScript(onload) {
1022
+ function loadReCAPTCHAV3Script(onload) {
976
1023
  const script = document.createElement('script');
977
- script.src = `${RECAPTCHA_URL}`;
1024
+ script.src = RECAPTCHA_URL;
1025
+ script.onload = onload;
1026
+ document.head.appendChild(script);
1027
+ }
1028
+ function loadReCAPTCHAEnterpriseScript(onload) {
1029
+ const script = document.createElement('script');
1030
+ script.src = RECAPTCHA_ENTERPRISE_URL;
978
1031
  script.onload = onload;
979
1032
  document.head.appendChild(script);
980
1033
  }
@@ -1014,19 +1067,13 @@ class ReCaptchaV3Provider {
1014
1067
  * @internal
1015
1068
  */
1016
1069
  async getToken() {
1017
- if (!this._app || !this._platformLoggerProvider) {
1018
- // This should only occur if user has not called initializeAppCheck().
1019
- // We don't have an appName to provide if so.
1020
- // This should already be caught in the top level `getToken()` function.
1021
- throw ERROR_FACTORY.create("use-before-activation" /* USE_BEFORE_ACTIVATION */, {
1022
- appName: ''
1023
- });
1024
- }
1070
+ // Top-level `getToken()` has already checked that App Check is initialized
1071
+ // and therefore this._app and this._platformLoggerProvider are available.
1025
1072
  const attestedClaimsToken = await getToken$1(this._app).catch(_e => {
1026
1073
  // reCaptcha.execute() throws null which is not very descriptive.
1027
1074
  throw ERROR_FACTORY.create("recaptcha-error" /* RECAPTCHA_ERROR */);
1028
1075
  });
1029
- return exchangeToken(getExchangeRecaptchaTokenRequest(this._app, attestedClaimsToken), this._platformLoggerProvider);
1076
+ return exchangeToken(getExchangeRecaptchaV3TokenRequest(this._app, attestedClaimsToken), this._platformLoggerProvider);
1030
1077
  }
1031
1078
  /**
1032
1079
  * @internal
@@ -1034,7 +1081,7 @@ class ReCaptchaV3Provider {
1034
1081
  initialize(app) {
1035
1082
  this._app = app;
1036
1083
  this._platformLoggerProvider = _getProvider(app, 'platform-logger');
1037
- initialize(app, this._siteKey).catch(() => {
1084
+ initializeV3(app, this._siteKey).catch(() => {
1038
1085
  /* we don't care about the initialization result */
1039
1086
  });
1040
1087
  }
@@ -1050,6 +1097,55 @@ class ReCaptchaV3Provider {
1050
1097
  }
1051
1098
  }
1052
1099
  }
1100
+ /**
1101
+ * App Check provider that can obtain a reCAPTCHA Enterprise token and exchange it
1102
+ * for an App Check token.
1103
+ *
1104
+ * @public
1105
+ */
1106
+ class ReCaptchaEnterpriseProvider {
1107
+ /**
1108
+ * Create a ReCaptchaEnterpriseProvider instance.
1109
+ * @param siteKey - reCAPTCHA Enterprise score-based site key.
1110
+ */
1111
+ constructor(_siteKey) {
1112
+ this._siteKey = _siteKey;
1113
+ }
1114
+ /**
1115
+ * Returns an App Check token.
1116
+ * @internal
1117
+ */
1118
+ async getToken() {
1119
+ // Top-level `getToken()` has already checked that App Check is initialized
1120
+ // and therefore this._app and this._platformLoggerProvider are available.
1121
+ const attestedClaimsToken = await getToken$1(this._app).catch(_e => {
1122
+ // reCaptcha.execute() throws null which is not very descriptive.
1123
+ throw ERROR_FACTORY.create("recaptcha-error" /* RECAPTCHA_ERROR */);
1124
+ });
1125
+ return exchangeToken(getExchangeRecaptchaEnterpriseTokenRequest(this._app, attestedClaimsToken), this._platformLoggerProvider);
1126
+ }
1127
+ /**
1128
+ * @internal
1129
+ */
1130
+ initialize(app) {
1131
+ this._app = app;
1132
+ this._platformLoggerProvider = _getProvider(app, 'platform-logger');
1133
+ initializeEnterprise(app, this._siteKey).catch(() => {
1134
+ /* we don't care about the initialization result */
1135
+ });
1136
+ }
1137
+ /**
1138
+ * @internal
1139
+ */
1140
+ isEqual(otherProvider) {
1141
+ if (otherProvider instanceof ReCaptchaEnterpriseProvider) {
1142
+ return this._siteKey === otherProvider._siteKey;
1143
+ }
1144
+ else {
1145
+ return false;
1146
+ }
1147
+ }
1148
+ }
1053
1149
  /**
1054
1150
  * Custom provider class.
1055
1151
  * @public
@@ -1062,14 +1158,6 @@ class CustomProvider {
1062
1158
  * @internal
1063
1159
  */
1064
1160
  async getToken() {
1065
- if (!this._app) {
1066
- // This should only occur if user has not called initializeAppCheck().
1067
- // We don't have an appName to provide if so.
1068
- // This should already be caught in the top level `getToken()` function.
1069
- throw ERROR_FACTORY.create("use-before-activation" /* USE_BEFORE_ACTIVATION */, {
1070
- appName: ''
1071
- });
1072
- }
1073
1161
  // custom provider
1074
1162
  const customToken = await this._customProviderOptions.getToken();
1075
1163
  // Try to extract IAT from custom token, in case this token is not
@@ -1293,5 +1381,5 @@ function registerAppCheck() {
1293
1381
  }
1294
1382
  registerAppCheck();
1295
1383
 
1296
- export { CustomProvider, ReCaptchaV3Provider, getToken, initializeAppCheck, onTokenChanged, setTokenAutoRefreshEnabled };
1384
+ export { CustomProvider, ReCaptchaEnterpriseProvider, ReCaptchaV3Provider, getToken, initializeAppCheck, onTokenChanged, setTokenAutoRefreshEnabled };
1297
1385
  //# sourceMappingURL=index.esm2017.js.map