UNPKG

@firebase/auth

Version:

The Firebase Authenticaton component of the Firebase JS SDK.

948 lines (935 loc) • 254 kB
import { ErrorFactory, deepEqual, isBrowserExtension, isMobileCordova, isReactNative, FirebaseError, querystring, getModularInstance, base64Decode, getUA, isIE, createSubscribe, querystringDecode, extractQuerystring } from '@firebase/util'; import { SDK_VERSION, _getProvider, _registerComponent, registerVersion, getApp } from '@firebase/app'; import { __rest } from 'tslib'; import { Logger, LogLevel } from '@firebase/logger'; import { Component } from '@firebase/component'; import * as fetchImpl from 'node-fetch'; /** * @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. */ /** * An enum of factors that may be used for multifactor authentication. * * @public */ const FactorId = { /** Phone as second factor */ PHONE: 'phone' }; /** * Enumeration of supported providers. * * @public */ const ProviderId = { /** Facebook provider ID */ FACEBOOK: 'facebook.com', /** GitHub provider ID */ GITHUB: 'github.com', /** Google provider ID */ GOOGLE: 'google.com', /** Password provider */ PASSWORD: 'password', /** Phone provider */ PHONE: 'phone', /** Twitter provider ID */ TWITTER: 'twitter.com' }; /** * Enumeration of supported sign-in methods. * * @public */ const SignInMethod = { /** Email link sign in method */ EMAIL_LINK: 'emailLink', /** Email/password sign in method */ EMAIL_PASSWORD: 'password', /** Facebook sign in method */ FACEBOOK: 'facebook.com', /** GitHub sign in method */ GITHUB: 'github.com', /** Google sign in method */ GOOGLE: 'google.com', /** Phone sign in method */ PHONE: 'phone', /** Twitter sign in method */ TWITTER: 'twitter.com' }; /** * Enumeration of supported operation types. * * @public */ const OperationType = { /** Operation involving linking an additional provider to an already signed-in user. */ LINK: 'link', /** Operation involving using a provider to reauthenticate an already signed-in user. */ REAUTHENTICATE: 'reauthenticate', /** Operation involving signing in a user. */ SIGN_IN: 'signIn' }; /** * An enumeration of the possible email action types. * * @public */ const ActionCodeOperation = { /** The email link sign-in action. */ EMAIL_SIGNIN: 'EMAIL_SIGNIN', /** The password reset action. */ PASSWORD_RESET: 'PASSWORD_RESET', /** The email revocation action. */ RECOVER_EMAIL: 'RECOVER_EMAIL', /** The revert second factor addition email action. */ REVERT_SECOND_FACTOR_ADDITION: 'REVERT_SECOND_FACTOR_ADDITION', /** The revert second factor addition email action. */ VERIFY_AND_CHANGE_EMAIL: 'VERIFY_AND_CHANGE_EMAIL', /** The email verification action. */ VERIFY_EMAIL: 'VERIFY_EMAIL' }; /** * @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 _debugErrorMap() { return { ["admin-restricted-operation" /* ADMIN_ONLY_OPERATION */]: 'This operation is restricted to administrators only.', ["argument-error" /* ARGUMENT_ERROR */]: '', ["app-not-authorized" /* APP_NOT_AUTHORIZED */]: "This app, identified by the domain where it's hosted, is not " + 'authorized to use Firebase Authentication with the provided API key. ' + 'Review your key configuration in the Google API console.', ["app-not-installed" /* APP_NOT_INSTALLED */]: 'The requested mobile application corresponding to the identifier (' + 'Android package name or iOS bundle ID) provided is not installed on ' + 'this device.', ["captcha-check-failed" /* CAPTCHA_CHECK_FAILED */]: 'The reCAPTCHA response token provided is either invalid, expired, ' + 'already used or the domain associated with it does not match the list ' + 'of whitelisted domains.', ["code-expired" /* CODE_EXPIRED */]: 'The SMS code has expired. Please re-send the verification code to try ' + 'again.', ["cordova-not-ready" /* CORDOVA_NOT_READY */]: 'Cordova framework is not ready.', ["cors-unsupported" /* CORS_UNSUPPORTED */]: 'This browser is not supported.', ["credential-already-in-use" /* CREDENTIAL_ALREADY_IN_USE */]: 'This credential is already associated with a different user account.', ["custom-token-mismatch" /* CREDENTIAL_MISMATCH */]: 'The custom token corresponds to a different audience.', ["requires-recent-login" /* CREDENTIAL_TOO_OLD_LOGIN_AGAIN */]: 'This operation is sensitive and requires recent authentication. Log in ' + 'again before retrying this request.', ["dependent-sdk-initialized-before-auth" /* DEPENDENT_SDK_INIT_BEFORE_AUTH */]: 'Another Firebase SDK was initialized and is trying to use Auth before Auth is ' + 'initialized. Please be sure to call `initializeAuth` or `getAuth` before ' + 'starting any other Firebase SDK.', ["dynamic-link-not-activated" /* DYNAMIC_LINK_NOT_ACTIVATED */]: 'Please activate Dynamic Links in the Firebase Console and agree to the terms and ' + 'conditions.', ["email-change-needs-verification" /* EMAIL_CHANGE_NEEDS_VERIFICATION */]: 'Multi-factor users must always have a verified email.', ["email-already-in-use" /* EMAIL_EXISTS */]: 'The email address is already in use by another account.', ["emulator-config-failed" /* EMULATOR_CONFIG_FAILED */]: 'Auth instance has already been used to make a network call. Auth can ' + 'no longer be configured to use the emulator. Try calling ' + '"connectAuthEmulator()" sooner.', ["expired-action-code" /* EXPIRED_OOB_CODE */]: 'The action code has expired.', ["cancelled-popup-request" /* EXPIRED_POPUP_REQUEST */]: 'This operation has been cancelled due to another conflicting popup being opened.', ["internal-error" /* INTERNAL_ERROR */]: 'An internal AuthError has occurred.', ["invalid-app-credential" /* INVALID_APP_CREDENTIAL */]: 'The phone verification request contains an invalid application verifier.' + ' The reCAPTCHA token response is either invalid or expired.', ["invalid-app-id" /* INVALID_APP_ID */]: 'The mobile app identifier is not registed for the current project.', ["invalid-user-token" /* INVALID_AUTH */]: "This user's credential isn't valid for this project. This can happen " + "if the user's token has been tampered with, or if the user isn't for " + 'the project associated with this API key.', ["invalid-auth-event" /* INVALID_AUTH_EVENT */]: 'An internal AuthError has occurred.', ["invalid-verification-code" /* INVALID_CODE */]: 'The SMS verification code used to create the phone auth credential is ' + 'invalid. Please resend the verification code sms and be sure to use the ' + 'verification code provided by the user.', ["invalid-continue-uri" /* INVALID_CONTINUE_URI */]: 'The continue URL provided in the request is invalid.', ["invalid-cordova-configuration" /* INVALID_CORDOVA_CONFIGURATION */]: 'The following Cordova plugins must be installed to enable OAuth sign-in: ' + 'cordova-plugin-buildinfo, cordova-universal-links-plugin, ' + 'cordova-plugin-browsertab, cordova-plugin-inappbrowser and ' + 'cordova-plugin-customurlscheme.', ["invalid-custom-token" /* INVALID_CUSTOM_TOKEN */]: 'The custom token format is incorrect. Please check the documentation.', ["invalid-dynamic-link-domain" /* INVALID_DYNAMIC_LINK_DOMAIN */]: 'The provided dynamic link domain is not configured or authorized for the current project.', ["invalid-email" /* INVALID_EMAIL */]: 'The email address is badly formatted.', ["invalid-emulator-scheme" /* INVALID_EMULATOR_SCHEME */]: 'Emulator URL must start with a valid scheme (http:// or https://).', ["invalid-api-key" /* INVALID_API_KEY */]: 'Your API key is invalid, please check you have copied it correctly.', ["invalid-cert-hash" /* INVALID_CERT_HASH */]: 'The SHA-1 certificate hash provided is invalid.', ["invalid-credential" /* INVALID_IDP_RESPONSE */]: 'The supplied auth credential is malformed or has expired.', ["invalid-message-payload" /* INVALID_MESSAGE_PAYLOAD */]: 'The email template corresponding to this action contains invalid characters in its message. ' + 'Please fix by going to the Auth email templates section in the Firebase Console.', ["invalid-multi-factor-session" /* INVALID_MFA_SESSION */]: 'The request does not contain a valid proof of first factor successful sign-in.', ["invalid-oauth-provider" /* INVALID_OAUTH_PROVIDER */]: 'EmailAuthProvider is not supported for this operation. This operation ' + 'only supports OAuth providers.', ["invalid-oauth-client-id" /* INVALID_OAUTH_CLIENT_ID */]: 'The OAuth client ID provided is either invalid or does not match the ' + 'specified API key.', ["unauthorized-domain" /* INVALID_ORIGIN */]: 'This domain is not authorized for OAuth operations for your Firebase ' + 'project. Edit the list of authorized domains from the Firebase console.', ["invalid-action-code" /* INVALID_OOB_CODE */]: 'The action code is invalid. This can happen if the code is malformed, ' + 'expired, or has already been used.', ["wrong-password" /* INVALID_PASSWORD */]: 'The password is invalid or the user does not have a password.', ["invalid-persistence-type" /* INVALID_PERSISTENCE */]: 'The specified persistence type is invalid. It can only be local, session or none.', ["invalid-phone-number" /* INVALID_PHONE_NUMBER */]: 'The format of the phone number provided is incorrect. Please enter the ' + 'phone number in a format that can be parsed into E.164 format. E.164 ' + 'phone numbers are written in the format [+][country code][subscriber ' + 'number including area code].', ["invalid-provider-id" /* INVALID_PROVIDER_ID */]: 'The specified provider ID is invalid.', ["invalid-recipient-email" /* INVALID_RECIPIENT_EMAIL */]: 'The email corresponding to this action failed to send as the provided ' + 'recipient email address is invalid.', ["invalid-sender" /* INVALID_SENDER */]: 'The email template corresponding to this action contains an invalid sender email or name. ' + 'Please fix by going to the Auth email templates section in the Firebase Console.', ["invalid-verification-id" /* INVALID_SESSION_INFO */]: 'The verification ID used to create the phone auth credential is invalid.', ["invalid-tenant-id" /* INVALID_TENANT_ID */]: "The Auth instance's tenant ID is invalid.", ["login-blocked" /* LOGIN_BLOCKED */]: "Login blocked by user-provided method: {$originalMessage}", ["missing-android-pkg-name" /* MISSING_ANDROID_PACKAGE_NAME */]: 'An Android Package Name must be provided if the Android App is required to be installed.', ["auth-domain-config-required" /* MISSING_AUTH_DOMAIN */]: 'Be sure to include authDomain when calling firebase.initializeApp(), ' + 'by following the instructions in the Firebase console.', ["missing-app-credential" /* MISSING_APP_CREDENTIAL */]: 'The phone verification request is missing an application verifier ' + 'assertion. A reCAPTCHA response token needs to be provided.', ["missing-verification-code" /* MISSING_CODE */]: 'The phone auth credential was created with an empty SMS verification code.', ["missing-continue-uri" /* MISSING_CONTINUE_URI */]: 'A continue URL must be provided in the request.', ["missing-iframe-start" /* MISSING_IFRAME_START */]: 'An internal AuthError has occurred.', ["missing-ios-bundle-id" /* MISSING_IOS_BUNDLE_ID */]: 'An iOS Bundle ID must be provided if an App Store ID is provided.', ["missing-or-invalid-nonce" /* MISSING_OR_INVALID_NONCE */]: 'The request does not contain a valid nonce. This can occur if the ' + 'SHA-256 hash of the provided raw nonce does not match the hashed nonce ' + 'in the ID token payload.', ["missing-multi-factor-info" /* MISSING_MFA_INFO */]: 'No second factor identifier is provided.', ["missing-multi-factor-session" /* MISSING_MFA_SESSION */]: 'The request is missing proof of first factor successful sign-in.', ["missing-phone-number" /* MISSING_PHONE_NUMBER */]: 'To send verification codes, provide a phone number for the recipient.', ["missing-verification-id" /* MISSING_SESSION_INFO */]: 'The phone auth credential was created with an empty verification ID.', ["app-deleted" /* MODULE_DESTROYED */]: 'This instance of FirebaseApp has been deleted.', ["multi-factor-info-not-found" /* MFA_INFO_NOT_FOUND */]: 'The user does not have a second factor matching the identifier provided.', ["multi-factor-auth-required" /* MFA_REQUIRED */]: 'Proof of ownership of a second factor is required to complete sign-in.', ["account-exists-with-different-credential" /* NEED_CONFIRMATION */]: 'An account already exists with the same email address but different ' + 'sign-in credentials. Sign in using a provider associated with this ' + 'email address.', ["network-request-failed" /* NETWORK_REQUEST_FAILED */]: 'A network AuthError (such as timeout, interrupted connection or unreachable host) has occurred.', ["no-auth-event" /* NO_AUTH_EVENT */]: 'An internal AuthError has occurred.', ["no-such-provider" /* NO_SUCH_PROVIDER */]: 'User was not linked to an account with the given provider.', ["null-user" /* NULL_USER */]: 'A null user object was provided as the argument for an operation which ' + 'requires a non-null user object.', ["operation-not-allowed" /* OPERATION_NOT_ALLOWED */]: 'The given sign-in provider is disabled for this Firebase project. ' + 'Enable it in the Firebase console, under the sign-in method tab of the ' + 'Auth section.', ["operation-not-supported-in-this-environment" /* OPERATION_NOT_SUPPORTED */]: 'This operation is not supported in the environment this application is ' + 'running on. "location.protocol" must be http, https or chrome-extension' + ' and web storage must be enabled.', ["popup-blocked" /* POPUP_BLOCKED */]: 'Unable to establish a connection with the popup. It may have been blocked by the browser.', ["popup-closed-by-user" /* POPUP_CLOSED_BY_USER */]: 'The popup has been closed by the user before finalizing the operation.', ["provider-already-linked" /* PROVIDER_ALREADY_LINKED */]: 'User can only be linked to one identity for the given provider.', ["quota-exceeded" /* QUOTA_EXCEEDED */]: "The project's quota for this operation has been exceeded.", ["redirect-cancelled-by-user" /* REDIRECT_CANCELLED_BY_USER */]: 'The redirect operation has been cancelled by the user before finalizing.', ["redirect-operation-pending" /* REDIRECT_OPERATION_PENDING */]: 'A redirect sign-in operation is already pending.', ["rejected-credential" /* REJECTED_CREDENTIAL */]: 'The request contains malformed or mismatching credentials.', ["second-factor-already-in-use" /* SECOND_FACTOR_ALREADY_ENROLLED */]: 'The second factor is already enrolled on this account.', ["maximum-second-factor-count-exceeded" /* SECOND_FACTOR_LIMIT_EXCEEDED */]: 'The maximum allowed number of second factors on a user has been exceeded.', ["tenant-id-mismatch" /* TENANT_ID_MISMATCH */]: "The provided tenant ID does not match the Auth instance's tenant ID", ["timeout" /* TIMEOUT */]: 'The operation has timed out.', ["user-token-expired" /* TOKEN_EXPIRED */]: "The user's credential is no longer valid. The user must sign in again.", ["too-many-requests" /* TOO_MANY_ATTEMPTS_TRY_LATER */]: 'We have blocked all requests from this device due to unusual activity. ' + 'Try again later.', ["unauthorized-continue-uri" /* UNAUTHORIZED_DOMAIN */]: 'The domain of the continue URL is not whitelisted. Please whitelist ' + 'the domain in the Firebase console.', ["unsupported-first-factor" /* UNSUPPORTED_FIRST_FACTOR */]: 'Enrolling a second factor or signing in with a multi-factor account requires sign-in with a supported first factor.', ["unsupported-persistence-type" /* UNSUPPORTED_PERSISTENCE */]: 'The current environment does not support the specified persistence type.', ["unsupported-tenant-operation" /* UNSUPPORTED_TENANT_OPERATION */]: 'This operation is not supported in a multi-tenant context.', ["unverified-email" /* UNVERIFIED_EMAIL */]: 'The operation requires a verified email.', ["user-cancelled" /* USER_CANCELLED */]: 'The user did not grant your application the permissions it requested.', ["user-not-found" /* USER_DELETED */]: 'There is no user record corresponding to this identifier. The user may ' + 'have been deleted.', ["user-disabled" /* USER_DISABLED */]: 'The user account has been disabled by an administrator.', ["user-mismatch" /* USER_MISMATCH */]: 'The supplied credentials do not correspond to the previously signed in user.', ["user-signed-out" /* USER_SIGNED_OUT */]: '', ["weak-password" /* WEAK_PASSWORD */]: 'The password must be 6 characters long or more.', ["web-storage-unsupported" /* WEB_STORAGE_UNSUPPORTED */]: 'This browser is not supported or 3rd party cookies and data may be disabled.', ["already-initialized" /* ALREADY_INITIALIZED */]: 'initializeAuth() has already been called with ' + 'different options. To avoid this error, call initializeAuth() with the ' + 'same options as when it was originally called, or call getAuth() to return the' + ' already initialized instance.' }; } function _prodErrorMap() { // We will include this one message in the prod error map since by the very // nature of this error, developers will never be able to see the message // using the debugErrorMap (which is installed during auth initialization). return { ["dependent-sdk-initialized-before-auth" /* DEPENDENT_SDK_INIT_BEFORE_AUTH */]: 'Another Firebase SDK was initialized and is trying to use Auth before Auth is ' + 'initialized. Please be sure to call `initializeAuth` or `getAuth` before ' + 'starting any other Firebase SDK.' }; } /** * A verbose error map with detailed descriptions for most error codes. * * See discussion at {@link AuthErrorMap} * * @public */ const debugErrorMap = _debugErrorMap; /** * A minimal error map with all verbose error messages stripped. * * See discussion at {@link AuthErrorMap} * * @public */ const prodErrorMap = _prodErrorMap; const _DEFAULT_AUTH_ERROR_FACTORY = new ErrorFactory('auth', 'Firebase', _prodErrorMap()); /** * A map of potential `Auth` error codes, for easier comparison with errors * thrown by the SDK. * * @remarks * Note that you can't tree-shake individual keys * in the map, so by using the map you might substantially increase your * bundle size. * * @public */ const AUTH_ERROR_CODES_MAP_DO_NOT_USE_INTERNALLY = { ADMIN_ONLY_OPERATION: 'auth/admin-restricted-operation', ARGUMENT_ERROR: 'auth/argument-error', APP_NOT_AUTHORIZED: 'auth/app-not-authorized', APP_NOT_INSTALLED: 'auth/app-not-installed', CAPTCHA_CHECK_FAILED: 'auth/captcha-check-failed', CODE_EXPIRED: 'auth/code-expired', CORDOVA_NOT_READY: 'auth/cordova-not-ready', CORS_UNSUPPORTED: 'auth/cors-unsupported', CREDENTIAL_ALREADY_IN_USE: 'auth/credential-already-in-use', CREDENTIAL_MISMATCH: 'auth/custom-token-mismatch', CREDENTIAL_TOO_OLD_LOGIN_AGAIN: 'auth/requires-recent-login', DEPENDENT_SDK_INIT_BEFORE_AUTH: 'auth/dependent-sdk-initialized-before-auth', DYNAMIC_LINK_NOT_ACTIVATED: 'auth/dynamic-link-not-activated', EMAIL_CHANGE_NEEDS_VERIFICATION: 'auth/email-change-needs-verification', EMAIL_EXISTS: 'auth/email-already-in-use', EMULATOR_CONFIG_FAILED: 'auth/emulator-config-failed', EXPIRED_OOB_CODE: 'auth/expired-action-code', EXPIRED_POPUP_REQUEST: 'auth/cancelled-popup-request', INTERNAL_ERROR: 'auth/internal-error', INVALID_API_KEY: 'auth/invalid-api-key', INVALID_APP_CREDENTIAL: 'auth/invalid-app-credential', INVALID_APP_ID: 'auth/invalid-app-id', INVALID_AUTH: 'auth/invalid-user-token', INVALID_AUTH_EVENT: 'auth/invalid-auth-event', INVALID_CERT_HASH: 'auth/invalid-cert-hash', INVALID_CODE: 'auth/invalid-verification-code', INVALID_CONTINUE_URI: 'auth/invalid-continue-uri', INVALID_CORDOVA_CONFIGURATION: 'auth/invalid-cordova-configuration', INVALID_CUSTOM_TOKEN: 'auth/invalid-custom-token', INVALID_DYNAMIC_LINK_DOMAIN: 'auth/invalid-dynamic-link-domain', INVALID_EMAIL: 'auth/invalid-email', INVALID_EMULATOR_SCHEME: 'auth/invalid-emulator-scheme', INVALID_IDP_RESPONSE: 'auth/invalid-credential', INVALID_MESSAGE_PAYLOAD: 'auth/invalid-message-payload', INVALID_MFA_SESSION: 'auth/invalid-multi-factor-session', INVALID_OAUTH_CLIENT_ID: 'auth/invalid-oauth-client-id', INVALID_OAUTH_PROVIDER: 'auth/invalid-oauth-provider', INVALID_OOB_CODE: 'auth/invalid-action-code', INVALID_ORIGIN: 'auth/unauthorized-domain', INVALID_PASSWORD: 'auth/wrong-password', INVALID_PERSISTENCE: 'auth/invalid-persistence-type', INVALID_PHONE_NUMBER: 'auth/invalid-phone-number', INVALID_PROVIDER_ID: 'auth/invalid-provider-id', INVALID_RECIPIENT_EMAIL: 'auth/invalid-recipient-email', INVALID_SENDER: 'auth/invalid-sender', INVALID_SESSION_INFO: 'auth/invalid-verification-id', INVALID_TENANT_ID: 'auth/invalid-tenant-id', MFA_INFO_NOT_FOUND: 'auth/multi-factor-info-not-found', MFA_REQUIRED: 'auth/multi-factor-auth-required', MISSING_ANDROID_PACKAGE_NAME: 'auth/missing-android-pkg-name', MISSING_APP_CREDENTIAL: 'auth/missing-app-credential', MISSING_AUTH_DOMAIN: 'auth/auth-domain-config-required', MISSING_CODE: 'auth/missing-verification-code', MISSING_CONTINUE_URI: 'auth/missing-continue-uri', MISSING_IFRAME_START: 'auth/missing-iframe-start', MISSING_IOS_BUNDLE_ID: 'auth/missing-ios-bundle-id', MISSING_OR_INVALID_NONCE: 'auth/missing-or-invalid-nonce', MISSING_MFA_INFO: 'auth/missing-multi-factor-info', MISSING_MFA_SESSION: 'auth/missing-multi-factor-session', MISSING_PHONE_NUMBER: 'auth/missing-phone-number', MISSING_SESSION_INFO: 'auth/missing-verification-id', MODULE_DESTROYED: 'auth/app-deleted', NEED_CONFIRMATION: 'auth/account-exists-with-different-credential', NETWORK_REQUEST_FAILED: 'auth/network-request-failed', NULL_USER: 'auth/null-user', NO_AUTH_EVENT: 'auth/no-auth-event', NO_SUCH_PROVIDER: 'auth/no-such-provider', OPERATION_NOT_ALLOWED: 'auth/operation-not-allowed', OPERATION_NOT_SUPPORTED: 'auth/operation-not-supported-in-this-environment', POPUP_BLOCKED: 'auth/popup-blocked', POPUP_CLOSED_BY_USER: 'auth/popup-closed-by-user', PROVIDER_ALREADY_LINKED: 'auth/provider-already-linked', QUOTA_EXCEEDED: 'auth/quota-exceeded', REDIRECT_CANCELLED_BY_USER: 'auth/redirect-cancelled-by-user', REDIRECT_OPERATION_PENDING: 'auth/redirect-operation-pending', REJECTED_CREDENTIAL: 'auth/rejected-credential', SECOND_FACTOR_ALREADY_ENROLLED: 'auth/second-factor-already-in-use', SECOND_FACTOR_LIMIT_EXCEEDED: 'auth/maximum-second-factor-count-exceeded', TENANT_ID_MISMATCH: 'auth/tenant-id-mismatch', TIMEOUT: 'auth/timeout', TOKEN_EXPIRED: 'auth/user-token-expired', TOO_MANY_ATTEMPTS_TRY_LATER: 'auth/too-many-requests', UNAUTHORIZED_DOMAIN: 'auth/unauthorized-continue-uri', UNSUPPORTED_FIRST_FACTOR: 'auth/unsupported-first-factor', UNSUPPORTED_PERSISTENCE: 'auth/unsupported-persistence-type', UNSUPPORTED_TENANT_OPERATION: 'auth/unsupported-tenant-operation', UNVERIFIED_EMAIL: 'auth/unverified-email', USER_CANCELLED: 'auth/user-cancelled', USER_DELETED: 'auth/user-not-found', USER_DISABLED: 'auth/user-disabled', USER_MISMATCH: 'auth/user-mismatch', USER_SIGNED_OUT: 'auth/user-signed-out', WEAK_PASSWORD: 'auth/weak-password', WEB_STORAGE_UNSUPPORTED: 'auth/web-storage-unsupported', ALREADY_INITIALIZED: 'auth/already-initialized' }; /** * @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 logClient = new Logger('@firebase/auth'); function _logError(msg, ...args) { if (logClient.logLevel <= LogLevel.ERROR) { logClient.error(`Auth (${SDK_VERSION}): ${msg}`, ...args); } } /** * @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 _fail(authOrCode, ...rest) { throw createErrorInternal(authOrCode, ...rest); } function _createError(authOrCode, ...rest) { return createErrorInternal(authOrCode, ...rest); } function _errorWithCustomMessage(auth, code, message) { const errorMap = Object.assign(Object.assign({}, prodErrorMap()), { [code]: message }); const factory = new ErrorFactory('auth', 'Firebase', errorMap); return factory.create(code, { appName: auth.name, }); } function createErrorInternal(authOrCode, ...rest) { if (typeof authOrCode !== 'string') { const code = rest[0]; const fullParams = [...rest.slice(1)]; if (fullParams[0]) { fullParams[0].appName = authOrCode.name; } return authOrCode._errorFactory.create(code, ...fullParams); } return _DEFAULT_AUTH_ERROR_FACTORY.create(authOrCode, ...rest); } function _assert(assertion, authOrCode, ...rest) { if (!assertion) { throw createErrorInternal(authOrCode, ...rest); } } /** * Unconditionally fails, throwing an internal error with the given message. * * @param failure type of failure encountered * @throws Error */ function debugFail(failure) { // Log the failure in addition to throw an exception, just in case the // exception is swallowed. const message = `INTERNAL ASSERTION FAILED: ` + failure; _logError(message); // NOTE: We don't use FirebaseError here because these are internal failures // that cannot be handled by the user. (Also it would create a circular // dependency between the error and assert modules which doesn't work.) throw new Error(message); } /** * Fails if the given assertion condition is false, throwing an Error with the * given message if it did. * * @param assertion * @param message */ function debugAssert(assertion, message) { if (!assertion) { debugFail(message); } } /** * @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 instanceCache = new Map(); function _getInstance(cls) { debugAssert(cls instanceof Function, 'Expected a class definition'); let instance = instanceCache.get(cls); if (instance) { debugAssert(instance instanceof cls, 'Instance stored in cache mismatched with class'); return instance; } instance = new cls(); instanceCache.set(cls, instance); return instance; } /** * @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. */ /** * Initializes an {@link Auth} instance with fine-grained control over * {@link Dependencies}. * * @remarks * * This function allows more control over the {@link Auth} instance than * {@link getAuth}. `getAuth` uses platform-specific defaults to supply * the {@link Dependencies}. In general, `getAuth` is the easiest way to * initialize Auth and works for most use cases. Use `initializeAuth` if you * need control over which persistence layer is used, or to minimize bundle * size if you're not using either `signInWithPopup` or `signInWithRedirect`. * * For example, if your app only uses anonymous accounts and you only want * accounts saved for the current session, initialize `Auth` with: * * ```js * const auth = initializeAuth(app, { * persistence: browserSessionPersistence, * popupRedirectResolver: undefined, * }); * ``` * * @public */ function initializeAuth(app, deps) { const provider = _getProvider(app, 'auth'); if (provider.isInitialized()) { const auth = provider.getImmediate(); const initialOptions = provider.getOptions(); if (deepEqual(initialOptions, deps !== null && deps !== void 0 ? deps : {})) { return auth; } else { _fail(auth, "already-initialized" /* ALREADY_INITIALIZED */); } } const auth = provider.initialize({ options: deps }); return auth; } function _initializeAuthInstance(auth, deps) { const persistence = (deps === null || deps === void 0 ? void 0 : deps.persistence) || []; const hierarchy = (Array.isArray(persistence) ? persistence : [persistence]).map(_getInstance); if (deps === null || deps === void 0 ? void 0 : deps.errorMap) { auth._updateErrorMap(deps.errorMap); } // This promise is intended to float; auth initialization happens in the // background, meanwhile the auth object may be used by the app. // eslint-disable-next-line @typescript-eslint/no-floating-promises auth._initializeWithPersistence(hierarchy, deps === null || deps === void 0 ? void 0 : deps.popupRedirectResolver); } /** * @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 _getCurrentUrl() { var _a; return (typeof self !== 'undefined' && ((_a = self.location) === null || _a === void 0 ? void 0 : _a.href)) || ''; } function _isHttpOrHttps() { return _getCurrentScheme() === 'http:' || _getCurrentScheme() === 'https:'; } function _getCurrentScheme() { var _a; return (typeof self !== 'undefined' && ((_a = self.location) === null || _a === void 0 ? void 0 : _a.protocol)) || null; } /** * @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. */ /** * Determine whether the browser is working online */ function _isOnline() { if (typeof navigator !== 'undefined' && navigator && 'onLine' in navigator && typeof navigator.onLine === 'boolean' && // Apply only for traditional web apps and Chrome extensions. // This is especially true for Cordova apps which have unreliable // navigator.onLine behavior unless cordova-plugin-network-information is // installed which overwrites the native navigator.onLine value and // defines navigator.connection. (_isHttpOrHttps() || isBrowserExtension() || 'connection' in navigator)) { return navigator.onLine; } // If we can't determine the state, assume it is online. return true; } function _getUserLanguage() { if (typeof navigator === 'undefined') { return null; } const navigatorLanguage = navigator; return ( // Most reliable, but only supported in Chrome/Firefox. (navigatorLanguage.languages && navigatorLanguage.languages[0]) || // Supported in most browsers, but returns the language of the browser // UI, not the language set in browser settings. navigatorLanguage.language || // Couldn't determine language. null); } /** * @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. */ /** * A structure to help pick between a range of long and short delay durations * depending on the current environment. In general, the long delay is used for * mobile environments whereas short delays are used for desktop environments. */ class Delay { constructor(shortDelay, longDelay) { this.shortDelay = shortDelay; this.longDelay = longDelay; // Internal error when improperly initialized. debugAssert(longDelay > shortDelay, 'Short delay should be less than long delay!'); this.isMobile = isMobileCordova() || isReactNative(); } get() { if (!_isOnline()) { // Pick the shorter timeout. return Math.min(5000 /* OFFLINE */, this.shortDelay); } // If running in a mobile environment, return the long delay, otherwise // return the short delay. // This could be improved in the future to dynamically change based on other // variables instead of just reading the current environment. return this.isMobile ? this.longDelay : this.shortDelay; } } /** * @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 _emulatorUrl(config, path) { debugAssert(config.emulator, 'Emulator should always be set here'); const { url } = config.emulator; if (!path) { return url; } return `${url}${path.startsWith('/') ? path.slice(1) : path}`; } /** * @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. */ class FetchProvider { static initialize(fetchImpl, headersImpl, responseImpl) { this.fetchImpl = fetchImpl; if (headersImpl) { this.headersImpl = headersImpl; } if (responseImpl) { this.responseImpl = responseImpl; } } static fetch() { if (this.fetchImpl) { return this.fetchImpl; } if (typeof self !== 'undefined' && 'fetch' in self) { return self.fetch; } debugFail('Could not find fetch implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill'); } static headers() { if (this.headersImpl) { return this.headersImpl; } if (typeof self !== 'undefined' && 'Headers' in self) { return self.Headers; } debugFail('Could not find Headers implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill'); } static response() { if (this.responseImpl) { return this.responseImpl; } if (typeof self !== 'undefined' && 'Response' in self) { return self.Response; } debugFail('Could not find Response implementation, make sure you call FetchProvider.initialize() with an appropriate polyfill'); } } /** * @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. */ /** * Map from errors returned by the server to errors to developer visible errors */ const SERVER_ERROR_MAP = { // Custom token errors. ["CREDENTIAL_MISMATCH" /* CREDENTIAL_MISMATCH */]: "custom-token-mismatch" /* CREDENTIAL_MISMATCH */, // This can only happen if the SDK sends a bad request. ["MISSING_CUSTOM_TOKEN" /* MISSING_CUSTOM_TOKEN */]: "internal-error" /* INTERNAL_ERROR */, // Create Auth URI errors. ["INVALID_IDENTIFIER" /* INVALID_IDENTIFIER */]: "invalid-email" /* INVALID_EMAIL */, // This can only happen if the SDK sends a bad request. ["MISSING_CONTINUE_URI" /* MISSING_CONTINUE_URI */]: "internal-error" /* INTERNAL_ERROR */, // Sign in with email and password errors (some apply to sign up too). ["INVALID_PASSWORD" /* INVALID_PASSWORD */]: "wrong-password" /* INVALID_PASSWORD */, // This can only happen if the SDK sends a bad request. ["MISSING_PASSWORD" /* MISSING_PASSWORD */]: "internal-error" /* INTERNAL_ERROR */, // Sign up with email and password errors. ["EMAIL_EXISTS" /* EMAIL_EXISTS */]: "email-already-in-use" /* EMAIL_EXISTS */, ["PASSWORD_LOGIN_DISABLED" /* PASSWORD_LOGIN_DISABLED */]: "operation-not-allowed" /* OPERATION_NOT_ALLOWED */, // Verify assertion for sign in with credential errors: ["INVALID_IDP_RESPONSE" /* INVALID_IDP_RESPONSE */]: "invalid-credential" /* INVALID_IDP_RESPONSE */, ["INVALID_PENDING_TOKEN" /* INVALID_PENDING_TOKEN */]: "invalid-credential" /* INVALID_IDP_RESPONSE */, ["FEDERATED_USER_ID_ALREADY_LINKED" /* FEDERATED_USER_ID_ALREADY_LINKED */]: "credential-already-in-use" /* CREDENTIAL_ALREADY_IN_USE */, // This can only happen if the SDK sends a bad request. ["MISSING_REQ_TYPE" /* MISSING_REQ_TYPE */]: "internal-error" /* INTERNAL_ERROR */, // Send Password reset email errors: ["EMAIL_NOT_FOUND" /* EMAIL_NOT_FOUND */]: "user-not-found" /* USER_DELETED */, ["RESET_PASSWORD_EXCEED_LIMIT" /* RESET_PASSWORD_EXCEED_LIMIT */]: "too-many-requests" /* TOO_MANY_ATTEMPTS_TRY_LATER */, ["EXPIRED_OOB_CODE" /* EXPIRED_OOB_CODE */]: "expired-action-code" /* EXPIRED_OOB_CODE */, ["INVALID_OOB_CODE" /* INVALID_OOB_CODE */]: "invalid-action-code" /* INVALID_OOB_CODE */, // This can only happen if the SDK sends a bad request. ["MISSING_OOB_CODE" /* MISSING_OOB_CODE */]: "internal-error" /* INTERNAL_ERROR */, // Operations that require ID token in request: ["CREDENTIAL_TOO_OLD_LOGIN_AGAIN" /* CREDENTIAL_TOO_OLD_LOGIN_AGAIN */]: "requires-recent-login" /* CREDENTIAL_TOO_OLD_LOGIN_AGAIN */, ["INVALID_ID_TOKEN" /* INVALID_ID_TOKEN */]: "invalid-user-token" /* INVALID_AUTH */, ["TOKEN_EXPIRED" /* TOKEN_EXPIRED */]: "user-token-expired" /* TOKEN_EXPIRED */, ["USER_NOT_FOUND" /* USER_NOT_FOUND */]: "user-token-expired" /* TOKEN_EXPIRED */, // Other errors. ["TOO_MANY_ATTEMPTS_TRY_LATER" /* TOO_MANY_ATTEMPTS_TRY_LATER */]: "too-many-requests" /* TOO_MANY_ATTEMPTS_TRY_LATER */, // Phone Auth related errors. ["INVALID_CODE" /* INVALID_CODE */]: "invalid-verification-code" /* INVALID_CODE */, ["INVALID_SESSION_INFO" /* INVALID_SESSION_INFO */]: "invalid-verification-id" /* INVALID_SESSION_INFO */, ["INVALID_TEMPORARY_PROOF" /* INVALID_TEMPORARY_PROOF */]: "invalid-credential" /* INVALID_IDP_RESPONSE */, ["MISSING_SESSION_INFO" /* MISSING_SESSION_INFO */]: "missing-verification-id" /* MISSING_SESSION_INFO */, ["SESSION_EXPIRED" /* SESSION_EXPIRED */]: "code-expired" /* CODE_EXPIRED */, // Other action code errors when additional settings passed. // MISSING_CONTINUE_URI is getting mapped to INTERNAL_ERROR above. // This is OK as this error will be caught by client side validation. ["MISSING_ANDROID_PACKAGE_NAME" /* MISSING_ANDROID_PACKAGE_NAME */]: "missing-android-pkg-name" /* MISSING_ANDROID_PACKAGE_NAME */, ["UNAUTHORIZED_DOMAIN" /* UNAUTHORIZED_DOMAIN */]: "unauthorized-continue-uri" /* UNAUTHORIZED_DOMAIN */, // getProjectConfig errors when clientId is passed. ["INVALID_OAUTH_CLIENT_ID" /* INVALID_OAUTH_CLIENT_ID */]: "invalid-oauth-client-id" /* INVALID_OAUTH_CLIENT_ID */, // User actions (sign-up or deletion) disabled errors. ["ADMIN_ONLY_OPERATION" /* ADMIN_ONLY_OPERATION */]: "admin-restricted-operation" /* ADMIN_ONLY_OPERATION */, // Multi factor related errors. ["INVALID_MFA_PENDING_CREDENTIAL" /* INVALID_MFA_PENDING_CREDENTIAL */]: "invalid-multi-factor-session" /* INVALID_MFA_SESSION */, ["MFA_ENROLLMENT_NOT_FOUND" /* MFA_ENROLLMENT_NOT_FOUND */]: "multi-factor-info-not-found" /* MFA_INFO_NOT_FOUND */, ["MISSING_MFA_ENROLLMENT_ID" /* MISSING_MFA_ENROLLMENT_ID */]: "missing-multi-factor-info" /* MISSING_MFA_INFO */, ["MISSING_MFA_PENDING_CREDENTIAL" /* MISSING_MFA_PENDING_CREDENTIAL */]: "missing-multi-factor-session" /* MISSING_MFA_SESSION */, ["SECOND_FACTOR_EXISTS" /* SECOND_FACTOR_EXISTS */]: "second-factor-already-in-use" /* SECOND_FACTOR_ALREADY_ENROLLED */, ["SECOND_FACTOR_LIMIT_EXCEEDED" /* SECOND_FACTOR_LIMIT_EXCEEDED */]: "maximum-second-factor-count-exceeded" /* SECOND_FACTOR_LIMIT_EXCEEDED */, // Blocking functions related errors. ["BLOCKING_FUNCTION_ERROR_RESPONSE" /* BLOCKING_FUNCTION_ERROR_RESPONSE */]: "internal-error" /* INTERNAL_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. */ const DEFAULT_API_TIMEOUT_MS = new Delay(30000, 60000); function _addTidIfNecessary(auth, request) { if (auth.tenantId && !request.tenantId) { return Object.assign(Object.assign({}, request), { tenantId: auth.tenantId }); } return request; } async function _performApiRequest(auth, method, path, request, customErrorMap = {}) { return _performFetchWithErrorHandling(auth, customErrorMap, async () => { let body = {}; let params = {}; if (request) { if (method === "GET" /* GET */) { params = request; } else { body = { body: JSON.stringify(request) }; } } const query = querystring(Object.assign({ key: auth.config.apiKey }, params)).slice(1); const headers = await auth._getAdditionalHeaders(); headers["Content-Type" /* CONTENT_TYPE */] = 'application/json'; if (auth.languageCode) { headers["X-Firebase-Locale" /* X_FIREBASE_LOCALE */] = auth.languageCode; } return FetchProvider.fetch()(_getFinalTarget(auth, auth.config.apiHost, path, query), Object.assign({ method, headers, referrerPolicy: 'no-referrer' }, body)); }); } async function _performFetchWithErrorHandling(auth, customErrorMap, fetchFn) { auth._canInitEmulator = false; const errorMap = Object.assign(Object.assign({}, SERVER_ERROR_MAP), customErrorMap); try { const networkTimeout = new NetworkTimeout(auth); const response = await Promise.race([ fetchFn(), networkTimeout.promise ]); // If we've reached this point, the fetch succeeded and the networkTimeout // didn't throw; clear the network timeout delay so that Node won't hang networkTimeout.clearNetworkTimeout(); const json = await response.json(); if ('needConfirmation' in json) { throw _makeTaggedError(auth, "account-exists-with-different-credential" /* NEED_CONFIRMATION */, json); } if (response.ok && !('errorMessage' in json)) { return json; } else { const errorMessage = response.ok ? json.errorMessage : jso