@firebase/auth
Version:
The Firebase Authenticaton component of the Firebase JS SDK.
948 lines (935 loc) • 254 kB
JavaScript
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