index.cjs.js 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var app = require('@firebase/app');
  4. var component = require('@firebase/component');
  5. var tslib = require('tslib');
  6. var util = require('@firebase/util');
  7. var logger$1 = require('@firebase/logger');
  8. /**
  9. * @license
  10. * Copyright 2020 Google LLC
  11. *
  12. * Licensed under the Apache License, Version 2.0 (the "License");
  13. * you may not use this file except in compliance with the License.
  14. * You may obtain a copy of the License at
  15. *
  16. * http://www.apache.org/licenses/LICENSE-2.0
  17. *
  18. * Unless required by applicable law or agreed to in writing, software
  19. * distributed under the License is distributed on an "AS IS" BASIS,
  20. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  21. * See the License for the specific language governing permissions and
  22. * limitations under the License.
  23. */
  24. var APP_CHECK_STATES = new Map();
  25. var DEFAULT_STATE = {
  26. activated: false,
  27. tokenObservers: []
  28. };
  29. var DEBUG_STATE = {
  30. initialized: false,
  31. enabled: false
  32. };
  33. /**
  34. * Gets a reference to the state object.
  35. */
  36. function getStateReference(app) {
  37. return APP_CHECK_STATES.get(app) || tslib.__assign({}, DEFAULT_STATE);
  38. }
  39. /**
  40. * Set once on initialization. The map should hold the same reference to the
  41. * same object until this entry is deleted.
  42. */
  43. function setInitialState(app, state) {
  44. APP_CHECK_STATES.set(app, state);
  45. return APP_CHECK_STATES.get(app);
  46. }
  47. function getDebugState() {
  48. return DEBUG_STATE;
  49. }
  50. /**
  51. * @license
  52. * Copyright 2020 Google LLC
  53. *
  54. * Licensed under the Apache License, Version 2.0 (the "License");
  55. * you may not use this file except in compliance with the License.
  56. * You may obtain a copy of the License at
  57. *
  58. * http://www.apache.org/licenses/LICENSE-2.0
  59. *
  60. * Unless required by applicable law or agreed to in writing, software
  61. * distributed under the License is distributed on an "AS IS" BASIS,
  62. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  63. * See the License for the specific language governing permissions and
  64. * limitations under the License.
  65. */
  66. var BASE_ENDPOINT = 'https://content-firebaseappcheck.googleapis.com/v1';
  67. var EXCHANGE_RECAPTCHA_TOKEN_METHOD = 'exchangeRecaptchaV3Token';
  68. var EXCHANGE_RECAPTCHA_ENTERPRISE_TOKEN_METHOD = 'exchangeRecaptchaEnterpriseToken';
  69. var EXCHANGE_DEBUG_TOKEN_METHOD = 'exchangeDebugToken';
  70. var TOKEN_REFRESH_TIME = {
  71. /**
  72. * The offset time before token natural expiration to run the refresh.
  73. * This is currently 5 minutes.
  74. */
  75. OFFSET_DURATION: 5 * 60 * 1000,
  76. /**
  77. * This is the first retrial wait after an error. This is currently
  78. * 30 seconds.
  79. */
  80. RETRIAL_MIN_WAIT: 30 * 1000,
  81. /**
  82. * This is the maximum retrial wait, currently 16 minutes.
  83. */
  84. RETRIAL_MAX_WAIT: 16 * 60 * 1000
  85. };
  86. /**
  87. * One day in millis, for certain error code backoffs.
  88. */
  89. var ONE_DAY = 24 * 60 * 60 * 1000;
  90. /**
  91. * @license
  92. * Copyright 2020 Google LLC
  93. *
  94. * Licensed under the Apache License, Version 2.0 (the "License");
  95. * you may not use this file except in compliance with the License.
  96. * You may obtain a copy of the License at
  97. *
  98. * http://www.apache.org/licenses/LICENSE-2.0
  99. *
  100. * Unless required by applicable law or agreed to in writing, software
  101. * distributed under the License is distributed on an "AS IS" BASIS,
  102. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  103. * See the License for the specific language governing permissions and
  104. * limitations under the License.
  105. */
  106. /**
  107. * Port from auth proactiverefresh.js
  108. *
  109. */
  110. // TODO: move it to @firebase/util?
  111. // TODO: allow to config whether refresh should happen in the background
  112. var Refresher = /** @class */ (function () {
  113. function Refresher(operation, retryPolicy, getWaitDuration, lowerBound, upperBound) {
  114. this.operation = operation;
  115. this.retryPolicy = retryPolicy;
  116. this.getWaitDuration = getWaitDuration;
  117. this.lowerBound = lowerBound;
  118. this.upperBound = upperBound;
  119. this.pending = null;
  120. this.nextErrorWaitInterval = lowerBound;
  121. if (lowerBound > upperBound) {
  122. throw new Error('Proactive refresh lower bound greater than upper bound!');
  123. }
  124. }
  125. Refresher.prototype.start = function () {
  126. this.nextErrorWaitInterval = this.lowerBound;
  127. this.process(true).catch(function () {
  128. /* we don't care about the result */
  129. });
  130. };
  131. Refresher.prototype.stop = function () {
  132. if (this.pending) {
  133. this.pending.reject('cancelled');
  134. this.pending = null;
  135. }
  136. };
  137. Refresher.prototype.isRunning = function () {
  138. return !!this.pending;
  139. };
  140. Refresher.prototype.process = function (hasSucceeded) {
  141. return tslib.__awaiter(this, void 0, void 0, function () {
  142. var error_1;
  143. return tslib.__generator(this, function (_a) {
  144. switch (_a.label) {
  145. case 0:
  146. this.stop();
  147. _a.label = 1;
  148. case 1:
  149. _a.trys.push([1, 6, , 7]);
  150. this.pending = new util.Deferred();
  151. return [4 /*yield*/, sleep(this.getNextRun(hasSucceeded))];
  152. case 2:
  153. _a.sent();
  154. // Why do we resolve a promise, then immediate wait for it?
  155. // We do it to make the promise chain cancellable.
  156. // We can call stop() which rejects the promise before the following line execute, which makes
  157. // the code jump to the catch block.
  158. // TODO: unit test this
  159. this.pending.resolve();
  160. return [4 /*yield*/, this.pending.promise];
  161. case 3:
  162. _a.sent();
  163. this.pending = new util.Deferred();
  164. return [4 /*yield*/, this.operation()];
  165. case 4:
  166. _a.sent();
  167. this.pending.resolve();
  168. return [4 /*yield*/, this.pending.promise];
  169. case 5:
  170. _a.sent();
  171. this.process(true).catch(function () {
  172. /* we don't care about the result */
  173. });
  174. return [3 /*break*/, 7];
  175. case 6:
  176. error_1 = _a.sent();
  177. if (this.retryPolicy(error_1)) {
  178. this.process(false).catch(function () {
  179. /* we don't care about the result */
  180. });
  181. }
  182. else {
  183. this.stop();
  184. }
  185. return [3 /*break*/, 7];
  186. case 7: return [2 /*return*/];
  187. }
  188. });
  189. });
  190. };
  191. Refresher.prototype.getNextRun = function (hasSucceeded) {
  192. if (hasSucceeded) {
  193. // If last operation succeeded, reset next error wait interval and return
  194. // the default wait duration.
  195. this.nextErrorWaitInterval = this.lowerBound;
  196. // Return typical wait duration interval after a successful operation.
  197. return this.getWaitDuration();
  198. }
  199. else {
  200. // Get next error wait interval.
  201. var currentErrorWaitInterval = this.nextErrorWaitInterval;
  202. // Double interval for next consecutive error.
  203. this.nextErrorWaitInterval *= 2;
  204. // Make sure next wait interval does not exceed the maximum upper bound.
  205. if (this.nextErrorWaitInterval > this.upperBound) {
  206. this.nextErrorWaitInterval = this.upperBound;
  207. }
  208. return currentErrorWaitInterval;
  209. }
  210. };
  211. return Refresher;
  212. }());
  213. function sleep(ms) {
  214. return new Promise(function (resolve) {
  215. setTimeout(resolve, ms);
  216. });
  217. }
  218. /**
  219. * @license
  220. * Copyright 2020 Google LLC
  221. *
  222. * Licensed under the Apache License, Version 2.0 (the "License");
  223. * you may not use this file except in compliance with the License.
  224. * You may obtain a copy of the License at
  225. *
  226. * http://www.apache.org/licenses/LICENSE-2.0
  227. *
  228. * Unless required by applicable law or agreed to in writing, software
  229. * distributed under the License is distributed on an "AS IS" BASIS,
  230. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  231. * See the License for the specific language governing permissions and
  232. * limitations under the License.
  233. */
  234. var _a;
  235. var ERRORS = (_a = {},
  236. _a["already-initialized" /* AppCheckError.ALREADY_INITIALIZED */] = 'You have already called initializeAppCheck() for FirebaseApp {$appName} with ' +
  237. 'different options. To avoid this error, call initializeAppCheck() with the ' +
  238. 'same options as when it was originally called. This will return the ' +
  239. 'already initialized instance.',
  240. _a["use-before-activation" /* AppCheckError.USE_BEFORE_ACTIVATION */] = 'App Check is being used before initializeAppCheck() is called for FirebaseApp {$appName}. ' +
  241. 'Call initializeAppCheck() before instantiating other Firebase services.',
  242. _a["fetch-network-error" /* AppCheckError.FETCH_NETWORK_ERROR */] = 'Fetch failed to connect to a network. Check Internet connection. ' +
  243. 'Original error: {$originalErrorMessage}.',
  244. _a["fetch-parse-error" /* AppCheckError.FETCH_PARSE_ERROR */] = 'Fetch client could not parse response.' +
  245. ' Original error: {$originalErrorMessage}.',
  246. _a["fetch-status-error" /* AppCheckError.FETCH_STATUS_ERROR */] = 'Fetch server returned an HTTP error status. HTTP status: {$httpStatus}.',
  247. _a["storage-open" /* AppCheckError.STORAGE_OPEN */] = 'Error thrown when opening storage. Original error: {$originalErrorMessage}.',
  248. _a["storage-get" /* AppCheckError.STORAGE_GET */] = 'Error thrown when reading from storage. Original error: {$originalErrorMessage}.',
  249. _a["storage-set" /* AppCheckError.STORAGE_WRITE */] = 'Error thrown when writing to storage. Original error: {$originalErrorMessage}.',
  250. _a["recaptcha-error" /* AppCheckError.RECAPTCHA_ERROR */] = 'ReCAPTCHA error.',
  251. _a["throttled" /* AppCheckError.THROTTLED */] = "Requests throttled due to {$httpStatus} error. Attempts allowed again after {$time}",
  252. _a);
  253. var ERROR_FACTORY = new util.ErrorFactory('appCheck', 'AppCheck', ERRORS);
  254. /**
  255. * @license
  256. * Copyright 2020 Google LLC
  257. *
  258. * Licensed under the Apache License, Version 2.0 (the "License");
  259. * you may not use this file except in compliance with the License.
  260. * You may obtain a copy of the License at
  261. *
  262. * http://www.apache.org/licenses/LICENSE-2.0
  263. *
  264. * Unless required by applicable law or agreed to in writing, software
  265. * distributed under the License is distributed on an "AS IS" BASIS,
  266. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  267. * See the License for the specific language governing permissions and
  268. * limitations under the License.
  269. */
  270. function getRecaptcha(isEnterprise) {
  271. var _a;
  272. if (isEnterprise === void 0) { isEnterprise = false; }
  273. if (isEnterprise) {
  274. return (_a = self.grecaptcha) === null || _a === void 0 ? void 0 : _a.enterprise;
  275. }
  276. return self.grecaptcha;
  277. }
  278. function ensureActivated(app) {
  279. if (!getStateReference(app).activated) {
  280. throw ERROR_FACTORY.create("use-before-activation" /* AppCheckError.USE_BEFORE_ACTIVATION */, {
  281. appName: app.name
  282. });
  283. }
  284. }
  285. function getDurationString(durationInMillis) {
  286. var totalSeconds = Math.round(durationInMillis / 1000);
  287. var days = Math.floor(totalSeconds / (3600 * 24));
  288. var hours = Math.floor((totalSeconds - days * 3600 * 24) / 3600);
  289. var minutes = Math.floor((totalSeconds - days * 3600 * 24 - hours * 3600) / 60);
  290. var seconds = totalSeconds - days * 3600 * 24 - hours * 3600 - minutes * 60;
  291. var result = '';
  292. if (days) {
  293. result += pad(days) + 'd:';
  294. }
  295. if (hours) {
  296. result += pad(hours) + 'h:';
  297. }
  298. result += pad(minutes) + 'm:' + pad(seconds) + 's';
  299. return result;
  300. }
  301. function pad(value) {
  302. if (value === 0) {
  303. return '00';
  304. }
  305. return value >= 10 ? value.toString() : '0' + value;
  306. }
  307. /**
  308. * @license
  309. * Copyright 2020 Google LLC
  310. *
  311. * Licensed under the Apache License, Version 2.0 (the "License");
  312. * you may not use this file except in compliance with the License.
  313. * You may obtain a copy of the License at
  314. *
  315. * http://www.apache.org/licenses/LICENSE-2.0
  316. *
  317. * Unless required by applicable law or agreed to in writing, software
  318. * distributed under the License is distributed on an "AS IS" BASIS,
  319. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  320. * See the License for the specific language governing permissions and
  321. * limitations under the License.
  322. */
  323. function exchangeToken(_a, heartbeatServiceProvider) {
  324. var url = _a.url, body = _a.body;
  325. return tslib.__awaiter(this, void 0, void 0, function () {
  326. var headers, heartbeatService, heartbeatsHeader, options, response, originalError_1, responseBody, originalError_2, match, timeToLiveAsNumber, now;
  327. return tslib.__generator(this, function (_b) {
  328. switch (_b.label) {
  329. case 0:
  330. headers = {
  331. 'Content-Type': 'application/json'
  332. };
  333. heartbeatService = heartbeatServiceProvider.getImmediate({
  334. optional: true
  335. });
  336. if (!heartbeatService) return [3 /*break*/, 2];
  337. return [4 /*yield*/, heartbeatService.getHeartbeatsHeader()];
  338. case 1:
  339. heartbeatsHeader = _b.sent();
  340. if (heartbeatsHeader) {
  341. headers['X-Firebase-Client'] = heartbeatsHeader;
  342. }
  343. _b.label = 2;
  344. case 2:
  345. options = {
  346. method: 'POST',
  347. body: JSON.stringify(body),
  348. headers: headers
  349. };
  350. _b.label = 3;
  351. case 3:
  352. _b.trys.push([3, 5, , 6]);
  353. return [4 /*yield*/, fetch(url, options)];
  354. case 4:
  355. response = _b.sent();
  356. return [3 /*break*/, 6];
  357. case 5:
  358. originalError_1 = _b.sent();
  359. throw ERROR_FACTORY.create("fetch-network-error" /* AppCheckError.FETCH_NETWORK_ERROR */, {
  360. originalErrorMessage: originalError_1 === null || originalError_1 === void 0 ? void 0 : originalError_1.message
  361. });
  362. case 6:
  363. if (response.status !== 200) {
  364. throw ERROR_FACTORY.create("fetch-status-error" /* AppCheckError.FETCH_STATUS_ERROR */, {
  365. httpStatus: response.status
  366. });
  367. }
  368. _b.label = 7;
  369. case 7:
  370. _b.trys.push([7, 9, , 10]);
  371. return [4 /*yield*/, response.json()];
  372. case 8:
  373. // JSON parsing throws SyntaxError if the response body isn't a JSON string.
  374. responseBody = _b.sent();
  375. return [3 /*break*/, 10];
  376. case 9:
  377. originalError_2 = _b.sent();
  378. throw ERROR_FACTORY.create("fetch-parse-error" /* AppCheckError.FETCH_PARSE_ERROR */, {
  379. originalErrorMessage: originalError_2 === null || originalError_2 === void 0 ? void 0 : originalError_2.message
  380. });
  381. case 10:
  382. match = responseBody.ttl.match(/^([\d.]+)(s)$/);
  383. if (!match || !match[2] || isNaN(Number(match[1]))) {
  384. throw ERROR_FACTORY.create("fetch-parse-error" /* AppCheckError.FETCH_PARSE_ERROR */, {
  385. originalErrorMessage: "ttl field (timeToLive) is not in standard Protobuf Duration " +
  386. "format: ".concat(responseBody.ttl)
  387. });
  388. }
  389. timeToLiveAsNumber = Number(match[1]) * 1000;
  390. now = Date.now();
  391. return [2 /*return*/, {
  392. token: responseBody.token,
  393. expireTimeMillis: now + timeToLiveAsNumber,
  394. issuedAtTimeMillis: now
  395. }];
  396. }
  397. });
  398. });
  399. }
  400. function getExchangeRecaptchaV3TokenRequest(app, reCAPTCHAToken) {
  401. var _a = app.options, projectId = _a.projectId, appId = _a.appId, apiKey = _a.apiKey;
  402. return {
  403. url: "".concat(BASE_ENDPOINT, "/projects/").concat(projectId, "/apps/").concat(appId, ":").concat(EXCHANGE_RECAPTCHA_TOKEN_METHOD, "?key=").concat(apiKey),
  404. body: {
  405. 'recaptcha_v3_token': reCAPTCHAToken
  406. }
  407. };
  408. }
  409. function getExchangeRecaptchaEnterpriseTokenRequest(app, reCAPTCHAToken) {
  410. var _a = app.options, projectId = _a.projectId, appId = _a.appId, apiKey = _a.apiKey;
  411. return {
  412. url: "".concat(BASE_ENDPOINT, "/projects/").concat(projectId, "/apps/").concat(appId, ":").concat(EXCHANGE_RECAPTCHA_ENTERPRISE_TOKEN_METHOD, "?key=").concat(apiKey),
  413. body: {
  414. 'recaptcha_enterprise_token': reCAPTCHAToken
  415. }
  416. };
  417. }
  418. function getExchangeDebugTokenRequest(app, debugToken) {
  419. var _a = app.options, projectId = _a.projectId, appId = _a.appId, apiKey = _a.apiKey;
  420. return {
  421. url: "".concat(BASE_ENDPOINT, "/projects/").concat(projectId, "/apps/").concat(appId, ":").concat(EXCHANGE_DEBUG_TOKEN_METHOD, "?key=").concat(apiKey),
  422. body: {
  423. // eslint-disable-next-line
  424. debug_token: debugToken
  425. }
  426. };
  427. }
  428. /**
  429. * @license
  430. * Copyright 2020 Google LLC
  431. *
  432. * Licensed under the Apache License, Version 2.0 (the "License");
  433. * you may not use this file except in compliance with the License.
  434. * You may obtain a copy of the License at
  435. *
  436. * http://www.apache.org/licenses/LICENSE-2.0
  437. *
  438. * Unless required by applicable law or agreed to in writing, software
  439. * distributed under the License is distributed on an "AS IS" BASIS,
  440. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  441. * See the License for the specific language governing permissions and
  442. * limitations under the License.
  443. */
  444. var DB_NAME = 'firebase-app-check-database';
  445. var DB_VERSION = 1;
  446. var STORE_NAME = 'firebase-app-check-store';
  447. var DEBUG_TOKEN_KEY = 'debug-token';
  448. var dbPromise = null;
  449. function getDBPromise() {
  450. if (dbPromise) {
  451. return dbPromise;
  452. }
  453. dbPromise = new Promise(function (resolve, reject) {
  454. try {
  455. var request = indexedDB.open(DB_NAME, DB_VERSION);
  456. request.onsuccess = function (event) {
  457. resolve(event.target.result);
  458. };
  459. request.onerror = function (event) {
  460. var _a;
  461. reject(ERROR_FACTORY.create("storage-open" /* AppCheckError.STORAGE_OPEN */, {
  462. originalErrorMessage: (_a = event.target.error) === null || _a === void 0 ? void 0 : _a.message
  463. }));
  464. };
  465. request.onupgradeneeded = function (event) {
  466. var db = event.target.result;
  467. // We don't use 'break' in this switch statement, the fall-through
  468. // behavior is what we want, because if there are multiple versions between
  469. // the old version and the current version, we want ALL the migrations
  470. // that correspond to those versions to run, not only the last one.
  471. // eslint-disable-next-line default-case
  472. switch (event.oldVersion) {
  473. case 0:
  474. db.createObjectStore(STORE_NAME, {
  475. keyPath: 'compositeKey'
  476. });
  477. }
  478. };
  479. }
  480. catch (e) {
  481. reject(ERROR_FACTORY.create("storage-open" /* AppCheckError.STORAGE_OPEN */, {
  482. originalErrorMessage: e === null || e === void 0 ? void 0 : e.message
  483. }));
  484. }
  485. });
  486. return dbPromise;
  487. }
  488. function readTokenFromIndexedDB(app) {
  489. return read(computeKey(app));
  490. }
  491. function writeTokenToIndexedDB(app, token) {
  492. return write(computeKey(app), token);
  493. }
  494. function writeDebugTokenToIndexedDB(token) {
  495. return write(DEBUG_TOKEN_KEY, token);
  496. }
  497. function readDebugTokenFromIndexedDB() {
  498. return read(DEBUG_TOKEN_KEY);
  499. }
  500. function write(key, value) {
  501. return tslib.__awaiter(this, void 0, void 0, function () {
  502. var db, transaction, store, request;
  503. return tslib.__generator(this, function (_a) {
  504. switch (_a.label) {
  505. case 0: return [4 /*yield*/, getDBPromise()];
  506. case 1:
  507. db = _a.sent();
  508. transaction = db.transaction(STORE_NAME, 'readwrite');
  509. store = transaction.objectStore(STORE_NAME);
  510. request = store.put({
  511. compositeKey: key,
  512. value: value
  513. });
  514. return [2 /*return*/, new Promise(function (resolve, reject) {
  515. request.onsuccess = function (_event) {
  516. resolve();
  517. };
  518. transaction.onerror = function (event) {
  519. var _a;
  520. reject(ERROR_FACTORY.create("storage-set" /* AppCheckError.STORAGE_WRITE */, {
  521. originalErrorMessage: (_a = event.target.error) === null || _a === void 0 ? void 0 : _a.message
  522. }));
  523. };
  524. })];
  525. }
  526. });
  527. });
  528. }
  529. function read(key) {
  530. return tslib.__awaiter(this, void 0, void 0, function () {
  531. var db, transaction, store, request;
  532. return tslib.__generator(this, function (_a) {
  533. switch (_a.label) {
  534. case 0: return [4 /*yield*/, getDBPromise()];
  535. case 1:
  536. db = _a.sent();
  537. transaction = db.transaction(STORE_NAME, 'readonly');
  538. store = transaction.objectStore(STORE_NAME);
  539. request = store.get(key);
  540. return [2 /*return*/, new Promise(function (resolve, reject) {
  541. request.onsuccess = function (event) {
  542. var result = event.target.result;
  543. if (result) {
  544. resolve(result.value);
  545. }
  546. else {
  547. resolve(undefined);
  548. }
  549. };
  550. transaction.onerror = function (event) {
  551. var _a;
  552. reject(ERROR_FACTORY.create("storage-get" /* AppCheckError.STORAGE_GET */, {
  553. originalErrorMessage: (_a = event.target.error) === null || _a === void 0 ? void 0 : _a.message
  554. }));
  555. };
  556. })];
  557. }
  558. });
  559. });
  560. }
  561. function computeKey(app) {
  562. return "".concat(app.options.appId, "-").concat(app.name);
  563. }
  564. /**
  565. * @license
  566. * Copyright 2020 Google LLC
  567. *
  568. * Licensed under the Apache License, Version 2.0 (the "License");
  569. * you may not use this file except in compliance with the License.
  570. * You may obtain a copy of the License at
  571. *
  572. * http://www.apache.org/licenses/LICENSE-2.0
  573. *
  574. * Unless required by applicable law or agreed to in writing, software
  575. * distributed under the License is distributed on an "AS IS" BASIS,
  576. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  577. * See the License for the specific language governing permissions and
  578. * limitations under the License.
  579. */
  580. var logger = new logger$1.Logger('@firebase/app-check');
  581. /**
  582. * @license
  583. * Copyright 2020 Google LLC
  584. *
  585. * Licensed under the Apache License, Version 2.0 (the "License");
  586. * you may not use this file except in compliance with the License.
  587. * You may obtain a copy of the License at
  588. *
  589. * http://www.apache.org/licenses/LICENSE-2.0
  590. *
  591. * Unless required by applicable law or agreed to in writing, software
  592. * distributed under the License is distributed on an "AS IS" BASIS,
  593. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  594. * See the License for the specific language governing permissions and
  595. * limitations under the License.
  596. */
  597. /**
  598. * Always resolves. In case of an error reading from indexeddb, resolve with undefined
  599. */
  600. function readTokenFromStorage(app) {
  601. return tslib.__awaiter(this, void 0, void 0, function () {
  602. var token, e_1;
  603. return tslib.__generator(this, function (_a) {
  604. switch (_a.label) {
  605. case 0:
  606. if (!util.isIndexedDBAvailable()) return [3 /*break*/, 5];
  607. token = undefined;
  608. _a.label = 1;
  609. case 1:
  610. _a.trys.push([1, 3, , 4]);
  611. return [4 /*yield*/, readTokenFromIndexedDB(app)];
  612. case 2:
  613. token = _a.sent();
  614. return [3 /*break*/, 4];
  615. case 3:
  616. e_1 = _a.sent();
  617. // swallow the error and return undefined
  618. logger.warn("Failed to read token from IndexedDB. Error: ".concat(e_1));
  619. return [3 /*break*/, 4];
  620. case 4: return [2 /*return*/, token];
  621. case 5: return [2 /*return*/, undefined];
  622. }
  623. });
  624. });
  625. }
  626. /**
  627. * Always resolves. In case of an error writing to indexeddb, print a warning and resolve the promise
  628. */
  629. function writeTokenToStorage(app, token) {
  630. if (util.isIndexedDBAvailable()) {
  631. return writeTokenToIndexedDB(app, token).catch(function (e) {
  632. // swallow the error and resolve the promise
  633. logger.warn("Failed to write token to IndexedDB. Error: ".concat(e));
  634. });
  635. }
  636. return Promise.resolve();
  637. }
  638. function readOrCreateDebugTokenFromStorage() {
  639. return tslib.__awaiter(this, void 0, void 0, function () {
  640. var existingDebugToken, newToken;
  641. return tslib.__generator(this, function (_a) {
  642. switch (_a.label) {
  643. case 0:
  644. existingDebugToken = undefined;
  645. _a.label = 1;
  646. case 1:
  647. _a.trys.push([1, 3, , 4]);
  648. return [4 /*yield*/, readDebugTokenFromIndexedDB()];
  649. case 2:
  650. existingDebugToken = _a.sent();
  651. return [3 /*break*/, 4];
  652. case 3:
  653. _a.sent();
  654. return [3 /*break*/, 4];
  655. case 4:
  656. if (!existingDebugToken) {
  657. newToken = util.uuidv4();
  658. // We don't need to block on writing to indexeddb
  659. // In case persistence failed, a new debug token will be generated everytime the page is refreshed.
  660. // It renders the debug token useless because you have to manually register(whitelist) the new token in the firebase console again and again.
  661. // If you see this error trying to use debug token, it probably means you are using a browser that doesn't support indexeddb.
  662. // You should switch to a different browser that supports indexeddb
  663. writeDebugTokenToIndexedDB(newToken).catch(function (e) {
  664. return logger.warn("Failed to persist debug token to IndexedDB. Error: ".concat(e));
  665. });
  666. return [2 /*return*/, newToken];
  667. }
  668. else {
  669. return [2 /*return*/, existingDebugToken];
  670. }
  671. }
  672. });
  673. });
  674. }
  675. /**
  676. * @license
  677. * Copyright 2020 Google LLC
  678. *
  679. * Licensed under the Apache License, Version 2.0 (the "License");
  680. * you may not use this file except in compliance with the License.
  681. * You may obtain a copy of the License at
  682. *
  683. * http://www.apache.org/licenses/LICENSE-2.0
  684. *
  685. * Unless required by applicable law or agreed to in writing, software
  686. * distributed under the License is distributed on an "AS IS" BASIS,
  687. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  688. * See the License for the specific language governing permissions and
  689. * limitations under the License.
  690. */
  691. function isDebugMode() {
  692. var debugState = getDebugState();
  693. return debugState.enabled;
  694. }
  695. function getDebugToken() {
  696. return tslib.__awaiter(this, void 0, void 0, function () {
  697. var state;
  698. return tslib.__generator(this, function (_a) {
  699. state = getDebugState();
  700. if (state.enabled && state.token) {
  701. return [2 /*return*/, state.token.promise];
  702. }
  703. else {
  704. // should not happen!
  705. throw Error("\n Can't get debug token in production mode.\n ");
  706. }
  707. });
  708. });
  709. }
  710. function initializeDebugMode() {
  711. var globals = util.getGlobal();
  712. var debugState = getDebugState();
  713. // Set to true if this function has been called, whether or not
  714. // it enabled debug mode.
  715. debugState.initialized = true;
  716. if (typeof globals.FIREBASE_APPCHECK_DEBUG_TOKEN !== 'string' &&
  717. globals.FIREBASE_APPCHECK_DEBUG_TOKEN !== true) {
  718. return;
  719. }
  720. debugState.enabled = true;
  721. var deferredToken = new util.Deferred();
  722. debugState.token = deferredToken;
  723. if (typeof globals.FIREBASE_APPCHECK_DEBUG_TOKEN === 'string') {
  724. deferredToken.resolve(globals.FIREBASE_APPCHECK_DEBUG_TOKEN);
  725. }
  726. else {
  727. deferredToken.resolve(readOrCreateDebugTokenFromStorage());
  728. }
  729. }
  730. /**
  731. * @license
  732. * Copyright 2020 Google LLC
  733. *
  734. * Licensed under the Apache License, Version 2.0 (the "License");
  735. * you may not use this file except in compliance with the License.
  736. * You may obtain a copy of the License at
  737. *
  738. * http://www.apache.org/licenses/LICENSE-2.0
  739. *
  740. * Unless required by applicable law or agreed to in writing, software
  741. * distributed under the License is distributed on an "AS IS" BASIS,
  742. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  743. * See the License for the specific language governing permissions and
  744. * limitations under the License.
  745. */
  746. // Initial hardcoded value agreed upon across platforms for initial launch.
  747. // Format left open for possible dynamic error values and other fields in the future.
  748. var defaultTokenErrorData = { error: 'UNKNOWN_ERROR' };
  749. /**
  750. * Stringify and base64 encode token error data.
  751. *
  752. * @param tokenError Error data, currently hardcoded.
  753. */
  754. function formatDummyToken(tokenErrorData) {
  755. return util.base64.encodeString(JSON.stringify(tokenErrorData),
  756. /* webSafe= */ false);
  757. }
  758. /**
  759. * This function always resolves.
  760. * The result will contain an error field if there is any error.
  761. * In case there is an error, the token field in the result will be populated with a dummy value
  762. */
  763. function getToken$2(appCheck, forceRefresh) {
  764. if (forceRefresh === void 0) { forceRefresh = false; }
  765. return tslib.__awaiter(this, void 0, void 0, function () {
  766. var app, state, token, error, cachedToken, shouldCallListeners, _a, _b, _c, _d, tokenFromDebugExchange, e_1, interopTokenResult;
  767. return tslib.__generator(this, function (_e) {
  768. switch (_e.label) {
  769. case 0:
  770. app = appCheck.app;
  771. ensureActivated(app);
  772. state = getStateReference(app);
  773. token = state.token;
  774. error = undefined;
  775. /**
  776. * If an invalid token was found in memory, clear token from
  777. * memory and unset the local variable `token`.
  778. */
  779. if (token && !isValid(token)) {
  780. state.token = undefined;
  781. token = undefined;
  782. }
  783. if (!!token) return [3 /*break*/, 4];
  784. return [4 /*yield*/, state.cachedTokenPromise];
  785. case 1:
  786. cachedToken = _e.sent();
  787. if (!cachedToken) return [3 /*break*/, 4];
  788. if (!isValid(cachedToken)) return [3 /*break*/, 2];
  789. token = cachedToken;
  790. return [3 /*break*/, 4];
  791. case 2:
  792. // If there was an invalid token in the indexedDB cache, clear it.
  793. return [4 /*yield*/, writeTokenToStorage(app, undefined)];
  794. case 3:
  795. // If there was an invalid token in the indexedDB cache, clear it.
  796. _e.sent();
  797. _e.label = 4;
  798. case 4:
  799. // Return the cached token (from either memory or indexedDB) if it's valid
  800. if (!forceRefresh && token && isValid(token)) {
  801. return [2 /*return*/, {
  802. token: token.token
  803. }];
  804. }
  805. shouldCallListeners = false;
  806. if (!isDebugMode()) return [3 /*break*/, 9];
  807. if (!!state.exchangeTokenPromise) return [3 /*break*/, 6];
  808. _a = state;
  809. _b = exchangeToken;
  810. _c = getExchangeDebugTokenRequest;
  811. _d = [app];
  812. return [4 /*yield*/, getDebugToken()];
  813. case 5:
  814. _a.exchangeTokenPromise = _b.apply(void 0, [_c.apply(void 0, _d.concat([_e.sent()])),
  815. appCheck.heartbeatServiceProvider]).finally(function () {
  816. // Clear promise when settled - either resolved or rejected.
  817. state.exchangeTokenPromise = undefined;
  818. });
  819. shouldCallListeners = true;
  820. _e.label = 6;
  821. case 6: return [4 /*yield*/, state.exchangeTokenPromise];
  822. case 7:
  823. tokenFromDebugExchange = _e.sent();
  824. // Write debug token to indexedDB.
  825. return [4 /*yield*/, writeTokenToStorage(app, tokenFromDebugExchange)];
  826. case 8:
  827. // Write debug token to indexedDB.
  828. _e.sent();
  829. // Write debug token to state.
  830. state.token = tokenFromDebugExchange;
  831. return [2 /*return*/, { token: tokenFromDebugExchange.token }];
  832. case 9:
  833. _e.trys.push([9, 11, , 12]);
  834. // Avoid making another call to the exchange endpoint if one is in flight.
  835. if (!state.exchangeTokenPromise) {
  836. // state.provider is populated in initializeAppCheck()
  837. // ensureActivated() at the top of this function checks that
  838. // initializeAppCheck() has been called.
  839. state.exchangeTokenPromise = state.provider.getToken().finally(function () {
  840. // Clear promise when settled - either resolved or rejected.
  841. state.exchangeTokenPromise = undefined;
  842. });
  843. shouldCallListeners = true;
  844. }
  845. return [4 /*yield*/, getStateReference(app).exchangeTokenPromise];
  846. case 10:
  847. token = _e.sent();
  848. return [3 /*break*/, 12];
  849. case 11:
  850. e_1 = _e.sent();
  851. if (e_1.code === "appCheck/".concat("throttled" /* AppCheckError.THROTTLED */)) {
  852. // Warn if throttled, but do not treat it as an error.
  853. logger.warn(e_1.message);
  854. }
  855. else {
  856. // `getToken()` should never throw, but logging error text to console will aid debugging.
  857. logger.error(e_1);
  858. }
  859. // Always save error to be added to dummy token.
  860. error = e_1;
  861. return [3 /*break*/, 12];
  862. case 12:
  863. if (!!token) return [3 /*break*/, 13];
  864. // If token is undefined, there must be an error.
  865. // Return a dummy token along with the error.
  866. interopTokenResult = makeDummyTokenResult(error);
  867. return [3 /*break*/, 16];
  868. case 13:
  869. if (!error) return [3 /*break*/, 14];
  870. if (isValid(token)) {
  871. // It's also possible a valid token exists, but there's also an error.
  872. // (Such as if the token is almost expired, tries to refresh, and
  873. // the exchange request fails.)
  874. // We add a special error property here so that the refresher will
  875. // count this as a failed attempt and use the backoff instead of
  876. // retrying repeatedly with no delay, but any 3P listeners will not
  877. // be hindered in getting the still-valid token.
  878. interopTokenResult = {
  879. token: token.token,
  880. internalError: error
  881. };
  882. }
  883. else {
  884. // No invalid tokens should make it to this step. Memory and cached tokens
  885. // are checked. Other tokens are from fresh exchanges. But just in case.
  886. interopTokenResult = makeDummyTokenResult(error);
  887. }
  888. return [3 /*break*/, 16];
  889. case 14:
  890. interopTokenResult = {
  891. token: token.token
  892. };
  893. // write the new token to the memory state as well as the persistent storage.
  894. // Only do it if we got a valid new token
  895. state.token = token;
  896. return [4 /*yield*/, writeTokenToStorage(app, token)];
  897. case 15:
  898. _e.sent();
  899. _e.label = 16;
  900. case 16:
  901. if (shouldCallListeners) {
  902. notifyTokenListeners(app, interopTokenResult);
  903. }
  904. return [2 /*return*/, interopTokenResult];
  905. }
  906. });
  907. });
  908. }
  909. /**
  910. * Internal API for limited use tokens. Skips all FAC state and simply calls
  911. * the underlying provider.
  912. */
  913. function getLimitedUseToken$1(appCheck) {
  914. return tslib.__awaiter(this, void 0, void 0, function () {
  915. var app, provider, debugToken, token, token;
  916. return tslib.__generator(this, function (_a) {
  917. switch (_a.label) {
  918. case 0:
  919. app = appCheck.app;
  920. ensureActivated(app);
  921. provider = getStateReference(app).provider;
  922. if (!isDebugMode()) return [3 /*break*/, 3];
  923. return [4 /*yield*/, getDebugToken()];
  924. case 1:
  925. debugToken = _a.sent();
  926. return [4 /*yield*/, exchangeToken(getExchangeDebugTokenRequest(app, debugToken), appCheck.heartbeatServiceProvider)];
  927. case 2:
  928. token = (_a.sent()).token;
  929. return [2 /*return*/, { token: token }];
  930. case 3: return [4 /*yield*/, provider.getToken()];
  931. case 4:
  932. token = (_a.sent()).token;
  933. return [2 /*return*/, { token: token }];
  934. }
  935. });
  936. });
  937. }
  938. function addTokenListener(appCheck, type, listener, onError) {
  939. var app = appCheck.app;
  940. var state = getStateReference(app);
  941. var tokenObserver = {
  942. next: listener,
  943. error: onError,
  944. type: type
  945. };
  946. state.tokenObservers = tslib.__spreadArray(tslib.__spreadArray([], state.tokenObservers, true), [tokenObserver], false);
  947. // Invoke the listener async immediately if there is a valid token
  948. // in memory.
  949. if (state.token && isValid(state.token)) {
  950. var validToken_1 = state.token;
  951. Promise.resolve()
  952. .then(function () {
  953. listener({ token: validToken_1.token });
  954. initTokenRefresher(appCheck);
  955. })
  956. .catch(function () {
  957. /* we don't care about exceptions thrown in listeners */
  958. });
  959. }
  960. /**
  961. * Wait for any cached token promise to resolve before starting the token
  962. * refresher. The refresher checks to see if there is an existing token
  963. * in state and calls the exchange endpoint if not. We should first let the
  964. * IndexedDB check have a chance to populate state if it can.
  965. *
  966. * Listener call isn't needed here because cachedTokenPromise will call any
  967. * listeners that exist when it resolves.
  968. */
  969. // state.cachedTokenPromise is always populated in `activate()`.
  970. void state.cachedTokenPromise.then(function () { return initTokenRefresher(appCheck); });
  971. }
  972. function removeTokenListener(app, listener) {
  973. var state = getStateReference(app);
  974. var newObservers = state.tokenObservers.filter(function (tokenObserver) { return tokenObserver.next !== listener; });
  975. if (newObservers.length === 0 &&
  976. state.tokenRefresher &&
  977. state.tokenRefresher.isRunning()) {
  978. state.tokenRefresher.stop();
  979. }
  980. state.tokenObservers = newObservers;
  981. }
  982. /**
  983. * Logic to create and start refresher as needed.
  984. */
  985. function initTokenRefresher(appCheck) {
  986. var app = appCheck.app;
  987. var state = getStateReference(app);
  988. // Create the refresher but don't start it if `isTokenAutoRefreshEnabled`
  989. // is not true.
  990. var refresher = state.tokenRefresher;
  991. if (!refresher) {
  992. refresher = createTokenRefresher(appCheck);
  993. state.tokenRefresher = refresher;
  994. }
  995. if (!refresher.isRunning() && state.isTokenAutoRefreshEnabled) {
  996. refresher.start();
  997. }
  998. }
  999. function createTokenRefresher(appCheck) {
  1000. var _this = this;
  1001. var app = appCheck.app;
  1002. return new Refresher(
  1003. // Keep in mind when this fails for any reason other than the ones
  1004. // for which we should retry, it will effectively stop the proactive refresh.
  1005. function () { return tslib.__awaiter(_this, void 0, void 0, function () {
  1006. var state, result;
  1007. return tslib.__generator(this, function (_a) {
  1008. switch (_a.label) {
  1009. case 0:
  1010. state = getStateReference(app);
  1011. if (!!state.token) return [3 /*break*/, 2];
  1012. return [4 /*yield*/, getToken$2(appCheck)];
  1013. case 1:
  1014. result = _a.sent();
  1015. return [3 /*break*/, 4];
  1016. case 2: return [4 /*yield*/, getToken$2(appCheck, true)];
  1017. case 3:
  1018. result = _a.sent();
  1019. _a.label = 4;
  1020. case 4:
  1021. /**
  1022. * getToken() always resolves. In case the result has an error field defined, it means
  1023. * the operation failed, and we should retry.
  1024. */
  1025. if (result.error) {
  1026. throw result.error;
  1027. }
  1028. /**
  1029. * A special `internalError` field reflects that there was an error
  1030. * getting a new token from the exchange endpoint, but there's still a
  1031. * previous token that's valid for now and this should be passed to 2P/3P
  1032. * requests for a token. But we want this callback (`this.operation` in
  1033. * `Refresher`) to throw in order to kick off the Refresher's retry
  1034. * backoff. (Setting `hasSucceeded` to false.)
  1035. */
  1036. if (result.internalError) {
  1037. throw result.internalError;
  1038. }
  1039. return [2 /*return*/];
  1040. }
  1041. });
  1042. }); }, function () {
  1043. return true;
  1044. }, function () {
  1045. var state = getStateReference(app);
  1046. if (state.token) {
  1047. // issuedAtTime + (50% * total TTL) + 5 minutes
  1048. var nextRefreshTimeMillis = state.token.issuedAtTimeMillis +
  1049. (state.token.expireTimeMillis - state.token.issuedAtTimeMillis) *
  1050. 0.5 +
  1051. 5 * 60 * 1000;
  1052. // Do not allow refresh time to be past (expireTime - 5 minutes)
  1053. var latestAllowableRefresh = state.token.expireTimeMillis - 5 * 60 * 1000;
  1054. nextRefreshTimeMillis = Math.min(nextRefreshTimeMillis, latestAllowableRefresh);
  1055. return Math.max(0, nextRefreshTimeMillis - Date.now());
  1056. }
  1057. else {
  1058. return 0;
  1059. }
  1060. }, TOKEN_REFRESH_TIME.RETRIAL_MIN_WAIT, TOKEN_REFRESH_TIME.RETRIAL_MAX_WAIT);
  1061. }
  1062. function notifyTokenListeners(app, token) {
  1063. var observers = getStateReference(app).tokenObservers;
  1064. for (var _i = 0, observers_1 = observers; _i < observers_1.length; _i++) {
  1065. var observer = observers_1[_i];
  1066. try {
  1067. if (observer.type === "EXTERNAL" /* ListenerType.EXTERNAL */ && token.error != null) {
  1068. // If this listener was added by a 3P call, send any token error to
  1069. // the supplied error handler. A 3P observer always has an error
  1070. // handler.
  1071. observer.error(token.error);
  1072. }
  1073. else {
  1074. // If the token has no error field, always return the token.
  1075. // If this is a 2P listener, return the token, whether or not it
  1076. // has an error field.
  1077. observer.next(token);
  1078. }
  1079. }
  1080. catch (e) {
  1081. // Errors in the listener function itself are always ignored.
  1082. }
  1083. }
  1084. }
  1085. function isValid(token) {
  1086. return token.expireTimeMillis - Date.now() > 0;
  1087. }
  1088. function makeDummyTokenResult(error) {
  1089. return {
  1090. token: formatDummyToken(defaultTokenErrorData),
  1091. error: error
  1092. };
  1093. }
  1094. /**
  1095. * @license
  1096. * Copyright 2020 Google LLC
  1097. *
  1098. * Licensed under the Apache License, Version 2.0 (the "License");
  1099. * you may not use this file except in compliance with the License.
  1100. * You may obtain a copy of the License at
  1101. *
  1102. * http://www.apache.org/licenses/LICENSE-2.0
  1103. *
  1104. * Unless required by applicable law or agreed to in writing, software
  1105. * distributed under the License is distributed on an "AS IS" BASIS,
  1106. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1107. * See the License for the specific language governing permissions and
  1108. * limitations under the License.
  1109. */
  1110. /**
  1111. * AppCheck Service class.
  1112. */
  1113. var AppCheckService = /** @class */ (function () {
  1114. function AppCheckService(app, heartbeatServiceProvider) {
  1115. this.app = app;
  1116. this.heartbeatServiceProvider = heartbeatServiceProvider;
  1117. }
  1118. AppCheckService.prototype._delete = function () {
  1119. var tokenObservers = getStateReference(this.app).tokenObservers;
  1120. for (var _i = 0, tokenObservers_1 = tokenObservers; _i < tokenObservers_1.length; _i++) {
  1121. var tokenObserver = tokenObservers_1[_i];
  1122. removeTokenListener(this.app, tokenObserver.next);
  1123. }
  1124. return Promise.resolve();
  1125. };
  1126. return AppCheckService;
  1127. }());
  1128. function factory(app, heartbeatServiceProvider) {
  1129. return new AppCheckService(app, heartbeatServiceProvider);
  1130. }
  1131. function internalFactory(appCheck) {
  1132. return {
  1133. getToken: function (forceRefresh) { return getToken$2(appCheck, forceRefresh); },
  1134. getLimitedUseToken: function () { return getLimitedUseToken$1(appCheck); },
  1135. addTokenListener: function (listener) {
  1136. return addTokenListener(appCheck, "INTERNAL" /* ListenerType.INTERNAL */, listener);
  1137. },
  1138. removeTokenListener: function (listener) { return removeTokenListener(appCheck.app, listener); }
  1139. };
  1140. }
  1141. var name = "@firebase/app-check";
  1142. var version = "0.8.0";
  1143. /**
  1144. * @license
  1145. * Copyright 2020 Google LLC
  1146. *
  1147. * Licensed under the Apache License, Version 2.0 (the "License");
  1148. * you may not use this file except in compliance with the License.
  1149. * You may obtain a copy of the License at
  1150. *
  1151. * http://www.apache.org/licenses/LICENSE-2.0
  1152. *
  1153. * Unless required by applicable law or agreed to in writing, software
  1154. * distributed under the License is distributed on an "AS IS" BASIS,
  1155. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1156. * See the License for the specific language governing permissions and
  1157. * limitations under the License.
  1158. */
  1159. var RECAPTCHA_URL = 'https://www.google.com/recaptcha/api.js';
  1160. var RECAPTCHA_ENTERPRISE_URL = 'https://www.google.com/recaptcha/enterprise.js';
  1161. function initializeV3(app, siteKey) {
  1162. var initialized = new util.Deferred();
  1163. var state = getStateReference(app);
  1164. state.reCAPTCHAState = { initialized: initialized };
  1165. var divId = makeDiv(app);
  1166. var grecaptcha = getRecaptcha(false);
  1167. if (!grecaptcha) {
  1168. loadReCAPTCHAV3Script(function () {
  1169. var grecaptcha = getRecaptcha(false);
  1170. if (!grecaptcha) {
  1171. // it shouldn't happen.
  1172. throw new Error('no recaptcha');
  1173. }
  1174. queueWidgetRender(app, siteKey, grecaptcha, divId, initialized);
  1175. });
  1176. }
  1177. else {
  1178. queueWidgetRender(app, siteKey, grecaptcha, divId, initialized);
  1179. }
  1180. return initialized.promise;
  1181. }
  1182. function initializeEnterprise(app, siteKey) {
  1183. var initialized = new util.Deferred();
  1184. var state = getStateReference(app);
  1185. state.reCAPTCHAState = { initialized: initialized };
  1186. var divId = makeDiv(app);
  1187. var grecaptcha = getRecaptcha(true);
  1188. if (!grecaptcha) {
  1189. loadReCAPTCHAEnterpriseScript(function () {
  1190. var grecaptcha = getRecaptcha(true);
  1191. if (!grecaptcha) {
  1192. // it shouldn't happen.
  1193. throw new Error('no recaptcha');
  1194. }
  1195. queueWidgetRender(app, siteKey, grecaptcha, divId, initialized);
  1196. });
  1197. }
  1198. else {
  1199. queueWidgetRender(app, siteKey, grecaptcha, divId, initialized);
  1200. }
  1201. return initialized.promise;
  1202. }
  1203. /**
  1204. * Add listener to render the widget and resolve the promise when
  1205. * the grecaptcha.ready() event fires.
  1206. */
  1207. function queueWidgetRender(app, siteKey, grecaptcha, container, initialized) {
  1208. grecaptcha.ready(function () {
  1209. // Invisible widgets allow us to set a different siteKey for each widget,
  1210. // so we use them to support multiple apps
  1211. renderInvisibleWidget(app, siteKey, grecaptcha, container);
  1212. initialized.resolve(grecaptcha);
  1213. });
  1214. }
  1215. /**
  1216. * Add invisible div to page.
  1217. */
  1218. function makeDiv(app) {
  1219. var divId = "fire_app_check_".concat(app.name);
  1220. var invisibleDiv = document.createElement('div');
  1221. invisibleDiv.id = divId;
  1222. invisibleDiv.style.display = 'none';
  1223. document.body.appendChild(invisibleDiv);
  1224. return divId;
  1225. }
  1226. function getToken$1(app) {
  1227. return tslib.__awaiter(this, void 0, void 0, function () {
  1228. var reCAPTCHAState, recaptcha;
  1229. return tslib.__generator(this, function (_a) {
  1230. switch (_a.label) {
  1231. case 0:
  1232. ensureActivated(app);
  1233. reCAPTCHAState = getStateReference(app).reCAPTCHAState;
  1234. return [4 /*yield*/, reCAPTCHAState.initialized.promise];
  1235. case 1:
  1236. recaptcha = _a.sent();
  1237. return [2 /*return*/, new Promise(function (resolve, _reject) {
  1238. // Updated after initialization is complete.
  1239. var reCAPTCHAState = getStateReference(app).reCAPTCHAState;
  1240. recaptcha.ready(function () {
  1241. resolve(
  1242. // widgetId is guaranteed to be available if reCAPTCHAState.initialized.promise resolved.
  1243. recaptcha.execute(reCAPTCHAState.widgetId, {
  1244. action: 'fire_app_check'
  1245. }));
  1246. });
  1247. })];
  1248. }
  1249. });
  1250. });
  1251. }
  1252. /**
  1253. *
  1254. * @param app
  1255. * @param container - Id of a HTML element.
  1256. */
  1257. function renderInvisibleWidget(app, siteKey, grecaptcha, container) {
  1258. var widgetId = grecaptcha.render(container, {
  1259. sitekey: siteKey,
  1260. size: 'invisible',
  1261. // Success callback - set state
  1262. callback: function () {
  1263. getStateReference(app).reCAPTCHAState.succeeded = true;
  1264. },
  1265. // Failure callback - set state
  1266. 'error-callback': function () {
  1267. getStateReference(app).reCAPTCHAState.succeeded = false;
  1268. }
  1269. });
  1270. var state = getStateReference(app);
  1271. state.reCAPTCHAState = tslib.__assign(tslib.__assign({}, state.reCAPTCHAState), { // state.reCAPTCHAState is set in the initialize()
  1272. widgetId: widgetId });
  1273. }
  1274. function loadReCAPTCHAV3Script(onload) {
  1275. var script = document.createElement('script');
  1276. script.src = RECAPTCHA_URL;
  1277. script.onload = onload;
  1278. document.head.appendChild(script);
  1279. }
  1280. function loadReCAPTCHAEnterpriseScript(onload) {
  1281. var script = document.createElement('script');
  1282. script.src = RECAPTCHA_ENTERPRISE_URL;
  1283. script.onload = onload;
  1284. document.head.appendChild(script);
  1285. }
  1286. /**
  1287. * @license
  1288. * Copyright 2021 Google LLC
  1289. *
  1290. * Licensed under the Apache License, Version 2.0 (the "License");
  1291. * you may not use this file except in compliance with the License.
  1292. * You may obtain a copy of the License at
  1293. *
  1294. * http://www.apache.org/licenses/LICENSE-2.0
  1295. *
  1296. * Unless required by applicable law or agreed to in writing, software
  1297. * distributed under the License is distributed on an "AS IS" BASIS,
  1298. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1299. * See the License for the specific language governing permissions and
  1300. * limitations under the License.
  1301. */
  1302. /**
  1303. * App Check provider that can obtain a reCAPTCHA V3 token and exchange it
  1304. * for an App Check token.
  1305. *
  1306. * @public
  1307. */
  1308. var ReCaptchaV3Provider = /** @class */ (function () {
  1309. /**
  1310. * Create a ReCaptchaV3Provider instance.
  1311. * @param siteKey - ReCAPTCHA V3 siteKey.
  1312. */
  1313. function ReCaptchaV3Provider(_siteKey) {
  1314. this._siteKey = _siteKey;
  1315. /**
  1316. * Throttle requests on certain error codes to prevent too many retries
  1317. * in a short time.
  1318. */
  1319. this._throttleData = null;
  1320. }
  1321. /**
  1322. * Returns an App Check token.
  1323. * @internal
  1324. */
  1325. ReCaptchaV3Provider.prototype.getToken = function () {
  1326. var _a, _b, _c;
  1327. return tslib.__awaiter(this, void 0, void 0, function () {
  1328. var attestedClaimsToken, result, e_1;
  1329. return tslib.__generator(this, function (_d) {
  1330. switch (_d.label) {
  1331. case 0:
  1332. throwIfThrottled(this._throttleData);
  1333. return [4 /*yield*/, getToken$1(this._app).catch(function (_e) {
  1334. // reCaptcha.execute() throws null which is not very descriptive.
  1335. throw ERROR_FACTORY.create("recaptcha-error" /* AppCheckError.RECAPTCHA_ERROR */);
  1336. })];
  1337. case 1:
  1338. attestedClaimsToken = _d.sent();
  1339. // Check if a failure state was set by the recaptcha "error-callback".
  1340. if (!((_a = getStateReference(this._app).reCAPTCHAState) === null || _a === void 0 ? void 0 : _a.succeeded)) {
  1341. throw ERROR_FACTORY.create("recaptcha-error" /* AppCheckError.RECAPTCHA_ERROR */);
  1342. }
  1343. _d.label = 2;
  1344. case 2:
  1345. _d.trys.push([2, 4, , 5]);
  1346. return [4 /*yield*/, exchangeToken(getExchangeRecaptchaV3TokenRequest(this._app, attestedClaimsToken), this._heartbeatServiceProvider)];
  1347. case 3:
  1348. result = _d.sent();
  1349. return [3 /*break*/, 5];
  1350. case 4:
  1351. e_1 = _d.sent();
  1352. if ((_b = e_1.code) === null || _b === void 0 ? void 0 : _b.includes("fetch-status-error" /* AppCheckError.FETCH_STATUS_ERROR */)) {
  1353. this._throttleData = setBackoff(Number((_c = e_1.customData) === null || _c === void 0 ? void 0 : _c.httpStatus), this._throttleData);
  1354. throw ERROR_FACTORY.create("throttled" /* AppCheckError.THROTTLED */, {
  1355. time: getDurationString(this._throttleData.allowRequestsAfter - Date.now()),
  1356. httpStatus: this._throttleData.httpStatus
  1357. });
  1358. }
  1359. else {
  1360. throw e_1;
  1361. }
  1362. case 5:
  1363. // If successful, clear throttle data.
  1364. this._throttleData = null;
  1365. return [2 /*return*/, result];
  1366. }
  1367. });
  1368. });
  1369. };
  1370. /**
  1371. * @internal
  1372. */
  1373. ReCaptchaV3Provider.prototype.initialize = function (app$1) {
  1374. this._app = app$1;
  1375. this._heartbeatServiceProvider = app._getProvider(app$1, 'heartbeat');
  1376. initializeV3(app$1, this._siteKey).catch(function () {
  1377. /* we don't care about the initialization result */
  1378. });
  1379. };
  1380. /**
  1381. * @internal
  1382. */
  1383. ReCaptchaV3Provider.prototype.isEqual = function (otherProvider) {
  1384. if (otherProvider instanceof ReCaptchaV3Provider) {
  1385. return this._siteKey === otherProvider._siteKey;
  1386. }
  1387. else {
  1388. return false;
  1389. }
  1390. };
  1391. return ReCaptchaV3Provider;
  1392. }());
  1393. /**
  1394. * App Check provider that can obtain a reCAPTCHA Enterprise token and exchange it
  1395. * for an App Check token.
  1396. *
  1397. * @public
  1398. */
  1399. var ReCaptchaEnterpriseProvider = /** @class */ (function () {
  1400. /**
  1401. * Create a ReCaptchaEnterpriseProvider instance.
  1402. * @param siteKey - reCAPTCHA Enterprise score-based site key.
  1403. */
  1404. function ReCaptchaEnterpriseProvider(_siteKey) {
  1405. this._siteKey = _siteKey;
  1406. /**
  1407. * Throttle requests on certain error codes to prevent too many retries
  1408. * in a short time.
  1409. */
  1410. this._throttleData = null;
  1411. }
  1412. /**
  1413. * Returns an App Check token.
  1414. * @internal
  1415. */
  1416. ReCaptchaEnterpriseProvider.prototype.getToken = function () {
  1417. var _a, _b, _c;
  1418. return tslib.__awaiter(this, void 0, void 0, function () {
  1419. var attestedClaimsToken, result, e_2;
  1420. return tslib.__generator(this, function (_d) {
  1421. switch (_d.label) {
  1422. case 0:
  1423. throwIfThrottled(this._throttleData);
  1424. return [4 /*yield*/, getToken$1(this._app).catch(function (_e) {
  1425. // reCaptcha.execute() throws null which is not very descriptive.
  1426. throw ERROR_FACTORY.create("recaptcha-error" /* AppCheckError.RECAPTCHA_ERROR */);
  1427. })];
  1428. case 1:
  1429. attestedClaimsToken = _d.sent();
  1430. // Check if a failure state was set by the recaptcha "error-callback".
  1431. if (!((_a = getStateReference(this._app).reCAPTCHAState) === null || _a === void 0 ? void 0 : _a.succeeded)) {
  1432. throw ERROR_FACTORY.create("recaptcha-error" /* AppCheckError.RECAPTCHA_ERROR */);
  1433. }
  1434. _d.label = 2;
  1435. case 2:
  1436. _d.trys.push([2, 4, , 5]);
  1437. return [4 /*yield*/, exchangeToken(getExchangeRecaptchaEnterpriseTokenRequest(this._app, attestedClaimsToken), this._heartbeatServiceProvider)];
  1438. case 3:
  1439. result = _d.sent();
  1440. return [3 /*break*/, 5];
  1441. case 4:
  1442. e_2 = _d.sent();
  1443. if ((_b = e_2.code) === null || _b === void 0 ? void 0 : _b.includes("fetch-status-error" /* AppCheckError.FETCH_STATUS_ERROR */)) {
  1444. this._throttleData = setBackoff(Number((_c = e_2.customData) === null || _c === void 0 ? void 0 : _c.httpStatus), this._throttleData);
  1445. throw ERROR_FACTORY.create("throttled" /* AppCheckError.THROTTLED */, {
  1446. time: getDurationString(this._throttleData.allowRequestsAfter - Date.now()),
  1447. httpStatus: this._throttleData.httpStatus
  1448. });
  1449. }
  1450. else {
  1451. throw e_2;
  1452. }
  1453. case 5:
  1454. // If successful, clear throttle data.
  1455. this._throttleData = null;
  1456. return [2 /*return*/, result];
  1457. }
  1458. });
  1459. });
  1460. };
  1461. /**
  1462. * @internal
  1463. */
  1464. ReCaptchaEnterpriseProvider.prototype.initialize = function (app$1) {
  1465. this._app = app$1;
  1466. this._heartbeatServiceProvider = app._getProvider(app$1, 'heartbeat');
  1467. initializeEnterprise(app$1, this._siteKey).catch(function () {
  1468. /* we don't care about the initialization result */
  1469. });
  1470. };
  1471. /**
  1472. * @internal
  1473. */
  1474. ReCaptchaEnterpriseProvider.prototype.isEqual = function (otherProvider) {
  1475. if (otherProvider instanceof ReCaptchaEnterpriseProvider) {
  1476. return this._siteKey === otherProvider._siteKey;
  1477. }
  1478. else {
  1479. return false;
  1480. }
  1481. };
  1482. return ReCaptchaEnterpriseProvider;
  1483. }());
  1484. /**
  1485. * Custom provider class.
  1486. * @public
  1487. */
  1488. var CustomProvider = /** @class */ (function () {
  1489. function CustomProvider(_customProviderOptions) {
  1490. this._customProviderOptions = _customProviderOptions;
  1491. }
  1492. /**
  1493. * @internal
  1494. */
  1495. CustomProvider.prototype.getToken = function () {
  1496. return tslib.__awaiter(this, void 0, void 0, function () {
  1497. var customToken, issuedAtTimeSeconds, issuedAtTimeMillis;
  1498. return tslib.__generator(this, function (_a) {
  1499. switch (_a.label) {
  1500. case 0: return [4 /*yield*/, this._customProviderOptions.getToken()];
  1501. case 1:
  1502. customToken = _a.sent();
  1503. issuedAtTimeSeconds = util.issuedAtTime(customToken.token);
  1504. issuedAtTimeMillis = issuedAtTimeSeconds !== null &&
  1505. issuedAtTimeSeconds < Date.now() &&
  1506. issuedAtTimeSeconds > 0
  1507. ? issuedAtTimeSeconds * 1000
  1508. : Date.now();
  1509. return [2 /*return*/, tslib.__assign(tslib.__assign({}, customToken), { issuedAtTimeMillis: issuedAtTimeMillis })];
  1510. }
  1511. });
  1512. });
  1513. };
  1514. /**
  1515. * @internal
  1516. */
  1517. CustomProvider.prototype.initialize = function (app) {
  1518. this._app = app;
  1519. };
  1520. /**
  1521. * @internal
  1522. */
  1523. CustomProvider.prototype.isEqual = function (otherProvider) {
  1524. if (otherProvider instanceof CustomProvider) {
  1525. return (this._customProviderOptions.getToken.toString() ===
  1526. otherProvider._customProviderOptions.getToken.toString());
  1527. }
  1528. else {
  1529. return false;
  1530. }
  1531. };
  1532. return CustomProvider;
  1533. }());
  1534. /**
  1535. * Set throttle data to block requests until after a certain time
  1536. * depending on the failed request's status code.
  1537. * @param httpStatus - Status code of failed request.
  1538. * @param throttleData - `ThrottleData` object containing previous throttle
  1539. * data state.
  1540. * @returns Data about current throttle state and expiration time.
  1541. */
  1542. function setBackoff(httpStatus, throttleData) {
  1543. /**
  1544. * Block retries for 1 day for the following error codes:
  1545. *
  1546. * 404: Likely malformed URL.
  1547. *
  1548. * 403:
  1549. * - Attestation failed
  1550. * - Wrong API key
  1551. * - Project deleted
  1552. */
  1553. if (httpStatus === 404 || httpStatus === 403) {
  1554. return {
  1555. backoffCount: 1,
  1556. allowRequestsAfter: Date.now() + ONE_DAY,
  1557. httpStatus: httpStatus
  1558. };
  1559. }
  1560. else {
  1561. /**
  1562. * For all other error codes, the time when it is ok to retry again
  1563. * is based on exponential backoff.
  1564. */
  1565. var backoffCount = throttleData ? throttleData.backoffCount : 0;
  1566. var backoffMillis = util.calculateBackoffMillis(backoffCount, 1000, 2);
  1567. return {
  1568. backoffCount: backoffCount + 1,
  1569. allowRequestsAfter: Date.now() + backoffMillis,
  1570. httpStatus: httpStatus
  1571. };
  1572. }
  1573. }
  1574. function throwIfThrottled(throttleData) {
  1575. if (throttleData) {
  1576. if (Date.now() - throttleData.allowRequestsAfter <= 0) {
  1577. // If before, throw.
  1578. throw ERROR_FACTORY.create("throttled" /* AppCheckError.THROTTLED */, {
  1579. time: getDurationString(throttleData.allowRequestsAfter - Date.now()),
  1580. httpStatus: throttleData.httpStatus
  1581. });
  1582. }
  1583. }
  1584. }
  1585. /**
  1586. * @license
  1587. * Copyright 2020 Google LLC
  1588. *
  1589. * Licensed under the Apache License, Version 2.0 (the "License");
  1590. * you may not use this file except in compliance with the License.
  1591. * You may obtain a copy of the License at
  1592. *
  1593. * http://www.apache.org/licenses/LICENSE-2.0
  1594. *
  1595. * Unless required by applicable law or agreed to in writing, software
  1596. * distributed under the License is distributed on an "AS IS" BASIS,
  1597. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  1598. * See the License for the specific language governing permissions and
  1599. * limitations under the License.
  1600. */
  1601. /**
  1602. * Activate App Check for the given app. Can be called only once per app.
  1603. * @param app - the {@link @firebase/app#FirebaseApp} to activate App Check for
  1604. * @param options - App Check initialization options
  1605. * @public
  1606. */
  1607. function initializeAppCheck(app$1, options) {
  1608. if (app$1 === void 0) { app$1 = app.getApp(); }
  1609. app$1 = util.getModularInstance(app$1);
  1610. var provider = app._getProvider(app$1, 'app-check');
  1611. // Ensure initializeDebugMode() is only called once.
  1612. if (!getDebugState().initialized) {
  1613. initializeDebugMode();
  1614. }
  1615. // Log a message containing the debug token when `initializeAppCheck()`
  1616. // is called in debug mode.
  1617. if (isDebugMode()) {
  1618. // Do not block initialization to get the token for the message.
  1619. void getDebugToken().then(function (token) {
  1620. // Not using logger because I don't think we ever want this accidentally hidden.
  1621. return console.log("App Check debug token: ".concat(token, ". You will need to add it to your app's App Check settings in the Firebase console for it to work."));
  1622. });
  1623. }
  1624. if (provider.isInitialized()) {
  1625. var existingInstance = provider.getImmediate();
  1626. var initialOptions = provider.getOptions();
  1627. if (initialOptions.isTokenAutoRefreshEnabled ===
  1628. options.isTokenAutoRefreshEnabled &&
  1629. initialOptions.provider.isEqual(options.provider)) {
  1630. return existingInstance;
  1631. }
  1632. else {
  1633. throw ERROR_FACTORY.create("already-initialized" /* AppCheckError.ALREADY_INITIALIZED */, {
  1634. appName: app$1.name
  1635. });
  1636. }
  1637. }
  1638. var appCheck = provider.initialize({ options: options });
  1639. _activate(app$1, options.provider, options.isTokenAutoRefreshEnabled);
  1640. // If isTokenAutoRefreshEnabled is false, do not send any requests to the
  1641. // exchange endpoint without an explicit call from the user either directly
  1642. // or through another Firebase library (storage, functions, etc.)
  1643. if (getStateReference(app$1).isTokenAutoRefreshEnabled) {
  1644. // Adding a listener will start the refresher and fetch a token if needed.
  1645. // This gets a token ready and prevents a delay when an internal library
  1646. // requests the token.
  1647. // Listener function does not need to do anything, its base functionality
  1648. // of calling getToken() already fetches token and writes it to memory/storage.
  1649. addTokenListener(appCheck, "INTERNAL" /* ListenerType.INTERNAL */, function () { });
  1650. }
  1651. return appCheck;
  1652. }
  1653. /**
  1654. * Activate App Check
  1655. * @param app - Firebase app to activate App Check for.
  1656. * @param provider - reCAPTCHA v3 provider or
  1657. * custom token provider.
  1658. * @param isTokenAutoRefreshEnabled - If true, the SDK automatically
  1659. * refreshes App Check tokens as needed. If undefined, defaults to the
  1660. * value of `app.automaticDataCollectionEnabled`, which defaults to
  1661. * false and can be set in the app config.
  1662. */
  1663. function _activate(app, provider, isTokenAutoRefreshEnabled) {
  1664. // Create an entry in the APP_CHECK_STATES map. Further changes should
  1665. // directly mutate this object.
  1666. var state = setInitialState(app, tslib.__assign({}, DEFAULT_STATE));
  1667. state.activated = true;
  1668. state.provider = provider; // Read cached token from storage if it exists and store it in memory.
  1669. state.cachedTokenPromise = readTokenFromStorage(app).then(function (cachedToken) {
  1670. if (cachedToken && isValid(cachedToken)) {
  1671. state.token = cachedToken;
  1672. // notify all listeners with the cached token
  1673. notifyTokenListeners(app, { token: cachedToken.token });
  1674. }
  1675. return cachedToken;
  1676. });
  1677. // Use value of global `automaticDataCollectionEnabled` (which
  1678. // itself defaults to false if not specified in config) if
  1679. // `isTokenAutoRefreshEnabled` param was not provided by user.
  1680. state.isTokenAutoRefreshEnabled =
  1681. isTokenAutoRefreshEnabled === undefined
  1682. ? app.automaticDataCollectionEnabled
  1683. : isTokenAutoRefreshEnabled;
  1684. state.provider.initialize(app);
  1685. }
  1686. /**
  1687. * Set whether App Check will automatically refresh tokens as needed.
  1688. *
  1689. * @param appCheckInstance - The App Check service instance.
  1690. * @param isTokenAutoRefreshEnabled - If true, the SDK automatically
  1691. * refreshes App Check tokens as needed. This overrides any value set
  1692. * during `initializeAppCheck()`.
  1693. * @public
  1694. */
  1695. function setTokenAutoRefreshEnabled(appCheckInstance, isTokenAutoRefreshEnabled) {
  1696. var app = appCheckInstance.app;
  1697. var state = getStateReference(app);
  1698. // This will exist if any product libraries have called
  1699. // `addTokenListener()`
  1700. if (state.tokenRefresher) {
  1701. if (isTokenAutoRefreshEnabled === true) {
  1702. state.tokenRefresher.start();
  1703. }
  1704. else {
  1705. state.tokenRefresher.stop();
  1706. }
  1707. }
  1708. state.isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled;
  1709. }
  1710. /**
  1711. * Get the current App Check token. Attaches to the most recent
  1712. * in-flight request if one is present. Returns null if no token
  1713. * is present and no token requests are in-flight.
  1714. *
  1715. * @param appCheckInstance - The App Check service instance.
  1716. * @param forceRefresh - If true, will always try to fetch a fresh token.
  1717. * If false, will use a cached token if found in storage.
  1718. * @public
  1719. */
  1720. function getToken(appCheckInstance, forceRefresh) {
  1721. return tslib.__awaiter(this, void 0, void 0, function () {
  1722. var result;
  1723. return tslib.__generator(this, function (_a) {
  1724. switch (_a.label) {
  1725. case 0: return [4 /*yield*/, getToken$2(appCheckInstance, forceRefresh)];
  1726. case 1:
  1727. result = _a.sent();
  1728. if (result.error) {
  1729. throw result.error;
  1730. }
  1731. return [2 /*return*/, { token: result.token }];
  1732. }
  1733. });
  1734. });
  1735. }
  1736. /**
  1737. * Requests a Firebase App Check token. This method should be used
  1738. * only if you need to authorize requests to a non-Firebase backend.
  1739. *
  1740. * Returns limited-use tokens that are intended for use with your
  1741. * non-Firebase backend endpoints that are protected with
  1742. * <a href="https://firebase.google.com/docs/app-check/custom-resource-backend#replay-protection">
  1743. * Replay Protection</a>. This method
  1744. * does not affect the token generation behavior of the
  1745. * #getAppCheckToken() method.
  1746. *
  1747. * @param appCheckInstance - The App Check service instance.
  1748. * @returns The limited use token.
  1749. * @public
  1750. */
  1751. function getLimitedUseToken(appCheckInstance) {
  1752. return getLimitedUseToken$1(appCheckInstance);
  1753. }
  1754. /**
  1755. * Wraps `addTokenListener`/`removeTokenListener` methods in an `Observer`
  1756. * pattern for public use.
  1757. */
  1758. function onTokenChanged(appCheckInstance, onNextOrObserver, onError,
  1759. /**
  1760. * NOTE: Although an `onCompletion` callback can be provided, it will
  1761. * never be called because the token stream is never-ending.
  1762. * It is added only for API consistency with the observer pattern, which
  1763. * we follow in JS APIs.
  1764. */
  1765. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  1766. onCompletion) {
  1767. var nextFn = function () { };
  1768. var errorFn = function () { };
  1769. if (onNextOrObserver.next != null) {
  1770. nextFn = onNextOrObserver.next.bind(onNextOrObserver);
  1771. }
  1772. else {
  1773. nextFn = onNextOrObserver;
  1774. }
  1775. if (onNextOrObserver.error != null) {
  1776. errorFn = onNextOrObserver.error.bind(onNextOrObserver);
  1777. }
  1778. else if (onError) {
  1779. errorFn = onError;
  1780. }
  1781. addTokenListener(appCheckInstance, "EXTERNAL" /* ListenerType.EXTERNAL */, nextFn, errorFn);
  1782. return function () { return removeTokenListener(appCheckInstance.app, nextFn); };
  1783. }
  1784. /**
  1785. * Firebase App Check
  1786. *
  1787. * @packageDocumentation
  1788. */
  1789. var APP_CHECK_NAME = 'app-check';
  1790. var APP_CHECK_NAME_INTERNAL = 'app-check-internal';
  1791. function registerAppCheck() {
  1792. // The public interface
  1793. app._registerComponent(new component.Component(APP_CHECK_NAME, function (container) {
  1794. // getImmediate for FirebaseApp will always succeed
  1795. var app = container.getProvider('app').getImmediate();
  1796. var heartbeatServiceProvider = container.getProvider('heartbeat');
  1797. return factory(app, heartbeatServiceProvider);
  1798. }, "PUBLIC" /* ComponentType.PUBLIC */)
  1799. .setInstantiationMode("EXPLICIT" /* InstantiationMode.EXPLICIT */)
  1800. /**
  1801. * Initialize app-check-internal after app-check is initialized to make AppCheck available to
  1802. * other Firebase SDKs
  1803. */
  1804. .setInstanceCreatedCallback(function (container, _identifier, _appcheckService) {
  1805. container.getProvider(APP_CHECK_NAME_INTERNAL).initialize();
  1806. }));
  1807. // The internal interface used by other Firebase products
  1808. app._registerComponent(new component.Component(APP_CHECK_NAME_INTERNAL, function (container) {
  1809. var appCheck = container.getProvider('app-check').getImmediate();
  1810. return internalFactory(appCheck);
  1811. }, "PUBLIC" /* ComponentType.PUBLIC */).setInstantiationMode("EXPLICIT" /* InstantiationMode.EXPLICIT */));
  1812. app.registerVersion(name, version);
  1813. }
  1814. registerAppCheck();
  1815. exports.CustomProvider = CustomProvider;
  1816. exports.ReCaptchaEnterpriseProvider = ReCaptchaEnterpriseProvider;
  1817. exports.ReCaptchaV3Provider = ReCaptchaV3Provider;
  1818. exports.getLimitedUseToken = getLimitedUseToken;
  1819. exports.getToken = getToken;
  1820. exports.initializeAppCheck = initializeAppCheck;
  1821. exports.onTokenChanged = onTokenChanged;
  1822. exports.setTokenAutoRefreshEnabled = setTokenAutoRefreshEnabled;
  1823. //# sourceMappingURL=index.cjs.js.map