@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.
- package/CHANGELOG.md +15 -0
- package/dist/app-check-public.d.ts +22 -2
- package/dist/app-check.d.ts +32 -2
- package/dist/esm/index.esm.js +143 -50
- package/dist/esm/index.esm.js.map +1 -1
- package/dist/esm/index.esm2017.js +131 -43
- package/dist/esm/index.esm2017.js.map +1 -1
- package/dist/esm/src/api.d.ts +1 -1
- package/dist/esm/src/client.d.ts +2 -1
- package/dist/esm/src/constants.d.ts +1 -0
- package/dist/esm/src/providers.d.ts +29 -0
- package/dist/esm/src/public-types.d.ts +3 -3
- package/dist/esm/src/recaptcha.d.ts +7 -2
- package/dist/esm/src/util.d.ts +1 -1
- package/dist/esm/test/util.d.ts +2 -2
- package/dist/index.cjs.js +143 -49
- package/dist/index.cjs.js.map +1 -1
- package/dist/src/api.d.ts +1 -1
- package/dist/src/client.d.ts +2 -1
- package/dist/src/constants.d.ts +1 -0
- package/dist/src/providers.d.ts +29 -0
- package/dist/src/public-types.d.ts +3 -3
- package/dist/src/recaptcha.d.ts +7 -2
- package/dist/src/util.d.ts +1 -1
- package/dist/test/util.d.ts +2 -2
- package/package.json +11 -10
|
@@ -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
|
|
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
|
-
|
|
335
|
-
|
|
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.
|
|
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
|
-
|
|
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 =
|
|
917
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
938
|
-
|
|
939
|
-
|
|
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
|
|
1022
|
+
function loadReCAPTCHAV3Script(onload) {
|
|
976
1023
|
const script = document.createElement('script');
|
|
977
|
-
script.src =
|
|
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
|
-
|
|
1018
|
-
|
|
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(
|
|
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
|
-
|
|
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
|