diff options
Diffstat (limited to 'frontend-old/node_modules/@firebase/app-check/dist/index.cjs.js')
| -rw-r--r-- | frontend-old/node_modules/@firebase/app-check/dist/index.cjs.js | 1704 |
1 files changed, 0 insertions, 1704 deletions
diff --git a/frontend-old/node_modules/@firebase/app-check/dist/index.cjs.js b/frontend-old/node_modules/@firebase/app-check/dist/index.cjs.js deleted file mode 100644 index 340b411..0000000 --- a/frontend-old/node_modules/@firebase/app-check/dist/index.cjs.js +++ /dev/null @@ -1,1704 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { value: true }); - -var app = require('@firebase/app'); -var component = require('@firebase/component'); -var util = require('@firebase/util'); -var logger$1 = require('@firebase/logger'); - -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -const APP_CHECK_STATES = new Map(); -const DEFAULT_STATE = { - activated: false, - tokenObservers: [] -}; -const DEBUG_STATE = { - initialized: false, - enabled: false -}; -/** - * Gets a reference to the state object. - */ -function getStateReference(app) { - return APP_CHECK_STATES.get(app) || { ...DEFAULT_STATE }; -} -/** - * Set once on initialization. The map should hold the same reference to the - * same object until this entry is deleted. - */ -function setInitialState(app, state) { - APP_CHECK_STATES.set(app, state); - return APP_CHECK_STATES.get(app); -} -function getDebugState() { - return DEBUG_STATE; -} - -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -const BASE_ENDPOINT = 'https://content-firebaseappcheck.googleapis.com/v1'; -const EXCHANGE_RECAPTCHA_TOKEN_METHOD = 'exchangeRecaptchaV3Token'; -const EXCHANGE_RECAPTCHA_ENTERPRISE_TOKEN_METHOD = 'exchangeRecaptchaEnterpriseToken'; -const EXCHANGE_DEBUG_TOKEN_METHOD = 'exchangeDebugToken'; -const TOKEN_REFRESH_TIME = { - /** - * The offset time before token natural expiration to run the refresh. - * This is currently 5 minutes. - */ - OFFSET_DURATION: 5 * 60 * 1000, - /** - * This is the first retrial wait after an error. This is currently - * 30 seconds. - */ - RETRIAL_MIN_WAIT: 30 * 1000, - /** - * This is the maximum retrial wait, currently 16 minutes. - */ - RETRIAL_MAX_WAIT: 16 * 60 * 1000 -}; -/** - * One day in millis, for certain error code backoffs. - */ -const ONE_DAY = 24 * 60 * 60 * 1000; - -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * Port from auth proactiverefresh.js - * - */ -// TODO: move it to @firebase/util? -// TODO: allow to config whether refresh should happen in the background -class Refresher { - constructor(operation, retryPolicy, getWaitDuration, lowerBound, upperBound) { - this.operation = operation; - this.retryPolicy = retryPolicy; - this.getWaitDuration = getWaitDuration; - this.lowerBound = lowerBound; - this.upperBound = upperBound; - this.pending = null; - this.nextErrorWaitInterval = lowerBound; - if (lowerBound > upperBound) { - throw new Error('Proactive refresh lower bound greater than upper bound!'); - } - } - start() { - this.nextErrorWaitInterval = this.lowerBound; - this.process(true).catch(() => { - /* we don't care about the result */ - }); - } - stop() { - if (this.pending) { - this.pending.reject('cancelled'); - this.pending = null; - } - } - isRunning() { - return !!this.pending; - } - async process(hasSucceeded) { - this.stop(); - try { - this.pending = new util.Deferred(); - this.pending.promise.catch(_e => { - /* ignore */ - }); - await sleep(this.getNextRun(hasSucceeded)); - // Why do we resolve a promise, then immediate wait for it? - // We do it to make the promise chain cancellable. - // We can call stop() which rejects the promise before the following line execute, which makes - // the code jump to the catch block. - // TODO: unit test this - this.pending.resolve(); - await this.pending.promise; - this.pending = new util.Deferred(); - this.pending.promise.catch(_e => { - /* ignore */ - }); - await this.operation(); - this.pending.resolve(); - await this.pending.promise; - this.process(true).catch(() => { - /* we don't care about the result */ - }); - } - catch (error) { - if (this.retryPolicy(error)) { - this.process(false).catch(() => { - /* we don't care about the result */ - }); - } - else { - this.stop(); - } - } - } - getNextRun(hasSucceeded) { - if (hasSucceeded) { - // If last operation succeeded, reset next error wait interval and return - // the default wait duration. - this.nextErrorWaitInterval = this.lowerBound; - // Return typical wait duration interval after a successful operation. - return this.getWaitDuration(); - } - else { - // Get next error wait interval. - const currentErrorWaitInterval = this.nextErrorWaitInterval; - // Double interval for next consecutive error. - this.nextErrorWaitInterval *= 2; - // Make sure next wait interval does not exceed the maximum upper bound. - if (this.nextErrorWaitInterval > this.upperBound) { - this.nextErrorWaitInterval = this.upperBound; - } - return currentErrorWaitInterval; - } - } -} -function sleep(ms) { - return new Promise(resolve => { - setTimeout(resolve, ms); - }); -} - -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -const ERRORS = { - ["already-initialized" /* AppCheckError.ALREADY_INITIALIZED */]: 'You have already called initializeAppCheck() for FirebaseApp {$appName} with ' + - 'different options. To avoid this error, call initializeAppCheck() with the ' + - 'same options as when it was originally called. This will return the ' + - 'already initialized instance.', - ["use-before-activation" /* AppCheckError.USE_BEFORE_ACTIVATION */]: 'App Check is being used before initializeAppCheck() is called for FirebaseApp {$appName}. ' + - 'Call initializeAppCheck() before instantiating other Firebase services.', - ["fetch-network-error" /* AppCheckError.FETCH_NETWORK_ERROR */]: 'Fetch failed to connect to a network. Check Internet connection. ' + - 'Original error: {$originalErrorMessage}.', - ["fetch-parse-error" /* AppCheckError.FETCH_PARSE_ERROR */]: 'Fetch client could not parse response.' + - ' Original error: {$originalErrorMessage}.', - ["fetch-status-error" /* AppCheckError.FETCH_STATUS_ERROR */]: 'Fetch server returned an HTTP error status. HTTP status: {$httpStatus}.', - ["storage-open" /* AppCheckError.STORAGE_OPEN */]: 'Error thrown when opening storage. Original error: {$originalErrorMessage}.', - ["storage-get" /* AppCheckError.STORAGE_GET */]: 'Error thrown when reading from storage. Original error: {$originalErrorMessage}.', - ["storage-set" /* AppCheckError.STORAGE_WRITE */]: 'Error thrown when writing to storage. Original error: {$originalErrorMessage}.', - ["recaptcha-error" /* AppCheckError.RECAPTCHA_ERROR */]: 'ReCAPTCHA error.', - ["initial-throttle" /* AppCheckError.INITIAL_THROTTLE */]: `{$httpStatus} error. Attempts allowed again after {$time}`, - ["throttled" /* AppCheckError.THROTTLED */]: `Requests throttled due to previous {$httpStatus} error. Attempts allowed again after {$time}` -}; -const ERROR_FACTORY = new util.ErrorFactory('appCheck', 'AppCheck', ERRORS); - -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -function getRecaptcha(isEnterprise = false) { - if (isEnterprise) { - return self.grecaptcha?.enterprise; - } - return self.grecaptcha; -} -function ensureActivated(app) { - if (!getStateReference(app).activated) { - throw ERROR_FACTORY.create("use-before-activation" /* AppCheckError.USE_BEFORE_ACTIVATION */, { - appName: app.name - }); - } -} -function getDurationString(durationInMillis) { - const totalSeconds = Math.round(durationInMillis / 1000); - const days = Math.floor(totalSeconds / (3600 * 24)); - const hours = Math.floor((totalSeconds - days * 3600 * 24) / 3600); - const minutes = Math.floor((totalSeconds - days * 3600 * 24 - hours * 3600) / 60); - const seconds = totalSeconds - days * 3600 * 24 - hours * 3600 - minutes * 60; - let result = ''; - if (days) { - result += pad(days) + 'd:'; - } - if (hours) { - result += pad(hours) + 'h:'; - } - result += pad(minutes) + 'm:' + pad(seconds) + 's'; - return result; -} -function pad(value) { - if (value === 0) { - return '00'; - } - return value >= 10 ? value.toString() : '0' + value; -} - -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -async function exchangeToken({ url, body }, heartbeatServiceProvider) { - const headers = { - 'Content-Type': 'application/json' - }; - // If heartbeat service exists, add heartbeat header string to the header. - const heartbeatService = heartbeatServiceProvider.getImmediate({ - optional: true - }); - if (heartbeatService) { - const heartbeatsHeader = await heartbeatService.getHeartbeatsHeader(); - if (heartbeatsHeader) { - headers['X-Firebase-Client'] = heartbeatsHeader; - } - } - const options = { - method: 'POST', - body: JSON.stringify(body), - headers - }; - let response; - try { - response = await fetch(url, options); - } - catch (originalError) { - throw ERROR_FACTORY.create("fetch-network-error" /* AppCheckError.FETCH_NETWORK_ERROR */, { - originalErrorMessage: originalError?.message - }); - } - if (response.status !== 200) { - throw ERROR_FACTORY.create("fetch-status-error" /* AppCheckError.FETCH_STATUS_ERROR */, { - httpStatus: response.status - }); - } - let responseBody; - try { - // JSON parsing throws SyntaxError if the response body isn't a JSON string. - responseBody = await response.json(); - } - catch (originalError) { - throw ERROR_FACTORY.create("fetch-parse-error" /* AppCheckError.FETCH_PARSE_ERROR */, { - originalErrorMessage: originalError?.message - }); - } - // Protobuf duration format. - // https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/Duration - const match = responseBody.ttl.match(/^([\d.]+)(s)$/); - if (!match || !match[2] || isNaN(Number(match[1]))) { - throw ERROR_FACTORY.create("fetch-parse-error" /* AppCheckError.FETCH_PARSE_ERROR */, { - originalErrorMessage: `ttl field (timeToLive) is not in standard Protobuf Duration ` + - `format: ${responseBody.ttl}` - }); - } - const timeToLiveAsNumber = Number(match[1]) * 1000; - const now = Date.now(); - return { - token: responseBody.token, - expireTimeMillis: now + timeToLiveAsNumber, - issuedAtTimeMillis: now - }; -} -function getExchangeRecaptchaV3TokenRequest(app, reCAPTCHAToken) { - const { projectId, appId, apiKey } = app.options; - return { - url: `${BASE_ENDPOINT}/projects/${projectId}/apps/${appId}:${EXCHANGE_RECAPTCHA_TOKEN_METHOD}?key=${apiKey}`, - body: { - 'recaptcha_v3_token': reCAPTCHAToken - } - }; -} -function getExchangeRecaptchaEnterpriseTokenRequest(app, reCAPTCHAToken) { - const { projectId, appId, apiKey } = app.options; - return { - url: `${BASE_ENDPOINT}/projects/${projectId}/apps/${appId}:${EXCHANGE_RECAPTCHA_ENTERPRISE_TOKEN_METHOD}?key=${apiKey}`, - body: { - 'recaptcha_enterprise_token': reCAPTCHAToken - } - }; -} -function getExchangeDebugTokenRequest(app, debugToken) { - const { projectId, appId, apiKey } = app.options; - return { - url: `${BASE_ENDPOINT}/projects/${projectId}/apps/${appId}:${EXCHANGE_DEBUG_TOKEN_METHOD}?key=${apiKey}`, - body: { - // eslint-disable-next-line - debug_token: debugToken - } - }; -} - -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -const DB_NAME = 'firebase-app-check-database'; -const DB_VERSION = 1; -const STORE_NAME = 'firebase-app-check-store'; -const DEBUG_TOKEN_KEY = 'debug-token'; -let dbPromise = null; -function getDBPromise() { - if (dbPromise) { - return dbPromise; - } - dbPromise = new Promise((resolve, reject) => { - try { - const request = indexedDB.open(DB_NAME, DB_VERSION); - request.onsuccess = event => { - resolve(event.target.result); - }; - request.onerror = event => { - reject(ERROR_FACTORY.create("storage-open" /* AppCheckError.STORAGE_OPEN */, { - originalErrorMessage: event.target.error?.message - })); - }; - request.onupgradeneeded = event => { - const db = event.target.result; - // We don't use 'break' in this switch statement, the fall-through - // behavior is what we want, because if there are multiple versions between - // the old version and the current version, we want ALL the migrations - // that correspond to those versions to run, not only the last one. - // eslint-disable-next-line default-case - switch (event.oldVersion) { - case 0: - db.createObjectStore(STORE_NAME, { - keyPath: 'compositeKey' - }); - } - }; - } - catch (e) { - reject(ERROR_FACTORY.create("storage-open" /* AppCheckError.STORAGE_OPEN */, { - originalErrorMessage: e?.message - })); - } - }); - return dbPromise; -} -function readTokenFromIndexedDB(app) { - return read(computeKey(app)); -} -function writeTokenToIndexedDB(app, token) { - return write(computeKey(app), token); -} -function writeDebugTokenToIndexedDB(token) { - return write(DEBUG_TOKEN_KEY, token); -} -function readDebugTokenFromIndexedDB() { - return read(DEBUG_TOKEN_KEY); -} -async function write(key, value) { - const db = await getDBPromise(); - const transaction = db.transaction(STORE_NAME, 'readwrite'); - const store = transaction.objectStore(STORE_NAME); - const request = store.put({ - compositeKey: key, - value - }); - return new Promise((resolve, reject) => { - request.onsuccess = _event => { - resolve(); - }; - transaction.onerror = event => { - reject(ERROR_FACTORY.create("storage-set" /* AppCheckError.STORAGE_WRITE */, { - originalErrorMessage: event.target.error?.message - })); - }; - }); -} -async function read(key) { - const db = await getDBPromise(); - const transaction = db.transaction(STORE_NAME, 'readonly'); - const store = transaction.objectStore(STORE_NAME); - const request = store.get(key); - return new Promise((resolve, reject) => { - request.onsuccess = event => { - const result = event.target.result; - if (result) { - resolve(result.value); - } - else { - resolve(undefined); - } - }; - transaction.onerror = event => { - reject(ERROR_FACTORY.create("storage-get" /* AppCheckError.STORAGE_GET */, { - originalErrorMessage: event.target.error?.message - })); - }; - }); -} -function computeKey(app) { - return `${app.options.appId}-${app.name}`; -} - -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -const logger = new logger$1.Logger('@firebase/app-check'); - -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * Always resolves. In case of an error reading from indexeddb, resolve with undefined - */ -async function readTokenFromStorage(app) { - if (util.isIndexedDBAvailable()) { - let token = undefined; - try { - token = await readTokenFromIndexedDB(app); - } - catch (e) { - // swallow the error and return undefined - logger.warn(`Failed to read token from IndexedDB. Error: ${e}`); - } - return token; - } - return undefined; -} -/** - * Always resolves. In case of an error writing to indexeddb, print a warning and resolve the promise - */ -function writeTokenToStorage(app, token) { - if (util.isIndexedDBAvailable()) { - return writeTokenToIndexedDB(app, token).catch(e => { - // swallow the error and resolve the promise - logger.warn(`Failed to write token to IndexedDB. Error: ${e}`); - }); - } - return Promise.resolve(); -} -async function readOrCreateDebugTokenFromStorage() { - /** - * Theoretically race condition can happen if we read, then write in 2 separate transactions. - * But it won't happen here, because this function will be called exactly once. - */ - let existingDebugToken = undefined; - try { - existingDebugToken = await readDebugTokenFromIndexedDB(); - } - catch (_e) { - // failed to read from indexeddb. We assume there is no existing debug token, and generate a new one. - } - if (!existingDebugToken) { - // create a new debug token - // This function is only available in secure contexts. See https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts - const newToken = crypto.randomUUID(); - // We don't need to block on writing to indexeddb - // In case persistence failed, a new debug token will be generated every time the page is refreshed. - // It renders the debug token useless because you have to manually register(whitelist) the new token in the firebase console again and again. - // If you see this error trying to use debug token, it probably means you are using a browser that doesn't support indexeddb. - // You should switch to a different browser that supports indexeddb - writeDebugTokenToIndexedDB(newToken).catch(e => logger.warn(`Failed to persist debug token to IndexedDB. Error: ${e}`)); - return newToken; - } - else { - return existingDebugToken; - } -} - -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -function isDebugMode() { - const debugState = getDebugState(); - return debugState.enabled; -} -async function getDebugToken() { - const state = getDebugState(); - if (state.enabled && state.token) { - return state.token.promise; - } - else { - // should not happen! - throw Error(` - Can't get debug token in production mode. - `); - } -} -function initializeDebugMode() { - const globals = util.getGlobal(); - const debugState = getDebugState(); - // Set to true if this function has been called, whether or not - // it enabled debug mode. - debugState.initialized = true; - if (typeof globals.FIREBASE_APPCHECK_DEBUG_TOKEN !== 'string' && - globals.FIREBASE_APPCHECK_DEBUG_TOKEN !== true) { - return; - } - debugState.enabled = true; - const deferredToken = new util.Deferred(); - debugState.token = deferredToken; - if (typeof globals.FIREBASE_APPCHECK_DEBUG_TOKEN === 'string') { - deferredToken.resolve(globals.FIREBASE_APPCHECK_DEBUG_TOKEN); - } - else { - deferredToken.resolve(readOrCreateDebugTokenFromStorage()); - } -} - -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -// Initial hardcoded value agreed upon across platforms for initial launch. -// Format left open for possible dynamic error values and other fields in the future. -const defaultTokenErrorData = { error: 'UNKNOWN_ERROR' }; -/** - * Stringify and base64 encode token error data. - * - * @param tokenError Error data, currently hardcoded. - */ -function formatDummyToken(tokenErrorData) { - return util.base64.encodeString(JSON.stringify(tokenErrorData), - /* webSafe= */ false); -} -/** - * This function always resolves. - * The result will contain an error field if there is any error. - * In case there is an error, the token field in the result will be populated with a dummy value - */ -async function getToken$2(appCheck, forceRefresh = false, shouldLogErrors = false) { - const app = appCheck.app; - ensureActivated(app); - const state = getStateReference(app); - /** - * First check if there is a token in memory from a previous `getToken()` call. - */ - let token = state.token; - let error = undefined; - /** - * If an invalid token was found in memory, clear token from - * memory and unset the local variable `token`. - */ - if (token && !isValid(token)) { - state.token = undefined; - token = undefined; - } - /** - * If there is no valid token in memory, try to load token from indexedDB. - */ - if (!token) { - // cachedTokenPromise contains the token found in IndexedDB or undefined if not found. - const cachedToken = await state.cachedTokenPromise; - if (cachedToken) { - if (isValid(cachedToken)) { - token = cachedToken; - } - else { - // If there was an invalid token in the indexedDB cache, clear it. - await writeTokenToStorage(app, undefined); - } - } - } - // Return the cached token (from either memory or indexedDB) if it's valid - if (!forceRefresh && token && isValid(token)) { - return { - token: token.token - }; - } - // Only set to true if this `getToken()` call is making the actual - // REST call to the exchange endpoint, versus waiting for an already - // in-flight call (see debug and regular exchange endpoint paths below) - let shouldCallListeners = false; - /** - * DEBUG MODE - * If debug mode is set, and there is no cached token, fetch a new App - * Check token using the debug token, and return it directly. - */ - if (isDebugMode()) { - try { - // Avoid making another call to the exchange endpoint if one is in flight. - if (!state.exchangeTokenPromise) { - state.exchangeTokenPromise = exchangeToken(getExchangeDebugTokenRequest(app, await getDebugToken()), appCheck.heartbeatServiceProvider).finally(() => { - // Clear promise when settled - either resolved or rejected. - state.exchangeTokenPromise = undefined; - }); - shouldCallListeners = true; - } - const tokenFromDebugExchange = await state.exchangeTokenPromise; - // Write debug token to indexedDB. - await writeTokenToStorage(app, tokenFromDebugExchange); - // Write debug token to state. - state.token = tokenFromDebugExchange; - return { token: tokenFromDebugExchange.token }; - } - catch (e) { - if (e.code === `appCheck/${"throttled" /* AppCheckError.THROTTLED */}` || - e.code === - `appCheck/${"initial-throttle" /* AppCheckError.INITIAL_THROTTLE */}`) { - // Warn if throttled, but do not treat it as an error. - logger.warn(e.message); - } - else if (shouldLogErrors) { - logger.error(e); - } - // Return dummy token and error - return makeDummyTokenResult(e); - } - } - /** - * There are no valid tokens in memory or indexedDB and we are not in - * debug mode. - * Request a new token from the exchange endpoint. - */ - try { - // Avoid making another call to the exchange endpoint if one is in flight. - if (!state.exchangeTokenPromise) { - // state.provider is populated in initializeAppCheck() - // ensureActivated() at the top of this function checks that - // initializeAppCheck() has been called. - state.exchangeTokenPromise = state.provider.getToken().finally(() => { - // Clear promise when settled - either resolved or rejected. - state.exchangeTokenPromise = undefined; - }); - shouldCallListeners = true; - } - token = await getStateReference(app).exchangeTokenPromise; - } - catch (e) { - if (e.code === `appCheck/${"throttled" /* AppCheckError.THROTTLED */}` || - e.code === `appCheck/${"initial-throttle" /* AppCheckError.INITIAL_THROTTLE */}`) { - // Warn if throttled, but do not treat it as an error. - logger.warn(e.message); - } - else if (shouldLogErrors) { - logger.error(e); - } - // Always save error to be added to dummy token. - error = e; - } - let interopTokenResult; - if (!token) { - // If token is undefined, there must be an error. - // Return a dummy token along with the error. - interopTokenResult = makeDummyTokenResult(error); - } - else if (error) { - if (isValid(token)) { - // It's also possible a valid token exists, but there's also an error. - // (Such as if the token is almost expired, tries to refresh, and - // the exchange request fails.) - // We add a special error property here so that the refresher will - // count this as a failed attempt and use the backoff instead of - // retrying repeatedly with no delay, but any 3P listeners will not - // be hindered in getting the still-valid token. - interopTokenResult = { - token: token.token, - internalError: error - }; - } - else { - // No invalid tokens should make it to this step. Memory and cached tokens - // are checked. Other tokens are from fresh exchanges. But just in case. - interopTokenResult = makeDummyTokenResult(error); - } - } - else { - interopTokenResult = { - token: token.token - }; - // write the new token to the memory state as well as the persistent storage. - // Only do it if we got a valid new token - state.token = token; - await writeTokenToStorage(app, token); - } - if (shouldCallListeners) { - notifyTokenListeners(app, interopTokenResult); - } - return interopTokenResult; -} -/** - * Internal API for limited use tokens. Skips all FAC state and simply calls - * the underlying provider. - */ -async function getLimitedUseToken$1(appCheck) { - const app = appCheck.app; - ensureActivated(app); - const { provider } = getStateReference(app); - if (isDebugMode()) { - const debugToken = await getDebugToken(); - const { token } = await exchangeToken(getExchangeDebugTokenRequest(app, debugToken), appCheck.heartbeatServiceProvider); - return { token }; - } - else { - // provider is definitely valid since we ensure AppCheck was activated - const { token } = await provider.getToken(); - return { token }; - } -} -function addTokenListener(appCheck, type, listener, onError) { - const { app } = appCheck; - const state = getStateReference(app); - const tokenObserver = { - next: listener, - error: onError, - type - }; - state.tokenObservers = [...state.tokenObservers, tokenObserver]; - // Invoke the listener async immediately if there is a valid token - // in memory. - if (state.token && isValid(state.token)) { - const validToken = state.token; - Promise.resolve() - .then(() => { - listener({ token: validToken.token }); - initTokenRefresher(appCheck); - }) - .catch(() => { - /* we don't care about exceptions thrown in listeners */ - }); - } - /** - * Wait for any cached token promise to resolve before starting the token - * refresher. The refresher checks to see if there is an existing token - * in state and calls the exchange endpoint if not. We should first let the - * IndexedDB check have a chance to populate state if it can. - * - * Listener call isn't needed here because cachedTokenPromise will call any - * listeners that exist when it resolves. - */ - // state.cachedTokenPromise is always populated in `activate()`. - void state.cachedTokenPromise.then(() => initTokenRefresher(appCheck)); -} -function removeTokenListener(app, listener) { - const state = getStateReference(app); - const newObservers = state.tokenObservers.filter(tokenObserver => tokenObserver.next !== listener); - if (newObservers.length === 0 && - state.tokenRefresher && - state.tokenRefresher.isRunning()) { - state.tokenRefresher.stop(); - } - state.tokenObservers = newObservers; -} -/** - * Logic to create and start refresher as needed. - */ -function initTokenRefresher(appCheck) { - const { app } = appCheck; - const state = getStateReference(app); - // Create the refresher but don't start it if `isTokenAutoRefreshEnabled` - // is not true. - let refresher = state.tokenRefresher; - if (!refresher) { - refresher = createTokenRefresher(appCheck); - state.tokenRefresher = refresher; - } - if (!refresher.isRunning() && state.isTokenAutoRefreshEnabled) { - refresher.start(); - } -} -function createTokenRefresher(appCheck) { - const { app } = appCheck; - return new Refresher( - // Keep in mind when this fails for any reason other than the ones - // for which we should retry, it will effectively stop the proactive refresh. - async () => { - const state = getStateReference(app); - // If there is no token, we will try to load it from storage and use it - // If there is a token, we force refresh it because we know it's going to expire soon - let result; - if (!state.token) { - result = await getToken$2(appCheck); - } - else { - result = await getToken$2(appCheck, true); - } - /** - * getToken() always resolves. In case the result has an error field defined, it means - * the operation failed, and we should retry. - */ - if (result.error) { - throw result.error; - } - /** - * A special `internalError` field reflects that there was an error - * getting a new token from the exchange endpoint, but there's still a - * previous token that's valid for now and this should be passed to 2P/3P - * requests for a token. But we want this callback (`this.operation` in - * `Refresher`) to throw in order to kick off the Refresher's retry - * backoff. (Setting `hasSucceeded` to false.) - */ - if (result.internalError) { - throw result.internalError; - } - }, () => { - return true; - }, () => { - const state = getStateReference(app); - if (state.token) { - // issuedAtTime + (50% * total TTL) + 5 minutes - let nextRefreshTimeMillis = state.token.issuedAtTimeMillis + - (state.token.expireTimeMillis - state.token.issuedAtTimeMillis) * - 0.5 + - 5 * 60 * 1000; - // Do not allow refresh time to be past (expireTime - 5 minutes) - const latestAllowableRefresh = state.token.expireTimeMillis - 5 * 60 * 1000; - nextRefreshTimeMillis = Math.min(nextRefreshTimeMillis, latestAllowableRefresh); - return Math.max(0, nextRefreshTimeMillis - Date.now()); - } - else { - return 0; - } - }, TOKEN_REFRESH_TIME.RETRIAL_MIN_WAIT, TOKEN_REFRESH_TIME.RETRIAL_MAX_WAIT); -} -function notifyTokenListeners(app, token) { - const observers = getStateReference(app).tokenObservers; - for (const observer of observers) { - try { - if (observer.type === "EXTERNAL" /* ListenerType.EXTERNAL */ && token.error != null) { - // If this listener was added by a 3P call, send any token error to - // the supplied error handler. A 3P observer always has an error - // handler. - observer.error(token.error); - } - else { - // If the token has no error field, always return the token. - // If this is a 2P listener, return the token, whether or not it - // has an error field. - observer.next(token); - } - } - catch (e) { - // Errors in the listener function itself are always ignored. - } - } -} -function isValid(token) { - return token.expireTimeMillis - Date.now() > 0; -} -function makeDummyTokenResult(error) { - return { - token: formatDummyToken(defaultTokenErrorData), - error - }; -} - -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * AppCheck Service class. - */ -class AppCheckService { - constructor(app, heartbeatServiceProvider) { - this.app = app; - this.heartbeatServiceProvider = heartbeatServiceProvider; - } - _delete() { - const { tokenObservers } = getStateReference(this.app); - for (const tokenObserver of tokenObservers) { - removeTokenListener(this.app, tokenObserver.next); - } - return Promise.resolve(); - } -} -function factory(app, heartbeatServiceProvider) { - return new AppCheckService(app, heartbeatServiceProvider); -} -function internalFactory(appCheck) { - return { - getToken: forceRefresh => getToken$2(appCheck, forceRefresh), - getLimitedUseToken: () => getLimitedUseToken$1(appCheck), - addTokenListener: listener => addTokenListener(appCheck, "INTERNAL" /* ListenerType.INTERNAL */, listener), - removeTokenListener: listener => removeTokenListener(appCheck.app, listener) - }; -} - -const name = "@firebase/app-check"; -const version = "0.11.0"; - -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -const RECAPTCHA_URL = 'https://www.google.com/recaptcha/api.js'; -const RECAPTCHA_ENTERPRISE_URL = 'https://www.google.com/recaptcha/enterprise.js'; -function initializeV3(app, siteKey) { - const initialized = new util.Deferred(); - const state = getStateReference(app); - state.reCAPTCHAState = { initialized }; - const divId = makeDiv(app); - const grecaptcha = getRecaptcha(false); - if (!grecaptcha) { - loadReCAPTCHAV3Script(() => { - const grecaptcha = getRecaptcha(false); - if (!grecaptcha) { - // it shouldn't happen. - throw new Error('no recaptcha'); - } - queueWidgetRender(app, siteKey, grecaptcha, divId, initialized); - }); - } - else { - queueWidgetRender(app, siteKey, grecaptcha, divId, initialized); - } - return initialized.promise; -} -function initializeEnterprise(app, siteKey) { - const initialized = new util.Deferred(); - const state = getStateReference(app); - state.reCAPTCHAState = { initialized }; - const divId = makeDiv(app); - const grecaptcha = getRecaptcha(true); - if (!grecaptcha) { - loadReCAPTCHAEnterpriseScript(() => { - const grecaptcha = getRecaptcha(true); - if (!grecaptcha) { - // it shouldn't happen. - throw new Error('no recaptcha'); - } - queueWidgetRender(app, siteKey, grecaptcha, divId, initialized); - }); - } - else { - queueWidgetRender(app, siteKey, grecaptcha, divId, initialized); - } - return initialized.promise; -} -/** - * Add listener to render the widget and resolve the promise when - * the grecaptcha.ready() event fires. - */ -function queueWidgetRender(app, siteKey, grecaptcha, container, initialized) { - grecaptcha.ready(() => { - // Invisible widgets allow us to set a different siteKey for each widget, - // so we use them to support multiple apps - renderInvisibleWidget(app, siteKey, grecaptcha, container); - initialized.resolve(grecaptcha); - }); -} -/** - * Add invisible div to page. - */ -function makeDiv(app) { - const divId = `fire_app_check_${app.name}`; - const invisibleDiv = document.createElement('div'); - invisibleDiv.id = divId; - invisibleDiv.style.display = 'none'; - document.body.appendChild(invisibleDiv); - return divId; -} -async function getToken$1(app) { - ensureActivated(app); - // ensureActivated() guarantees that reCAPTCHAState is set - const reCAPTCHAState = getStateReference(app).reCAPTCHAState; - const recaptcha = await reCAPTCHAState.initialized.promise; - return new Promise((resolve, _reject) => { - // Updated after initialization is complete. - const reCAPTCHAState = getStateReference(app).reCAPTCHAState; - recaptcha.ready(() => { - resolve( - // widgetId is guaranteed to be available if reCAPTCHAState.initialized.promise resolved. - recaptcha.execute(reCAPTCHAState.widgetId, { - action: 'fire_app_check' - })); - }); - }); -} -/** - * - * @param app - * @param container - Id of a HTML element. - */ -function renderInvisibleWidget(app, siteKey, grecaptcha, container) { - const widgetId = grecaptcha.render(container, { - sitekey: siteKey, - size: 'invisible', - // Success callback - set state - callback: () => { - getStateReference(app).reCAPTCHAState.succeeded = true; - }, - // Failure callback - set state - 'error-callback': () => { - getStateReference(app).reCAPTCHAState.succeeded = false; - } - }); - const state = getStateReference(app); - state.reCAPTCHAState = { - ...state.reCAPTCHAState, // state.reCAPTCHAState is set in the initialize() - widgetId - }; -} -function loadReCAPTCHAV3Script(onload) { - const script = document.createElement('script'); - script.src = RECAPTCHA_URL; - script.onload = onload; - document.head.appendChild(script); -} -function loadReCAPTCHAEnterpriseScript(onload) { - const script = document.createElement('script'); - script.src = RECAPTCHA_ENTERPRISE_URL; - script.onload = onload; - document.head.appendChild(script); -} - -/** - * @license - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * App Check provider that can obtain a reCAPTCHA V3 token and exchange it - * for an App Check token. - * - * @public - */ -class ReCaptchaV3Provider { - /** - * Create a ReCaptchaV3Provider instance. - * @param siteKey - ReCAPTCHA V3 siteKey. - */ - constructor(_siteKey) { - this._siteKey = _siteKey; - /** - * Throttle requests on certain error codes to prevent too many retries - * in a short time. - */ - this._throttleData = null; - } - /** - * Returns an App Check token. - * @internal - */ - async getToken() { - throwIfThrottled(this._throttleData); - // Top-level `getToken()` has already checked that App Check is initialized - // and therefore this._app and this._heartbeatServiceProvider are available. - const attestedClaimsToken = await getToken$1(this._app).catch(_e => { - // reCaptcha.execute() throws null which is not very descriptive. - throw ERROR_FACTORY.create("recaptcha-error" /* AppCheckError.RECAPTCHA_ERROR */); - }); - // Check if a failure state was set by the recaptcha "error-callback". - if (!getStateReference(this._app).reCAPTCHAState?.succeeded) { - throw ERROR_FACTORY.create("recaptcha-error" /* AppCheckError.RECAPTCHA_ERROR */); - } - let result; - try { - result = await exchangeToken(getExchangeRecaptchaV3TokenRequest(this._app, attestedClaimsToken), this._heartbeatServiceProvider); - } - catch (e) { - if (e.code?.includes("fetch-status-error" /* AppCheckError.FETCH_STATUS_ERROR */)) { - this._throttleData = setBackoff(Number(e.customData?.httpStatus), this._throttleData); - throw ERROR_FACTORY.create("initial-throttle" /* AppCheckError.INITIAL_THROTTLE */, { - time: getDurationString(this._throttleData.allowRequestsAfter - Date.now()), - httpStatus: this._throttleData.httpStatus - }); - } - else { - throw e; - } - } - // If successful, clear throttle data. - this._throttleData = null; - return result; - } - /** - * @internal - */ - initialize(app$1) { - this._app = app$1; - this._heartbeatServiceProvider = app._getProvider(app$1, 'heartbeat'); - initializeV3(app$1, this._siteKey).catch(() => { - /* we don't care about the initialization result */ - }); - } - /** - * @internal - */ - isEqual(otherProvider) { - if (otherProvider instanceof ReCaptchaV3Provider) { - return this._siteKey === otherProvider._siteKey; - } - else { - return false; - } - } -} -/** - * App Check provider that can obtain a reCAPTCHA Enterprise token and exchange it - * for an App Check token. - * - * @public - */ -class ReCaptchaEnterpriseProvider { - /** - * Create a ReCaptchaEnterpriseProvider instance. - * @param siteKey - reCAPTCHA Enterprise score-based site key. - */ - constructor(_siteKey) { - this._siteKey = _siteKey; - /** - * Throttle requests on certain error codes to prevent too many retries - * in a short time. - */ - this._throttleData = null; - } - /** - * Returns an App Check token. - * @internal - */ - async getToken() { - throwIfThrottled(this._throttleData); - // Top-level `getToken()` has already checked that App Check is initialized - // and therefore this._app and this._heartbeatServiceProvider are available. - const attestedClaimsToken = await getToken$1(this._app).catch(_e => { - // reCaptcha.execute() throws null which is not very descriptive. - throw ERROR_FACTORY.create("recaptcha-error" /* AppCheckError.RECAPTCHA_ERROR */); - }); - // Check if a failure state was set by the recaptcha "error-callback". - if (!getStateReference(this._app).reCAPTCHAState?.succeeded) { - throw ERROR_FACTORY.create("recaptcha-error" /* AppCheckError.RECAPTCHA_ERROR */); - } - let result; - try { - result = await exchangeToken(getExchangeRecaptchaEnterpriseTokenRequest(this._app, attestedClaimsToken), this._heartbeatServiceProvider); - } - catch (e) { - if (e.code?.includes("fetch-status-error" /* AppCheckError.FETCH_STATUS_ERROR */)) { - this._throttleData = setBackoff(Number(e.customData?.httpStatus), this._throttleData); - throw ERROR_FACTORY.create("initial-throttle" /* AppCheckError.INITIAL_THROTTLE */, { - time: getDurationString(this._throttleData.allowRequestsAfter - Date.now()), - httpStatus: this._throttleData.httpStatus - }); - } - else { - throw e; - } - } - // If successful, clear throttle data. - this._throttleData = null; - return result; - } - /** - * @internal - */ - initialize(app$1) { - this._app = app$1; - this._heartbeatServiceProvider = app._getProvider(app$1, 'heartbeat'); - initializeEnterprise(app$1, this._siteKey).catch(() => { - /* we don't care about the initialization result */ - }); - } - /** - * @internal - */ - isEqual(otherProvider) { - if (otherProvider instanceof ReCaptchaEnterpriseProvider) { - return this._siteKey === otherProvider._siteKey; - } - else { - return false; - } - } -} -/** - * Custom provider class. - * @public - */ -class CustomProvider { - constructor(_customProviderOptions) { - this._customProviderOptions = _customProviderOptions; - } - /** - * @internal - */ - async getToken() { - // custom provider - const customToken = await this._customProviderOptions.getToken(); - // Try to extract IAT from custom token, in case this token is not - // being newly issued. JWT timestamps are in seconds since epoch. - const issuedAtTimeSeconds = util.issuedAtTime(customToken.token); - // Very basic validation, use current timestamp as IAT if JWT - // has no `iat` field or value is out of bounds. - const issuedAtTimeMillis = issuedAtTimeSeconds !== null && - issuedAtTimeSeconds < Date.now() && - issuedAtTimeSeconds > 0 - ? issuedAtTimeSeconds * 1000 - : Date.now(); - return { ...customToken, issuedAtTimeMillis }; - } - /** - * @internal - */ - initialize(app) { - this._app = app; - } - /** - * @internal - */ - isEqual(otherProvider) { - if (otherProvider instanceof CustomProvider) { - return (this._customProviderOptions.getToken.toString() === - otherProvider._customProviderOptions.getToken.toString()); - } - else { - return false; - } - } -} -/** - * Set throttle data to block requests until after a certain time - * depending on the failed request's status code. - * @param httpStatus - Status code of failed request. - * @param throttleData - `ThrottleData` object containing previous throttle - * data state. - * @returns Data about current throttle state and expiration time. - */ -function setBackoff(httpStatus, throttleData) { - /** - * Block retries for 1 day for the following error codes: - * - * 404: Likely malformed URL. - * - * 403: - * - Attestation failed - * - Wrong API key - * - Project deleted - */ - if (httpStatus === 404 || httpStatus === 403) { - return { - backoffCount: 1, - allowRequestsAfter: Date.now() + ONE_DAY, - httpStatus - }; - } - else { - /** - * For all other error codes, the time when it is ok to retry again - * is based on exponential backoff. - */ - const backoffCount = throttleData ? throttleData.backoffCount : 0; - const backoffMillis = util.calculateBackoffMillis(backoffCount, 1000, 2); - return { - backoffCount: backoffCount + 1, - allowRequestsAfter: Date.now() + backoffMillis, - httpStatus - }; - } -} -function throwIfThrottled(throttleData) { - if (throttleData) { - if (Date.now() - throttleData.allowRequestsAfter <= 0) { - // If before, throw. - throw ERROR_FACTORY.create("throttled" /* AppCheckError.THROTTLED */, { - time: getDurationString(throttleData.allowRequestsAfter - Date.now()), - httpStatus: throttleData.httpStatus - }); - } - } -} - -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * Activate App Check for the given app. Can be called only once per app. - * @param app - the {@link @firebase/app#FirebaseApp} to activate App Check for - * @param options - App Check initialization options - * @public - */ -function initializeAppCheck(app$1 = app.getApp(), options) { - app$1 = util.getModularInstance(app$1); - const provider = app._getProvider(app$1, 'app-check'); - // Ensure initializeDebugMode() is only called once. - if (!getDebugState().initialized) { - initializeDebugMode(); - } - // Log a message containing the debug token when `initializeAppCheck()` - // is called in debug mode. - if (isDebugMode()) { - // Do not block initialization to get the token for the message. - void getDebugToken().then(token => - // Not using logger because I don't think we ever want this accidentally hidden. - console.log(`App Check debug token: ${token}. You will need to add it to your app's App Check settings in the Firebase console for it to work.`)); - } - if (provider.isInitialized()) { - const existingInstance = provider.getImmediate(); - const initialOptions = provider.getOptions(); - if (initialOptions.isTokenAutoRefreshEnabled === - options.isTokenAutoRefreshEnabled && - initialOptions.provider.isEqual(options.provider)) { - return existingInstance; - } - else { - throw ERROR_FACTORY.create("already-initialized" /* AppCheckError.ALREADY_INITIALIZED */, { - appName: app$1.name - }); - } - } - const appCheck = provider.initialize({ options }); - _activate(app$1, options.provider, options.isTokenAutoRefreshEnabled); - // If isTokenAutoRefreshEnabled is false, do not send any requests to the - // exchange endpoint without an explicit call from the user either directly - // or through another Firebase library (storage, functions, etc.) - if (getStateReference(app$1).isTokenAutoRefreshEnabled) { - // Adding a listener will start the refresher and fetch a token if needed. - // This gets a token ready and prevents a delay when an internal library - // requests the token. - // Listener function does not need to do anything, its base functionality - // of calling getToken() already fetches token and writes it to memory/storage. - addTokenListener(appCheck, "INTERNAL" /* ListenerType.INTERNAL */, () => { }); - } - return appCheck; -} -/** - * Activate App Check - * @param app - Firebase app to activate App Check for. - * @param provider - reCAPTCHA v3 provider or - * custom token provider. - * @param isTokenAutoRefreshEnabled - If true, the SDK automatically - * refreshes App Check tokens as needed. If undefined, defaults to the - * value of `app.automaticDataCollectionEnabled`, which defaults to - * false and can be set in the app config. - */ -function _activate(app, provider, isTokenAutoRefreshEnabled = false) { - // Create an entry in the APP_CHECK_STATES map. Further changes should - // directly mutate this object. - const state = setInitialState(app, { ...DEFAULT_STATE }); - state.activated = true; - state.provider = provider; // Read cached token from storage if it exists and store it in memory. - state.cachedTokenPromise = readTokenFromStorage(app).then(cachedToken => { - if (cachedToken && isValid(cachedToken)) { - state.token = cachedToken; - // notify all listeners with the cached token - notifyTokenListeners(app, { token: cachedToken.token }); - } - return cachedToken; - }); - // Global `automaticDataCollectionEnabled` (defaults to true) and - // `isTokenAutoRefreshEnabled` must both be true. - state.isTokenAutoRefreshEnabled = - isTokenAutoRefreshEnabled && app.automaticDataCollectionEnabled; - if (!app.automaticDataCollectionEnabled && isTokenAutoRefreshEnabled) { - logger.warn('`isTokenAutoRefreshEnabled` is true but ' + - '`automaticDataCollectionEnabled` was set to false during' + - ' `initializeApp()`. This blocks automatic token refresh.'); - } - state.provider.initialize(app); -} -/** - * Set whether App Check will automatically refresh tokens as needed. - * - * @param appCheckInstance - The App Check service instance. - * @param isTokenAutoRefreshEnabled - If true, the SDK automatically - * refreshes App Check tokens as needed. This overrides any value set - * during `initializeAppCheck()`. - * @public - */ -function setTokenAutoRefreshEnabled(appCheckInstance, isTokenAutoRefreshEnabled) { - const app = appCheckInstance.app; - const state = getStateReference(app); - // This will exist if any product libraries have called - // `addTokenListener()` - if (state.tokenRefresher) { - if (isTokenAutoRefreshEnabled === true) { - state.tokenRefresher.start(); - } - else { - state.tokenRefresher.stop(); - } - } - state.isTokenAutoRefreshEnabled = isTokenAutoRefreshEnabled; -} -/** - * Get the current App Check token. If `forceRefresh` is false, this function first - * checks for a valid token in memory, then local persistence (IndexedDB). - * If not found, or if `forceRefresh` is true, it makes a request to the - * App Check endpoint for a fresh token. That request attaches - * to the most recent in-flight request if one is present. - * - * @param appCheckInstance - The App Check service instance. - * @param forceRefresh - If true, will always try to fetch a fresh token. - * If false, will use a cached token if found in storage. - * @public - */ -async function getToken(appCheckInstance, forceRefresh) { - const result = await getToken$2(appCheckInstance, forceRefresh); - if (result.error) { - throw result.error; - } - if (result.internalError) { - throw result.internalError; - } - return { token: result.token }; -} -/** - * Requests a Firebase App Check token. This method should be used - * only if you need to authorize requests to a non-Firebase backend. - * - * Returns limited-use tokens that are intended for use with your - * non-Firebase backend endpoints that are protected with - * <a href="https://firebase.google.com/docs/app-check/custom-resource-backend#replay-protection"> - * Replay Protection</a>. This method - * does not affect the token generation behavior of the - * #getAppCheckToken() method. - * - * @param appCheckInstance - The App Check service instance. - * @returns The limited use token. - * @public - */ -function getLimitedUseToken(appCheckInstance) { - return getLimitedUseToken$1(appCheckInstance); -} -/** - * Wraps `addTokenListener`/`removeTokenListener` methods in an `Observer` - * pattern for public use. - */ -function onTokenChanged(appCheckInstance, onNextOrObserver, onError, -/** - * NOTE: Although an `onCompletion` callback can be provided, it will - * never be called because the token stream is never-ending. - * It is added only for API consistency with the observer pattern, which - * we follow in JS APIs. - */ -// eslint-disable-next-line @typescript-eslint/no-unused-vars -onCompletion) { - let nextFn = () => { }; - let errorFn = () => { }; - if (onNextOrObserver.next != null) { - nextFn = onNextOrObserver.next.bind(onNextOrObserver); - } - else { - nextFn = onNextOrObserver; - } - if (onNextOrObserver.error != null) { - errorFn = onNextOrObserver.error.bind(onNextOrObserver); - } - else if (onError) { - errorFn = onError; - } - addTokenListener(appCheckInstance, "EXTERNAL" /* ListenerType.EXTERNAL */, nextFn, errorFn); - return () => removeTokenListener(appCheckInstance.app, nextFn); -} - -/** - * The Firebase App Check Web SDK. - * - * @remarks - * Firebase App Check does not work in a Node.js environment using `ReCaptchaV3Provider` or - * `ReCaptchaEnterpriseProvider`, but can be used in Node.js if you use - * `CustomProvider` and write your own attestation method. - * - * @packageDocumentation - */ -const APP_CHECK_NAME = 'app-check'; -const APP_CHECK_NAME_INTERNAL = 'app-check-internal'; -function registerAppCheck() { - // The public interface - app._registerComponent(new component.Component(APP_CHECK_NAME, container => { - // getImmediate for FirebaseApp will always succeed - const app = container.getProvider('app').getImmediate(); - const heartbeatServiceProvider = container.getProvider('heartbeat'); - return factory(app, heartbeatServiceProvider); - }, "PUBLIC" /* ComponentType.PUBLIC */) - .setInstantiationMode("EXPLICIT" /* InstantiationMode.EXPLICIT */) - /** - * Initialize app-check-internal after app-check is initialized to make AppCheck available to - * other Firebase SDKs - */ - .setInstanceCreatedCallback((container, _identifier, _appcheckService) => { - container.getProvider(APP_CHECK_NAME_INTERNAL).initialize(); - })); - // The internal interface used by other Firebase products - app._registerComponent(new component.Component(APP_CHECK_NAME_INTERNAL, container => { - const appCheck = container.getProvider('app-check').getImmediate(); - return internalFactory(appCheck); - }, "PUBLIC" /* ComponentType.PUBLIC */).setInstantiationMode("EXPLICIT" /* InstantiationMode.EXPLICIT */)); - app.registerVersion(name, version); -} -registerAppCheck(); - -exports.CustomProvider = CustomProvider; -exports.ReCaptchaEnterpriseProvider = ReCaptchaEnterpriseProvider; -exports.ReCaptchaV3Provider = ReCaptchaV3Provider; -exports.getLimitedUseToken = getLimitedUseToken; -exports.getToken = getToken; -exports.initializeAppCheck = initializeAppCheck; -exports.onTokenChanged = onTokenChanged; -exports.setTokenAutoRefreshEnabled = setTokenAutoRefreshEnabled; -//# sourceMappingURL=index.cjs.js.map |
