123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981 |
- /*! firebase-admin v12.1.1 */
- "use strict";
- /*!
- * Copyright 2021 Google Inc.
- *
- * 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.
- */
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.BaseAuth = exports.createFirebaseTokenGenerator = void 0;
- const error_1 = require("../utils/error");
- const deep_copy_1 = require("../utils/deep-copy");
- const validator = require("../utils/validator");
- const auth_api_request_1 = require("./auth-api-request");
- const token_generator_1 = require("./token-generator");
- const token_verifier_1 = require("./token-verifier");
- const auth_config_1 = require("./auth-config");
- const user_record_1 = require("./user-record");
- const identifier_1 = require("./identifier");
- const crypto_signer_1 = require("../utils/crypto-signer");
- /**
- * @internal
- */
- function createFirebaseTokenGenerator(app, tenantId) {
- try {
- const signer = (0, auth_api_request_1.useEmulator)() ? new token_generator_1.EmulatedSigner() : (0, crypto_signer_1.cryptoSignerFromApp)(app);
- return new token_generator_1.FirebaseTokenGenerator(signer, tenantId);
- }
- catch (err) {
- throw (0, token_generator_1.handleCryptoSignerError)(err);
- }
- }
- exports.createFirebaseTokenGenerator = createFirebaseTokenGenerator;
- /**
- * Common parent interface for both `Auth` and `TenantAwareAuth` APIs.
- */
- class BaseAuth {
- /**
- * The BaseAuth class constructor.
- *
- * @param app - The FirebaseApp to associate with this Auth instance.
- * @param authRequestHandler - The RPC request handler for this instance.
- * @param tokenGenerator - Optional token generator. If not specified, a
- * (non-tenant-aware) instance will be created. Use this paramter to
- * specify a tenant-aware tokenGenerator.
- * @constructor
- * @internal
- */
- constructor(app,
- /** @internal */ authRequestHandler, tokenGenerator) {
- this.authRequestHandler = authRequestHandler;
- if (tokenGenerator) {
- this.tokenGenerator = tokenGenerator;
- }
- else {
- this.tokenGenerator = createFirebaseTokenGenerator(app);
- }
- this.sessionCookieVerifier = (0, token_verifier_1.createSessionCookieVerifier)(app);
- this.idTokenVerifier = (0, token_verifier_1.createIdTokenVerifier)(app);
- this.authBlockingTokenVerifier = (0, token_verifier_1.createAuthBlockingTokenVerifier)(app);
- }
- /**
- * Creates a new Firebase custom token (JWT) that can be sent back to a client
- * device to use to sign in with the client SDKs' `signInWithCustomToken()`
- * methods. (Tenant-aware instances will also embed the tenant ID in the
- * token.)
- *
- * See {@link https://firebase.google.com/docs/auth/admin/create-custom-tokens | Create Custom Tokens}
- * for code samples and detailed documentation.
- *
- * @param uid - The `uid` to use as the custom token's subject.
- * @param developerClaims - Optional additional claims to include
- * in the custom token's payload.
- *
- * @returns A promise fulfilled with a custom token for the
- * provided `uid` and payload.
- */
- createCustomToken(uid, developerClaims) {
- return this.tokenGenerator.createCustomToken(uid, developerClaims);
- }
- /**
- * Verifies a Firebase ID token (JWT). If the token is valid, the promise is
- * fulfilled with the token's decoded claims; otherwise, the promise is
- * rejected.
- *
- * If `checkRevoked` is set to true, first verifies whether the corresponding
- * user is disabled. If yes, an `auth/user-disabled` error is thrown. If no,
- * verifies if the session corresponding to the ID token was revoked. If the
- * corresponding user's session was invalidated, an `auth/id-token-revoked`
- * error is thrown. If not specified the check is not applied.
- *
- * See {@link https://firebase.google.com/docs/auth/admin/verify-id-tokens | Verify ID Tokens}
- * for code samples and detailed documentation.
- *
- * @param idToken - The ID token to verify.
- * @param checkRevoked - Whether to check if the ID token was revoked.
- * This requires an extra request to the Firebase Auth backend to check
- * the `tokensValidAfterTime` time for the corresponding user.
- * When not specified, this additional check is not applied.
- *
- * @returns A promise fulfilled with the
- * token's decoded claims if the ID token is valid; otherwise, a rejected
- * promise.
- */
- verifyIdToken(idToken, checkRevoked = false) {
- const isEmulator = (0, auth_api_request_1.useEmulator)();
- return this.idTokenVerifier.verifyJWT(idToken, isEmulator)
- .then((decodedIdToken) => {
- // Whether to check if the token was revoked.
- if (checkRevoked || isEmulator) {
- return this.verifyDecodedJWTNotRevokedOrDisabled(decodedIdToken, error_1.AuthClientErrorCode.ID_TOKEN_REVOKED);
- }
- return decodedIdToken;
- });
- }
- /**
- * Gets the user data for the user corresponding to a given `uid`.
- *
- * See {@link https://firebase.google.com/docs/auth/admin/manage-users#retrieve_user_data | Retrieve user data}
- * for code samples and detailed documentation.
- *
- * @param uid - The `uid` corresponding to the user whose data to fetch.
- *
- * @returns A promise fulfilled with the user
- * data corresponding to the provided `uid`.
- */
- getUser(uid) {
- return this.authRequestHandler.getAccountInfoByUid(uid)
- .then((response) => {
- // Returns the user record populated with server response.
- return new user_record_1.UserRecord(response.users[0]);
- });
- }
- /**
- * Gets the user data for the user corresponding to a given email.
- *
- * See {@link https://firebase.google.com/docs/auth/admin/manage-users#retrieve_user_data | Retrieve user data}
- * for code samples and detailed documentation.
- *
- * @param email - The email corresponding to the user whose data to
- * fetch.
- *
- * @returns A promise fulfilled with the user
- * data corresponding to the provided email.
- */
- getUserByEmail(email) {
- return this.authRequestHandler.getAccountInfoByEmail(email)
- .then((response) => {
- // Returns the user record populated with server response.
- return new user_record_1.UserRecord(response.users[0]);
- });
- }
- /**
- * Gets the user data for the user corresponding to a given phone number. The
- * phone number has to conform to the E.164 specification.
- *
- * See {@link https://firebase.google.com/docs/auth/admin/manage-users#retrieve_user_data | Retrieve user data}
- * for code samples and detailed documentation.
- *
- * @param phoneNumber - The phone number corresponding to the user whose
- * data to fetch.
- *
- * @returns A promise fulfilled with the user
- * data corresponding to the provided phone number.
- */
- getUserByPhoneNumber(phoneNumber) {
- return this.authRequestHandler.getAccountInfoByPhoneNumber(phoneNumber)
- .then((response) => {
- // Returns the user record populated with server response.
- return new user_record_1.UserRecord(response.users[0]);
- });
- }
- /**
- * Gets the user data for the user corresponding to a given provider id.
- *
- * See {@link https://firebase.google.com/docs/auth/admin/manage-users#retrieve_user_data | Retrieve user data}
- * for code samples and detailed documentation.
- *
- * @param providerId - The provider ID, for example, "google.com" for the
- * Google provider.
- * @param uid - The user identifier for the given provider.
- *
- * @returns A promise fulfilled with the user data corresponding to the
- * given provider id.
- */
- getUserByProviderUid(providerId, uid) {
- // Although we don't really advertise it, we want to also handle
- // non-federated idps with this call. So if we detect one of them, we'll
- // reroute this request appropriately.
- if (providerId === 'phone') {
- return this.getUserByPhoneNumber(uid);
- }
- else if (providerId === 'email') {
- return this.getUserByEmail(uid);
- }
- return this.authRequestHandler.getAccountInfoByFederatedUid(providerId, uid)
- .then((response) => {
- // Returns the user record populated with server response.
- return new user_record_1.UserRecord(response.users[0]);
- });
- }
- /**
- * Gets the user data corresponding to the specified identifiers.
- *
- * There are no ordering guarantees; in particular, the nth entry in the result list is not
- * guaranteed to correspond to the nth entry in the input parameters list.
- *
- * Only a maximum of 100 identifiers may be supplied. If more than 100 identifiers are supplied,
- * this method throws a FirebaseAuthError.
- *
- * @param identifiers - The identifiers used to indicate which user records should be returned.
- * Must not have more than 100 entries.
- * @returns A promise that resolves to the corresponding user records.
- * @throws FirebaseAuthError If any of the identifiers are invalid or if more than 100
- * identifiers are specified.
- */
- getUsers(identifiers) {
- if (!validator.isArray(identifiers)) {
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '`identifiers` parameter must be an array');
- }
- return this.authRequestHandler
- .getAccountInfoByIdentifiers(identifiers)
- .then((response) => {
- /**
- * Checks if the specified identifier is within the list of
- * UserRecords.
- */
- const isUserFound = ((id, userRecords) => {
- return !!userRecords.find((userRecord) => {
- if ((0, identifier_1.isUidIdentifier)(id)) {
- return id.uid === userRecord.uid;
- }
- else if ((0, identifier_1.isEmailIdentifier)(id)) {
- return id.email === userRecord.email;
- }
- else if ((0, identifier_1.isPhoneIdentifier)(id)) {
- return id.phoneNumber === userRecord.phoneNumber;
- }
- else if ((0, identifier_1.isProviderIdentifier)(id)) {
- const matchingUserInfo = userRecord.providerData.find((userInfo) => {
- return id.providerId === userInfo.providerId;
- });
- return !!matchingUserInfo && id.providerUid === matchingUserInfo.uid;
- }
- else {
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'Unhandled identifier type');
- }
- });
- });
- const users = response.users ? response.users.map((user) => new user_record_1.UserRecord(user)) : [];
- const notFound = identifiers.filter((id) => !isUserFound(id, users));
- return { users, notFound };
- });
- }
- /**
- * Retrieves a list of users (single batch only) with a size of `maxResults`
- * starting from the offset as specified by `pageToken`. This is used to
- * retrieve all the users of a specified project in batches.
- *
- * See {@link https://firebase.google.com/docs/auth/admin/manage-users#list_all_users | List all users}
- * for code samples and detailed documentation.
- *
- * @param maxResults - The page size, 1000 if undefined. This is also
- * the maximum allowed limit.
- * @param pageToken - The next page token. If not specified, returns
- * users starting without any offset.
- * @returns A promise that resolves with
- * the current batch of downloaded users and the next page token.
- */
- listUsers(maxResults, pageToken) {
- return this.authRequestHandler.downloadAccount(maxResults, pageToken)
- .then((response) => {
- // List of users to return.
- const users = [];
- // Convert each user response to a UserRecord.
- response.users.forEach((userResponse) => {
- users.push(new user_record_1.UserRecord(userResponse));
- });
- // Return list of user records and the next page token if available.
- const result = {
- users,
- pageToken: response.nextPageToken,
- };
- // Delete result.pageToken if undefined.
- if (typeof result.pageToken === 'undefined') {
- delete result.pageToken;
- }
- return result;
- });
- }
- /**
- * Creates a new user.
- *
- * See {@link https://firebase.google.com/docs/auth/admin/manage-users#create_a_user | Create a user}
- * for code samples and detailed documentation.
- *
- * @param properties - The properties to set on the
- * new user record to be created.
- *
- * @returns A promise fulfilled with the user
- * data corresponding to the newly created user.
- */
- createUser(properties) {
- return this.authRequestHandler.createNewAccount(properties)
- .then((uid) => {
- // Return the corresponding user record.
- return this.getUser(uid);
- })
- .catch((error) => {
- if (error.code === 'auth/user-not-found') {
- // Something must have happened after creating the user and then retrieving it.
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'Unable to create the user record provided.');
- }
- throw error;
- });
- }
- /**
- * Deletes an existing user.
- *
- * See {@link https://firebase.google.com/docs/auth/admin/manage-users#delete_a_user | Delete a user}
- * for code samples and detailed documentation.
- *
- * @param uid - The `uid` corresponding to the user to delete.
- *
- * @returns An empty promise fulfilled once the user has been
- * deleted.
- */
- deleteUser(uid) {
- return this.authRequestHandler.deleteAccount(uid)
- .then(() => {
- // Return nothing on success.
- });
- }
- /**
- * Deletes the users specified by the given uids.
- *
- * Deleting a non-existing user won't generate an error (i.e. this method
- * is idempotent.) Non-existing users are considered to be successfully
- * deleted, and are therefore counted in the
- * `DeleteUsersResult.successCount` value.
- *
- * Only a maximum of 1000 identifiers may be supplied. If more than 1000
- * identifiers are supplied, this method throws a FirebaseAuthError.
- *
- * This API is currently rate limited at the server to 1 QPS. If you exceed
- * this, you may get a quota exceeded error. Therefore, if you want to
- * delete more than 1000 users, you may need to add a delay to ensure you
- * don't go over this limit.
- *
- * @param uids - The `uids` corresponding to the users to delete.
- *
- * @returns A Promise that resolves to the total number of successful/failed
- * deletions, as well as the array of errors that corresponds to the
- * failed deletions.
- */
- deleteUsers(uids) {
- if (!validator.isArray(uids)) {
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '`uids` parameter must be an array');
- }
- return this.authRequestHandler.deleteAccounts(uids, /*force=*/ true)
- .then((batchDeleteAccountsResponse) => {
- const result = {
- failureCount: 0,
- successCount: uids.length,
- errors: [],
- };
- if (!validator.isNonEmptyArray(batchDeleteAccountsResponse.errors)) {
- return result;
- }
- result.failureCount = batchDeleteAccountsResponse.errors.length;
- result.successCount = uids.length - batchDeleteAccountsResponse.errors.length;
- result.errors = batchDeleteAccountsResponse.errors.map((batchDeleteErrorInfo) => {
- if (batchDeleteErrorInfo.index === undefined) {
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'Corrupt BatchDeleteAccountsResponse detected');
- }
- const errMsgToError = (msg) => {
- // We unconditionally set force=true, so the 'NOT_DISABLED' error
- // should not be possible.
- const code = msg && msg.startsWith('NOT_DISABLED') ?
- error_1.AuthClientErrorCode.USER_NOT_DISABLED : error_1.AuthClientErrorCode.INTERNAL_ERROR;
- return new error_1.FirebaseAuthError(code, batchDeleteErrorInfo.message);
- };
- return {
- index: batchDeleteErrorInfo.index,
- error: errMsgToError(batchDeleteErrorInfo.message),
- };
- });
- return result;
- });
- }
- /**
- * Updates an existing user.
- *
- * See {@link https://firebase.google.com/docs/auth/admin/manage-users#update_a_user | Update a user}
- * for code samples and detailed documentation.
- *
- * @param uid - The `uid` corresponding to the user to update.
- * @param properties - The properties to update on
- * the provided user.
- *
- * @returns A promise fulfilled with the
- * updated user data.
- */
- updateUser(uid, properties) {
- // Although we don't really advertise it, we want to also handle linking of
- // non-federated idps with this call. So if we detect one of them, we'll
- // adjust the properties parameter appropriately. This *does* imply that a
- // conflict could arise, e.g. if the user provides a phoneNumber property,
- // but also provides a providerToLink with a 'phone' provider id. In that
- // case, we'll throw an error.
- properties = (0, deep_copy_1.deepCopy)(properties);
- if (properties?.providerToLink) {
- if (properties.providerToLink.providerId === 'email') {
- if (typeof properties.email !== 'undefined') {
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Both UpdateRequest.email and UpdateRequest.providerToLink.providerId='email' were set. To "
- + 'link to the email/password provider, only specify the UpdateRequest.email field.');
- }
- properties.email = properties.providerToLink.uid;
- delete properties.providerToLink;
- }
- else if (properties.providerToLink.providerId === 'phone') {
- if (typeof properties.phoneNumber !== 'undefined') {
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Both UpdateRequest.phoneNumber and UpdateRequest.providerToLink.providerId='phone' were set. To "
- + 'link to a phone provider, only specify the UpdateRequest.phoneNumber field.');
- }
- properties.phoneNumber = properties.providerToLink.uid;
- delete properties.providerToLink;
- }
- }
- if (properties?.providersToUnlink) {
- if (properties.providersToUnlink.indexOf('phone') !== -1) {
- // If we've been told to unlink the phone provider both via setting
- // phoneNumber to null *and* by setting providersToUnlink to include
- // 'phone', then we'll reject that. Though it might also be reasonable
- // to relax this restriction and just unlink it.
- if (properties.phoneNumber === null) {
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, "Both UpdateRequest.phoneNumber=null and UpdateRequest.providersToUnlink=['phone'] were set. To "
- + 'unlink from a phone provider, only specify the UpdateRequest.phoneNumber=null field.');
- }
- }
- }
- return this.authRequestHandler.updateExistingAccount(uid, properties)
- .then((existingUid) => {
- // Return the corresponding user record.
- return this.getUser(existingUid);
- });
- }
- /**
- * Sets additional developer claims on an existing user identified by the
- * provided `uid`, typically used to define user roles and levels of
- * access. These claims should propagate to all devices where the user is
- * already signed in (after token expiration or when token refresh is forced)
- * and the next time the user signs in. If a reserved OIDC claim name
- * is used (sub, iat, iss, etc), an error is thrown. They are set on the
- * authenticated user's ID token JWT.
- *
- * See {@link https://firebase.google.com/docs/auth/admin/custom-claims |
- * Defining user roles and access levels}
- * for code samples and detailed documentation.
- *
- * @param uid - The `uid` of the user to edit.
- * @param customUserClaims - The developer claims to set. If null is
- * passed, existing custom claims are deleted. Passing a custom claims payload
- * larger than 1000 bytes will throw an error. Custom claims are added to the
- * user's ID token which is transmitted on every authenticated request.
- * For profile non-access related user attributes, use database or other
- * separate storage systems.
- * @returns A promise that resolves when the operation completes
- * successfully.
- */
- setCustomUserClaims(uid, customUserClaims) {
- return this.authRequestHandler.setCustomUserClaims(uid, customUserClaims)
- .then(() => {
- // Return nothing on success.
- });
- }
- /**
- * Revokes all refresh tokens for an existing user.
- *
- * This API will update the user's {@link UserRecord.tokensValidAfterTime} to
- * the current UTC. It is important that the server on which this is called has
- * its clock set correctly and synchronized.
- *
- * While this will revoke all sessions for a specified user and disable any
- * new ID tokens for existing sessions from getting minted, existing ID tokens
- * may remain active until their natural expiration (one hour). To verify that
- * ID tokens are revoked, use {@link BaseAuth.verifyIdToken}
- * where `checkRevoked` is set to true.
- *
- * @param uid - The `uid` corresponding to the user whose refresh tokens
- * are to be revoked.
- *
- * @returns An empty promise fulfilled once the user's refresh
- * tokens have been revoked.
- */
- revokeRefreshTokens(uid) {
- return this.authRequestHandler.revokeRefreshTokens(uid)
- .then(() => {
- // Return nothing on success.
- });
- }
- /**
- * Imports the provided list of users into Firebase Auth.
- * A maximum of 1000 users are allowed to be imported one at a time.
- * When importing users with passwords,
- * {@link UserImportOptions} are required to be
- * specified.
- * This operation is optimized for bulk imports and will ignore checks on `uid`,
- * `email` and other identifier uniqueness which could result in duplications.
- *
- * @param users - The list of user records to import to Firebase Auth.
- * @param options - The user import options, required when the users provided include
- * password credentials.
- * @returns A promise that resolves when
- * the operation completes with the result of the import. This includes the
- * number of successful imports, the number of failed imports and their
- * corresponding errors.
- */
- importUsers(users, options) {
- return this.authRequestHandler.uploadAccount(users, options);
- }
- /**
- * Creates a new Firebase session cookie with the specified options. The created
- * JWT string can be set as a server-side session cookie with a custom cookie
- * policy, and be used for session management. The session cookie JWT will have
- * the same payload claims as the provided ID token.
- *
- * See {@link https://firebase.google.com/docs/auth/admin/manage-cookies | Manage Session Cookies}
- * for code samples and detailed documentation.
- *
- * @param idToken - The Firebase ID token to exchange for a session
- * cookie.
- * @param sessionCookieOptions - The session
- * cookie options which includes custom session duration.
- *
- * @returns A promise that resolves on success with the
- * created session cookie.
- */
- createSessionCookie(idToken, sessionCookieOptions) {
- // Return rejected promise if expiresIn is not available.
- if (!validator.isNonNullObject(sessionCookieOptions) ||
- !validator.isNumber(sessionCookieOptions.expiresIn)) {
- return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_SESSION_COOKIE_DURATION));
- }
- return this.authRequestHandler.createSessionCookie(idToken, sessionCookieOptions.expiresIn);
- }
- /**
- * Verifies a Firebase session cookie. Returns a Promise with the cookie claims.
- * Rejects the promise if the cookie could not be verified.
- *
- * If `checkRevoked` is set to true, first verifies whether the corresponding
- * user is disabled: If yes, an `auth/user-disabled` error is thrown. If no,
- * verifies if the session corresponding to the session cookie was revoked.
- * If the corresponding user's session was invalidated, an
- * `auth/session-cookie-revoked` error is thrown. If not specified the check
- * is not performed.
- *
- * See {@link https://firebase.google.com/docs/auth/admin/manage-cookies#verify_session_cookie_and_check_permissions |
- * Verify Session Cookies}
- * for code samples and detailed documentation
- *
- * @param sessionCookie - The session cookie to verify.
- * @param checkForRevocation - Whether to check if the session cookie was
- * revoked. This requires an extra request to the Firebase Auth backend to
- * check the `tokensValidAfterTime` time for the corresponding user.
- * When not specified, this additional check is not performed.
- *
- * @returns A promise fulfilled with the
- * session cookie's decoded claims if the session cookie is valid; otherwise,
- * a rejected promise.
- */
- verifySessionCookie(sessionCookie, checkRevoked = false) {
- const isEmulator = (0, auth_api_request_1.useEmulator)();
- return this.sessionCookieVerifier.verifyJWT(sessionCookie, isEmulator)
- .then((decodedIdToken) => {
- // Whether to check if the token was revoked.
- if (checkRevoked || isEmulator) {
- return this.verifyDecodedJWTNotRevokedOrDisabled(decodedIdToken, error_1.AuthClientErrorCode.SESSION_COOKIE_REVOKED);
- }
- return decodedIdToken;
- });
- }
- /**
- * Generates the out of band email action link to reset a user's password.
- * The link is generated for the user with the specified email address. The
- * optional {@link ActionCodeSettings} object
- * defines whether the link is to be handled by a mobile app or browser and the
- * additional state information to be passed in the deep link, etc.
- *
- * @example
- * ```javascript
- * var actionCodeSettings = {
- * url: 'https://www.example.com/?email=user@example.com',
- * iOS: {
- * bundleId: 'com.example.ios'
- * },
- * android: {
- * packageName: 'com.example.android',
- * installApp: true,
- * minimumVersion: '12'
- * },
- * handleCodeInApp: true,
- * dynamicLinkDomain: 'custom.page.link'
- * };
- * admin.auth()
- * .generatePasswordResetLink('user@example.com', actionCodeSettings)
- * .then(function(link) {
- * // The link was successfully generated.
- * })
- * .catch(function(error) {
- * // Some error occurred, you can inspect the code: error.code
- * });
- * ```
- *
- * @param email - The email address of the user whose password is to be
- * reset.
- * @param actionCodeSettings - The action
- * code settings. If specified, the state/continue URL is set as the
- * "continueUrl" parameter in the password reset link. The default password
- * reset landing page will use this to display a link to go back to the app
- * if it is installed.
- * If the actionCodeSettings is not specified, no URL is appended to the
- * action URL.
- * The state URL provided must belong to a domain that is whitelisted by the
- * developer in the console. Otherwise an error is thrown.
- * Mobile app redirects are only applicable if the developer configures
- * and accepts the Firebase Dynamic Links terms of service.
- * The Android package name and iOS bundle ID are respected only if they
- * are configured in the same Firebase Auth project.
- * @returns A promise that resolves with the generated link.
- */
- generatePasswordResetLink(email, actionCodeSettings) {
- return this.authRequestHandler.getEmailActionLink('PASSWORD_RESET', email, actionCodeSettings);
- }
- /**
- * Generates the out of band email action link to verify the user's ownership
- * of the specified email. The {@link ActionCodeSettings} object provided
- * as an argument to this method defines whether the link is to be handled by a
- * mobile app or browser along with additional state information to be passed in
- * the deep link, etc.
- *
- * @example
- * ```javascript
- * var actionCodeSettings = {
- * url: 'https://www.example.com/cart?email=user@example.com&cartId=123',
- * iOS: {
- * bundleId: 'com.example.ios'
- * },
- * android: {
- * packageName: 'com.example.android',
- * installApp: true,
- * minimumVersion: '12'
- * },
- * handleCodeInApp: true,
- * dynamicLinkDomain: 'custom.page.link'
- * };
- * admin.auth()
- * .generateEmailVerificationLink('user@example.com', actionCodeSettings)
- * .then(function(link) {
- * // The link was successfully generated.
- * })
- * .catch(function(error) {
- * // Some error occurred, you can inspect the code: error.code
- * });
- * ```
- *
- * @param email - The email account to verify.
- * @param actionCodeSettings - The action
- * code settings. If specified, the state/continue URL is set as the
- * "continueUrl" parameter in the email verification link. The default email
- * verification landing page will use this to display a link to go back to
- * the app if it is installed.
- * If the actionCodeSettings is not specified, no URL is appended to the
- * action URL.
- * The state URL provided must belong to a domain that is whitelisted by the
- * developer in the console. Otherwise an error is thrown.
- * Mobile app redirects are only applicable if the developer configures
- * and accepts the Firebase Dynamic Links terms of service.
- * The Android package name and iOS bundle ID are respected only if they
- * are configured in the same Firebase Auth project.
- * @returns A promise that resolves with the generated link.
- */
- generateEmailVerificationLink(email, actionCodeSettings) {
- return this.authRequestHandler.getEmailActionLink('VERIFY_EMAIL', email, actionCodeSettings);
- }
- /**
- * Generates an out-of-band email action link to verify the user's ownership
- * of the specified email. The {@link ActionCodeSettings} object provided
- * as an argument to this method defines whether the link is to be handled by a
- * mobile app or browser along with additional state information to be passed in
- * the deep link, etc.
- *
- * @param email - The current email account.
- * @param newEmail - The email address the account is being updated to.
- * @param actionCodeSettings - The action
- * code settings. If specified, the state/continue URL is set as the
- * "continueUrl" parameter in the email verification link. The default email
- * verification landing page will use this to display a link to go back to
- * the app if it is installed.
- * If the actionCodeSettings is not specified, no URL is appended to the
- * action URL.
- * The state URL provided must belong to a domain that is authorized
- * in the console, or an error will be thrown.
- * Mobile app redirects are only applicable if the developer configures
- * and accepts the Firebase Dynamic Links terms of service.
- * The Android package name and iOS bundle ID are respected only if they
- * are configured in the same Firebase Auth project.
- * @returns A promise that resolves with the generated link.
- */
- generateVerifyAndChangeEmailLink(email, newEmail, actionCodeSettings) {
- return this.authRequestHandler.getEmailActionLink('VERIFY_AND_CHANGE_EMAIL', email, actionCodeSettings, newEmail);
- }
- /**
- * Generates the out of band email action link to verify the user's ownership
- * of the specified email. The {@link ActionCodeSettings} object provided
- * as an argument to this method defines whether the link is to be handled by a
- * mobile app or browser along with additional state information to be passed in
- * the deep link, etc.
- *
- * @example
- * ```javascript
- * var actionCodeSettings = {
- * url: 'https://www.example.com/cart?email=user@example.com&cartId=123',
- * iOS: {
- * bundleId: 'com.example.ios'
- * },
- * android: {
- * packageName: 'com.example.android',
- * installApp: true,
- * minimumVersion: '12'
- * },
- * handleCodeInApp: true,
- * dynamicLinkDomain: 'custom.page.link'
- * };
- * admin.auth()
- * .generateEmailVerificationLink('user@example.com', actionCodeSettings)
- * .then(function(link) {
- * // The link was successfully generated.
- * })
- * .catch(function(error) {
- * // Some error occurred, you can inspect the code: error.code
- * });
- * ```
- *
- * @param email - The email account to verify.
- * @param actionCodeSettings - The action
- * code settings. If specified, the state/continue URL is set as the
- * "continueUrl" parameter in the email verification link. The default email
- * verification landing page will use this to display a link to go back to
- * the app if it is installed.
- * If the actionCodeSettings is not specified, no URL is appended to the
- * action URL.
- * The state URL provided must belong to a domain that is whitelisted by the
- * developer in the console. Otherwise an error is thrown.
- * Mobile app redirects are only applicable if the developer configures
- * and accepts the Firebase Dynamic Links terms of service.
- * The Android package name and iOS bundle ID are respected only if they
- * are configured in the same Firebase Auth project.
- * @returns A promise that resolves with the generated link.
- */
- generateSignInWithEmailLink(email, actionCodeSettings) {
- return this.authRequestHandler.getEmailActionLink('EMAIL_SIGNIN', email, actionCodeSettings);
- }
- /**
- * Returns the list of existing provider configurations matching the filter
- * provided. At most, 100 provider configs can be listed at a time.
- *
- * SAML and OIDC provider support requires Google Cloud's Identity Platform
- * (GCIP). To learn more about GCIP, including pricing and features,
- * see the {@link https://cloud.google.com/identity-platform | GCIP documentation}.
- *
- * @param options - The provider config filter to apply.
- * @returns A promise that resolves with the list of provider configs meeting the
- * filter requirements.
- */
- listProviderConfigs(options) {
- const processResponse = (response, providerConfigs) => {
- // Return list of provider configuration and the next page token if available.
- const result = {
- providerConfigs,
- };
- // Delete result.pageToken if undefined.
- if (Object.prototype.hasOwnProperty.call(response, 'nextPageToken')) {
- result.pageToken = response.nextPageToken;
- }
- return result;
- };
- if (options && options.type === 'oidc') {
- return this.authRequestHandler.listOAuthIdpConfigs(options.maxResults, options.pageToken)
- .then((response) => {
- // List of provider configurations to return.
- const providerConfigs = [];
- // Convert each provider config response to a OIDCConfig.
- response.oauthIdpConfigs.forEach((configResponse) => {
- providerConfigs.push(new auth_config_1.OIDCConfig(configResponse));
- });
- // Return list of provider configuration and the next page token if available.
- return processResponse(response, providerConfigs);
- });
- }
- else if (options && options.type === 'saml') {
- return this.authRequestHandler.listInboundSamlConfigs(options.maxResults, options.pageToken)
- .then((response) => {
- // List of provider configurations to return.
- const providerConfigs = [];
- // Convert each provider config response to a SAMLConfig.
- response.inboundSamlConfigs.forEach((configResponse) => {
- providerConfigs.push(new auth_config_1.SAMLConfig(configResponse));
- });
- // Return list of provider configuration and the next page token if available.
- return processResponse(response, providerConfigs);
- });
- }
- return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"AuthProviderConfigFilter.type" must be either "saml" or "oidc"'));
- }
- /**
- * Looks up an Auth provider configuration by the provided ID.
- * Returns a promise that resolves with the provider configuration
- * corresponding to the provider ID specified. If the specified ID does not
- * exist, an `auth/configuration-not-found` error is thrown.
- *
- * SAML and OIDC provider support requires Google Cloud's Identity Platform
- * (GCIP). To learn more about GCIP, including pricing and features,
- * see the {@link https://cloud.google.com/identity-platform | GCIP documentation}.
- *
- * @param providerId - The provider ID corresponding to the provider
- * config to return.
- * @returns A promise that resolves
- * with the configuration corresponding to the provided ID.
- */
- getProviderConfig(providerId) {
- if (auth_config_1.OIDCConfig.isProviderId(providerId)) {
- return this.authRequestHandler.getOAuthIdpConfig(providerId)
- .then((response) => {
- return new auth_config_1.OIDCConfig(response);
- });
- }
- else if (auth_config_1.SAMLConfig.isProviderId(providerId)) {
- return this.authRequestHandler.getInboundSamlConfig(providerId)
- .then((response) => {
- return new auth_config_1.SAMLConfig(response);
- });
- }
- return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
- }
- /**
- * Deletes the provider configuration corresponding to the provider ID passed.
- * If the specified ID does not exist, an `auth/configuration-not-found` error
- * is thrown.
- *
- * SAML and OIDC provider support requires Google Cloud's Identity Platform
- * (GCIP). To learn more about GCIP, including pricing and features,
- * see the {@link https://cloud.google.com/identity-platform | GCIP documentation}.
- *
- * @param providerId - The provider ID corresponding to the provider
- * config to delete.
- * @returns A promise that resolves on completion.
- */
- deleteProviderConfig(providerId) {
- if (auth_config_1.OIDCConfig.isProviderId(providerId)) {
- return this.authRequestHandler.deleteOAuthIdpConfig(providerId);
- }
- else if (auth_config_1.SAMLConfig.isProviderId(providerId)) {
- return this.authRequestHandler.deleteInboundSamlConfig(providerId);
- }
- return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
- }
- /**
- * Returns a promise that resolves with the updated `AuthProviderConfig`
- * corresponding to the provider ID specified.
- * If the specified ID does not exist, an `auth/configuration-not-found` error
- * is thrown.
- *
- * SAML and OIDC provider support requires Google Cloud's Identity Platform
- * (GCIP). To learn more about GCIP, including pricing and features,
- * see the {@link https://cloud.google.com/identity-platform | GCIP documentation}.
- *
- * @param providerId - The provider ID corresponding to the provider
- * config to update.
- * @param updatedConfig - The updated configuration.
- * @returns A promise that resolves with the updated provider configuration.
- */
- updateProviderConfig(providerId, updatedConfig) {
- if (!validator.isNonNullObject(updatedConfig)) {
- return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CONFIG, 'Request is missing "UpdateAuthProviderRequest" configuration.'));
- }
- if (auth_config_1.OIDCConfig.isProviderId(providerId)) {
- return this.authRequestHandler.updateOAuthIdpConfig(providerId, updatedConfig)
- .then((response) => {
- return new auth_config_1.OIDCConfig(response);
- });
- }
- else if (auth_config_1.SAMLConfig.isProviderId(providerId)) {
- return this.authRequestHandler.updateInboundSamlConfig(providerId, updatedConfig)
- .then((response) => {
- return new auth_config_1.SAMLConfig(response);
- });
- }
- return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
- }
- /**
- * Returns a promise that resolves with the newly created `AuthProviderConfig`
- * when the new provider configuration is created.
- *
- * SAML and OIDC provider support requires Google Cloud's Identity Platform
- * (GCIP). To learn more about GCIP, including pricing and features,
- * see the {@link https://cloud.google.com/identity-platform | GCIP documentation}.
- *
- * @param config - The provider configuration to create.
- * @returns A promise that resolves with the created provider configuration.
- */
- createProviderConfig(config) {
- if (!validator.isNonNullObject(config)) {
- return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CONFIG, 'Request is missing "AuthProviderConfig" configuration.'));
- }
- if (auth_config_1.OIDCConfig.isProviderId(config.providerId)) {
- return this.authRequestHandler.createOAuthIdpConfig(config)
- .then((response) => {
- return new auth_config_1.OIDCConfig(response);
- });
- }
- else if (auth_config_1.SAMLConfig.isProviderId(config.providerId)) {
- return this.authRequestHandler.createInboundSamlConfig(config)
- .then((response) => {
- return new auth_config_1.SAMLConfig(response);
- });
- }
- return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PROVIDER_ID));
- }
- /** @alpha */
- // eslint-disable-next-line @typescript-eslint/naming-convention
- _verifyAuthBlockingToken(token, audience) {
- const isEmulator = (0, auth_api_request_1.useEmulator)();
- return this.authBlockingTokenVerifier._verifyAuthBlockingToken(token, isEmulator, audience)
- .then((decodedAuthBlockingToken) => {
- return decodedAuthBlockingToken;
- });
- }
- /**
- * Verifies the decoded Firebase issued JWT is not revoked or disabled. Returns a promise that
- * resolves with the decoded claims on success. Rejects the promise with revocation error if revoked
- * or user disabled.
- *
- * @param decodedIdToken - The JWT's decoded claims.
- * @param revocationErrorInfo - The revocation error info to throw on revocation
- * detection.
- * @returns A promise that will be fulfilled after a successful verification.
- */
- verifyDecodedJWTNotRevokedOrDisabled(decodedIdToken, revocationErrorInfo) {
- // Get tokens valid after time for the corresponding user.
- return this.getUser(decodedIdToken.sub)
- .then((user) => {
- if (user.disabled) {
- throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.USER_DISABLED, 'The user record is disabled.');
- }
- // If no tokens valid after time available, token is not revoked.
- if (user.tokensValidAfterTime) {
- // Get the ID token authentication time and convert to milliseconds UTC.
- const authTimeUtc = decodedIdToken.auth_time * 1000;
- // Get user tokens valid after time in milliseconds UTC.
- const validSinceUtc = new Date(user.tokensValidAfterTime).getTime();
- // Check if authentication time is older than valid since time.
- if (authTimeUtc < validSinceUtc) {
- throw new error_1.FirebaseAuthError(revocationErrorInfo);
- }
- }
- // All checks above passed. Return the decoded token.
- return decodedIdToken;
- });
- }
- }
- exports.BaseAuth = BaseAuth;
|