initial commit

This commit is contained in:
2025-09-01 22:12:29 +02:00
parent b1873f9c1d
commit 02a54f61c0
5598 changed files with 903558 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
/*! firebase-admin v13.5.0 */
/*!
* Copyright 2018 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.
*/
/**
* This is the interface that defines the required continue/state URL with
* optional Android and iOS bundle identifiers.
*/
export interface ActionCodeSettings {
/**
* Defines the link continue/state URL, which has different meanings in
* different contexts:
* <ul>
* <li>When the link is handled in the web action widgets, this is the deep
* link in the `continueUrl` query parameter.</li>
* <li>When the link is handled in the app directly, this is the `continueUrl`
* query parameter in the deep link of the Dynamic Link.</li>
* </ul>
*/
url: string;
/**
* Whether to open the link via a mobile app or a browser.
* The default is false. When set to true, the action code link is sent
* as a Universal Link or Android App Link and is opened by the app if
* installed. In the false case, the code is sent to the web widget first
* and then redirects to the app if installed.
*/
handleCodeInApp?: boolean;
/**
* Defines the iOS bundle ID. This will try to open the link in an iOS app if it
* is installed.
*/
iOS?: {
/**
* Defines the required iOS bundle ID of the app where the link should be
* handled if the application is already installed on the device.
*/
bundleId: string;
};
/**
* Defines the Android package name. This will try to open the link in an
* android app if it is installed. If `installApp` is passed, it specifies
* whether to install the Android app if the device supports it and the app is
* not already installed. If this field is provided without a `packageName`, an
* error is thrown explaining that the `packageName` must be provided in
* conjunction with this field. If `minimumVersion` is specified, and an older
* version of the app is installed, the user is taken to the Play Store to
* upgrade the app.
*/
android?: {
/**
* Defines the required Android package name of the app where the link should be
* handled if the Android app is installed.
*/
packageName: string;
/**
* Whether to install the Android app if the device supports it and the app is
* not already installed.
*/
installApp?: boolean;
/**
* The Android minimum version if available. If the installed app is an older
* version, the user is taken to the GOogle Play Store to upgrade the app.
*/
minimumVersion?: string;
};
/**
* Defines the dynamic link domain to use for the current link if it is to be
* opened using Firebase Dynamic Links, as multiple dynamic link domains can be
* configured per project. This field provides the ability to explicitly choose
* configured per project. This fields provides the ability explicitly choose
* one. If none is provided, the oldest domain is used by default.
* @deprecated use `linkDomain` instead
*/
dynamicLinkDomain?: string;
/**
* Defines the custom Firebase Hosting domain to use when the link is to be opened
* via a specified mobile app,
* This is a replacement of Firebase Dynamic Link.
* If none is provided,
* a default hosting domain will be used (for example, `example.firebaseapp.com`)
*/
linkDomain?: string;
}

View File

@@ -0,0 +1,125 @@
/*! firebase-admin v13.5.0 */
"use strict";
/*!
* Copyright 2018 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.ActionCodeSettingsBuilder = void 0;
const validator = require("../utils/validator");
const error_1 = require("../utils/error");
/**
* Defines the ActionCodeSettings builder class used to convert the
* ActionCodeSettings object to its corresponding server request.
*
* @internal
*/
class ActionCodeSettingsBuilder {
/**
* ActionCodeSettingsBuilder constructor.
*
* @param {ActionCodeSettings} actionCodeSettings The ActionCodeSettings
* object used to initiliaze this server request builder.
* @constructor
*/
constructor(actionCodeSettings) {
if (!validator.isNonNullObject(actionCodeSettings)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings" must be a non-null object.');
}
if (typeof actionCodeSettings.url === 'undefined') {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISSING_CONTINUE_URI);
}
else if (!validator.isURL(actionCodeSettings.url)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CONTINUE_URI);
}
this.continueUrl = actionCodeSettings.url;
if (typeof actionCodeSettings.handleCodeInApp !== 'undefined' &&
!validator.isBoolean(actionCodeSettings.handleCodeInApp)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.handleCodeInApp" must be a boolean.');
}
this.canHandleCodeInApp = actionCodeSettings.handleCodeInApp || false;
if (typeof actionCodeSettings.dynamicLinkDomain !== 'undefined' &&
!validator.isNonEmptyString(actionCodeSettings.dynamicLinkDomain)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_DYNAMIC_LINK_DOMAIN);
}
this.dynamicLinkDomain = actionCodeSettings.dynamicLinkDomain;
if (typeof actionCodeSettings.linkDomain !== 'undefined' &&
!validator.isNonEmptyString(actionCodeSettings.linkDomain)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HOSTING_LINK_DOMAIN);
}
this.linkDomain = actionCodeSettings.linkDomain;
if (typeof actionCodeSettings.iOS !== 'undefined') {
if (!validator.isNonNullObject(actionCodeSettings.iOS)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.iOS" must be a valid non-null object.');
}
else if (typeof actionCodeSettings.iOS.bundleId === 'undefined') {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISSING_IOS_BUNDLE_ID);
}
else if (!validator.isNonEmptyString(actionCodeSettings.iOS.bundleId)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.iOS.bundleId" must be a valid non-empty string.');
}
this.ibi = actionCodeSettings.iOS.bundleId;
}
if (typeof actionCodeSettings.android !== 'undefined') {
if (!validator.isNonNullObject(actionCodeSettings.android)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.android" must be a valid non-null object.');
}
else if (typeof actionCodeSettings.android.packageName === 'undefined') {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISSING_ANDROID_PACKAGE_NAME);
}
else if (!validator.isNonEmptyString(actionCodeSettings.android.packageName)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.android.packageName" must be a valid non-empty string.');
}
else if (typeof actionCodeSettings.android.minimumVersion !== 'undefined' &&
!validator.isNonEmptyString(actionCodeSettings.android.minimumVersion)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.android.minimumVersion" must be a valid non-empty string.');
}
else if (typeof actionCodeSettings.android.installApp !== 'undefined' &&
!validator.isBoolean(actionCodeSettings.android.installApp)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"ActionCodeSettings.android.installApp" must be a valid boolean.');
}
this.apn = actionCodeSettings.android.packageName;
this.amv = actionCodeSettings.android.minimumVersion;
this.installApp = actionCodeSettings.android.installApp || false;
}
}
/**
* Returns the corresponding constructed server request corresponding to the
* current ActionCodeSettings.
*
* @returns The constructed EmailActionCodeRequest request.
*/
buildRequest() {
const request = {
continueUrl: this.continueUrl,
canHandleCodeInApp: this.canHandleCodeInApp,
dynamicLinkDomain: this.dynamicLinkDomain,
linkDomain: this.linkDomain,
androidPackageName: this.apn,
androidMinimumVersion: this.amv,
androidInstallApp: this.installApp,
iOSBundleId: this.ibi,
};
// Remove all null and undefined fields from request.
for (const key in request) {
if (Object.prototype.hasOwnProperty.call(request, key)) {
if (typeof request[key] === 'undefined' || request[key] === null) {
delete request[key];
}
}
}
return request;
}
}
exports.ActionCodeSettingsBuilder = ActionCodeSettingsBuilder;

View File

@@ -0,0 +1,185 @@
/*! firebase-admin v13.5.0 */
/*!
* @license
* Copyright 2017 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.
*/
import { App } from '../app/index';
import { UserImportOptions, UserImportRecord, UserImportResult } from './user-import-builder';
import { TenantServerResponse, CreateTenantRequest, UpdateTenantRequest } from './tenant';
import { ProjectConfigServerResponse, UpdateProjectConfigRequest } from './project-config';
/** List of reserved claims which cannot be provided when creating a custom token. */
export declare const RESERVED_CLAIMS: string[];
/** List of supported email action request types. */
export declare const EMAIL_ACTION_REQUEST_TYPES: string[];
/** Defines a base utility to help with resource URL construction. */
declare class AuthResourceUrlBuilder {
protected app: App;
protected version: string;
protected urlFormat: string;
private projectId;
/**
* The resource URL builder constructor.
*
* @param projectId - The resource project ID.
* @param version - The endpoint API version.
* @constructor
*/
constructor(app: App, version?: string);
/**
* Returns the resource URL corresponding to the provided parameters.
*
* @param api - The backend API name.
* @param params - The optional additional parameters to substitute in the
* URL path.
* @returns The corresponding resource URL.
*/
getUrl(api?: string, params?: object): Promise<string>;
private getProjectId;
}
interface BatchDeleteErrorInfo {
index?: number;
localId?: string;
message?: string;
}
export interface BatchDeleteAccountsResponse {
errors?: BatchDeleteErrorInfo[];
}
/**
* Utility for sending requests to Auth server that are Auth instance related. This includes user, tenant,
* and project config management related APIs. This extends the BaseFirebaseAuthRequestHandler class and defines
* additional tenant management related APIs.
*/
export declare class AuthRequestHandler extends AbstractAuthRequestHandler {
protected readonly authResourceUrlBuilder: AuthResourceUrlBuilder;
/**
* The FirebaseAuthRequestHandler constructor used to initialize an instance using a FirebaseApp.
*
* @param app - The app used to fetch access tokens to sign API requests.
* @constructor
*/
constructor(app: App);
/**
* @returns A new Auth user management resource URL builder instance.
*/
protected newAuthUrlBuilder(): AuthResourceUrlBuilder;
/**
* @returns A new project config resource URL builder instance.
*/
protected newProjectConfigUrlBuilder(): AuthResourceUrlBuilder;
/**
* Get the current project's config
* @returns A promise that resolves with the project config information.
*/
getProjectConfig(): Promise<ProjectConfigServerResponse>;
/**
* Update the current project's config.
* @returns A promise that resolves with the project config information.
*/
updateProjectConfig(options: UpdateProjectConfigRequest): Promise<ProjectConfigServerResponse>;
/**
* Looks up a tenant by tenant ID.
*
* @param tenantId - The tenant identifier of the tenant to lookup.
* @returns A promise that resolves with the tenant information.
*/
getTenant(tenantId: string): Promise<TenantServerResponse>;
/**
* Exports the tenants (single batch only) with a size of maxResults and starting from
* the offset as specified by pageToken.
*
* @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 tenants starting
* without any offset. Tenants are returned in the order they were created from oldest to
* newest, relative to the page token offset.
* @returns A promise that resolves with the current batch of downloaded
* tenants and the next page token if available. For the last page, an empty list of tenants
* and no page token are returned.
*/
listTenants(maxResults?: number, pageToken?: string): Promise<{
tenants: TenantServerResponse[];
nextPageToken?: string;
}>;
/**
* Deletes a tenant identified by a tenantId.
*
* @param tenantId - The identifier of the tenant to delete.
* @returns A promise that resolves when the tenant is deleted.
*/
deleteTenant(tenantId: string): Promise<void>;
/**
* Creates a new tenant with the properties provided.
*
* @param tenantOptions - The properties to set on the new tenant to be created.
* @returns A promise that resolves with the newly created tenant object.
*/
createTenant(tenantOptions: CreateTenantRequest): Promise<TenantServerResponse>;
/**
* Updates an existing tenant with the properties provided.
*
* @param tenantId - The tenant identifier of the tenant to update.
* @param tenantOptions - The properties to update on the existing tenant.
* @returns A promise that resolves with the modified tenant object.
*/
updateTenant(tenantId: string, tenantOptions: UpdateTenantRequest): Promise<TenantServerResponse>;
}
/**
* Utility for sending requests to Auth server that are tenant Auth instance related. This includes user
* management related APIs for specified tenants.
* This extends the BaseFirebaseAuthRequestHandler class.
*/
export declare class TenantAwareAuthRequestHandler extends AbstractAuthRequestHandler {
private readonly tenantId;
/**
* The FirebaseTenantRequestHandler constructor used to initialize an instance using a
* FirebaseApp and a tenant ID.
*
* @param app - The app used to fetch access tokens to sign API requests.
* @param tenantId - The request handler's tenant ID.
* @constructor
*/
constructor(app: App, tenantId: string);
/**
* @returns A new Auth user management resource URL builder instance.
*/
protected newAuthUrlBuilder(): AuthResourceUrlBuilder;
/**
* @returns A new project config resource URL builder instance.
*/
protected newProjectConfigUrlBuilder(): AuthResourceUrlBuilder;
/**
* Imports the list of users provided to Firebase Auth. This is useful when
* migrating from an external authentication system without having to use the Firebase CLI SDK.
* At most, 1000 users are allowed to be imported one at a time.
* When importing a list of password users, UserImportOptions are required to be specified.
*
* Overrides the superclass methods by adding an additional check to match tenant IDs of
* imported user records if present.
*
* @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 uploads and their corresponding errors.
*/
uploadAccount(users: UserImportRecord[], options?: UserImportOptions): Promise<UserImportResult>;
}
/**
* When true the SDK should communicate with the Auth Emulator for all API
* calls and also produce unsigned tokens.
*/
export declare function useEmulator(): boolean;
export {};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,851 @@
/*! firebase-admin v13.5.0 */
/*!
* Copyright 2018 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.
*/
/**
* Interface representing base properties of a user-enrolled second factor for a
* `CreateRequest`.
*/
export interface BaseCreateMultiFactorInfoRequest {
/**
* The optional display name for an enrolled second factor.
*/
displayName?: string;
/**
* The type identifier of the second factor. For SMS second factors, this is `phone`.
*/
factorId: string;
}
/**
* Interface representing a phone specific user-enrolled second factor for a
* `CreateRequest`.
*/
export interface CreatePhoneMultiFactorInfoRequest extends BaseCreateMultiFactorInfoRequest {
/**
* The phone number associated with a phone second factor.
*/
phoneNumber: string;
}
/**
* Type representing the properties of a user-enrolled second factor
* for a `CreateRequest`.
*/
export type CreateMultiFactorInfoRequest = CreatePhoneMultiFactorInfoRequest;
/**
* Interface representing common properties of a user-enrolled second factor
* for an `UpdateRequest`.
*/
export interface BaseUpdateMultiFactorInfoRequest {
/**
* The ID of the enrolled second factor. This ID is unique to the user. When not provided,
* a new one is provisioned by the Auth server.
*/
uid?: string;
/**
* The optional display name for an enrolled second factor.
*/
displayName?: string;
/**
* The optional date the second factor was enrolled, formatted as a UTC string.
*/
enrollmentTime?: string;
/**
* The type identifier of the second factor. For SMS second factors, this is `phone`.
*/
factorId: string;
}
/**
* Interface representing a phone specific user-enrolled second factor
* for an `UpdateRequest`.
*/
export interface UpdatePhoneMultiFactorInfoRequest extends BaseUpdateMultiFactorInfoRequest {
/**
* The phone number associated with a phone second factor.
*/
phoneNumber: string;
}
/**
* Type representing the properties of a user-enrolled second factor
* for an `UpdateRequest`.
*/
export type UpdateMultiFactorInfoRequest = UpdatePhoneMultiFactorInfoRequest;
/**
* The multi-factor related user settings for create operations.
*/
export interface MultiFactorCreateSettings {
/**
* The created user's list of enrolled second factors.
*/
enrolledFactors: CreateMultiFactorInfoRequest[];
}
/**
* The multi-factor related user settings for update operations.
*/
export interface MultiFactorUpdateSettings {
/**
* The updated list of enrolled second factors. The provided list overwrites the user's
* existing list of second factors.
* When null is passed, all of the user's existing second factors are removed.
*/
enrolledFactors: UpdateMultiFactorInfoRequest[] | null;
}
/**
* Interface representing the properties to update on the provided user.
*/
export interface UpdateRequest {
/**
* Whether or not the user is disabled: `true` for disabled;
* `false` for enabled.
*/
disabled?: boolean;
/**
* The user's display name.
*/
displayName?: string | null;
/**
* The user's primary email.
*/
email?: string;
/**
* Whether or not the user's primary email is verified.
*/
emailVerified?: boolean;
/**
* The user's unhashed password.
*/
password?: string;
/**
* The user's primary phone number.
*/
phoneNumber?: string | null;
/**
* The user's photo URL.
*/
photoURL?: string | null;
/**
* The user's updated multi-factor related properties.
*/
multiFactor?: MultiFactorUpdateSettings;
/**
* Links this user to the specified provider.
*
* Linking a provider to an existing user account does not invalidate the
* refresh token of that account. In other words, the existing account
* would continue to be able to access resources, despite not having used
* the newly linked provider to log in. If you wish to force the user to
* authenticate with this new provider, you need to (a) revoke their
* refresh token (see
* https://firebase.google.com/docs/auth/admin/manage-sessions#revoke_refresh_tokens),
* and (b) ensure no other authentication methods are present on this
* account.
*/
providerToLink?: UserProvider;
/**
* Unlinks this user from the specified providers.
*/
providersToUnlink?: string[];
}
/**
* Represents a user identity provider that can be associated with a Firebase user.
*/
export interface UserProvider {
/**
* The user identifier for the linked provider.
*/
uid?: string;
/**
* The display name for the linked provider.
*/
displayName?: string;
/**
* The email for the linked provider.
*/
email?: string;
/**
* The phone number for the linked provider.
*/
phoneNumber?: string;
/**
* The photo URL for the linked provider.
*/
photoURL?: string;
/**
* The linked provider ID (for example, "google.com" for the Google provider).
*/
providerId?: string;
}
/**
* Interface representing the properties to set on a new user record to be
* created.
*/
export interface CreateRequest extends UpdateRequest {
/**
* The user's `uid`.
*/
uid?: string;
/**
* The user's multi-factor related properties.
*/
multiFactor?: MultiFactorCreateSettings;
}
/**
* The response interface for listing provider configs. This is only available
* when listing all identity providers' configurations via
* {@link BaseAuth.listProviderConfigs}.
*/
export interface ListProviderConfigResults {
/**
* The list of providers for the specified type in the current page.
*/
providerConfigs: AuthProviderConfig[];
/**
* The next page token, if available.
*/
pageToken?: string;
}
/**
* The filter interface used for listing provider configurations. This is used
* when specifying how to list configured identity providers via
* {@link BaseAuth.listProviderConfigs}.
*/
export interface AuthProviderConfigFilter {
/**
* The Auth provider configuration filter. This can be either `saml` or `oidc`.
* The former is used to look up SAML providers only, while the latter is used
* for OIDC providers.
*/
type: 'saml' | 'oidc';
/**
* The maximum number of results to return per page. The default and maximum is
* 100.
*/
maxResults?: number;
/**
* The next page token. When not specified, the lookup starts from the beginning
* of the list.
*/
pageToken?: string;
}
/**
* The request interface for updating a SAML Auth provider. This is used
* when updating a SAML provider's configuration via
* {@link BaseAuth.updateProviderConfig}.
*/
export interface SAMLUpdateAuthProviderRequest {
/**
* The SAML provider's updated display name. If not provided, the existing
* configuration's value is not modified.
*/
displayName?: string;
/**
* Whether the SAML provider is enabled or not. If not provided, the existing
* configuration's setting is not modified.
*/
enabled?: boolean;
/**
* The SAML provider's updated IdP entity ID. If not provided, the existing
* configuration's value is not modified.
*/
idpEntityId?: string;
/**
* The SAML provider's updated SSO URL. If not provided, the existing
* configuration's value is not modified.
*/
ssoURL?: string;
/**
* The SAML provider's updated list of X.509 certificated. If not provided, the
* existing configuration list is not modified.
*/
x509Certificates?: string[];
/**
* The SAML provider's updated RP entity ID. If not provided, the existing
* configuration's value is not modified.
*/
rpEntityId?: string;
/**
* The SAML provider's callback URL. If not provided, the existing
* configuration's value is not modified.
*/
callbackURL?: string;
}
/**
* The request interface for updating an OIDC Auth provider. This is used
* when updating an OIDC provider's configuration via
* {@link BaseAuth.updateProviderConfig}.
*/
export interface OIDCUpdateAuthProviderRequest {
/**
* The OIDC provider's updated display name. If not provided, the existing
* configuration's value is not modified.
*/
displayName?: string;
/**
* Whether the OIDC provider is enabled or not. If not provided, the existing
* configuration's setting is not modified.
*/
enabled?: boolean;
/**
* The OIDC provider's updated client ID. If not provided, the existing
* configuration's value is not modified.
*/
clientId?: string;
/**
* The OIDC provider's updated issuer. If not provided, the existing
* configuration's value is not modified.
*/
issuer?: string;
/**
* The OIDC provider's client secret to enable OIDC code flow.
* If not provided, the existing configuration's value is not modified.
*/
clientSecret?: string;
/**
* The OIDC provider's response object for OAuth authorization flow.
*/
responseType?: OAuthResponseType;
}
export type UpdateAuthProviderRequest = SAMLUpdateAuthProviderRequest | OIDCUpdateAuthProviderRequest;
/** A maximum of 10 test phone number / code pairs can be configured. */
export declare const MAXIMUM_TEST_PHONE_NUMBERS = 10;
/** The server side SAML configuration request interface. */
export interface SAMLConfigServerRequest {
idpConfig?: {
idpEntityId?: string;
ssoUrl?: string;
idpCertificates?: Array<{
x509Certificate: string;
}>;
signRequest?: boolean;
};
spConfig?: {
spEntityId?: string;
callbackUri?: string;
};
displayName?: string;
enabled?: boolean;
[key: string]: any;
}
/** The server side SAML configuration response interface. */
export interface SAMLConfigServerResponse {
name?: string;
idpConfig?: {
idpEntityId?: string;
ssoUrl?: string;
idpCertificates?: Array<{
x509Certificate: string;
}>;
signRequest?: boolean;
};
spConfig?: {
spEntityId?: string;
callbackUri?: string;
};
displayName?: string;
enabled?: boolean;
}
/** The server side OIDC configuration request interface. */
export interface OIDCConfigServerRequest {
clientId?: string;
issuer?: string;
displayName?: string;
enabled?: boolean;
clientSecret?: string;
responseType?: OAuthResponseType;
[key: string]: any;
}
/** The server side OIDC configuration response interface. */
export interface OIDCConfigServerResponse {
name?: string;
clientId?: string;
issuer?: string;
displayName?: string;
enabled?: boolean;
clientSecret?: string;
responseType?: OAuthResponseType;
}
/** The server side email configuration request interface. */
export interface EmailSignInConfigServerRequest {
allowPasswordSignup?: boolean;
enableEmailLinkSignin?: boolean;
}
/** Identifies the server side second factor type. */
type AuthFactorServerType = 'PHONE_SMS';
/** Server side multi-factor configuration. */
export interface MultiFactorAuthServerConfig {
state?: MultiFactorConfigState;
enabledProviders?: AuthFactorServerType[];
providerConfigs?: MultiFactorProviderConfig[];
}
/**
* Identifies a second factor type.
*/
export type AuthFactorType = 'phone';
/**
* Identifies a multi-factor configuration state.
*/
export type MultiFactorConfigState = 'ENABLED' | 'DISABLED';
/**
* Interface representing a multi-factor configuration.
* This can be used to define whether multi-factor authentication is enabled
* or disabled and the list of second factor challenges that are supported.
*/
export interface MultiFactorConfig {
/**
* The multi-factor config state.
*/
state: MultiFactorConfigState;
/**
* The list of identifiers for enabled second factors.
* Currently only phone is supported.
*/
factorIds?: AuthFactorType[];
/**
* A list of multi-factor provider configurations.
* MFA providers (except phone) indicate whether they're enabled through this field. */
providerConfigs?: MultiFactorProviderConfig[];
}
/**
* Interface representing a multi-factor auth provider configuration.
* This interface is used for second factor auth providers other than SMS.
* Currently, only TOTP is supported.
*/ export interface MultiFactorProviderConfig {
/**
* Indicates whether this multi-factor provider is enabled or disabled. */
state: MultiFactorConfigState;
/**
* TOTP multi-factor provider config. */
totpProviderConfig?: TotpMultiFactorProviderConfig;
}
/**
* Interface representing configuration settings for TOTP second factor auth.
*/
export interface TotpMultiFactorProviderConfig {
/**
* The allowed number of adjacent intervals that will be used for verification
* to compensate for clock skew. */
adjacentIntervals?: number;
}
/**
* Validates the provided map of test phone number / code pairs.
* @param testPhoneNumbers - The phone number / code pairs to validate.
*/
export declare function validateTestPhoneNumbers(testPhoneNumbers: {
[phoneNumber: string]: string;
}): void;
/**
* The email sign in provider configuration.
*/
export interface EmailSignInProviderConfig {
/**
* Whether email provider is enabled.
*/
enabled: boolean;
/**
* Whether password is required for email sign-in. When not required,
* email sign-in can be performed with password or via email link sign-in.
*/
passwordRequired?: boolean;
}
/**
* The base Auth provider configuration interface.
*/
export interface BaseAuthProviderConfig {
/**
* The provider ID defined by the developer.
* For a SAML provider, this is always prefixed by `saml.`.
* For an OIDC provider, this is always prefixed by `oidc.`.
*/
providerId: string;
/**
* The user-friendly display name to the current configuration. This name is
* also used as the provider label in the Cloud Console.
*/
displayName?: string;
/**
* Whether the provider configuration is enabled or disabled. A user
* cannot sign in using a disabled provider.
*/
enabled: boolean;
}
/**
* The
* [SAML](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html)
* Auth provider configuration interface. A SAML provider can be created via
* {@link BaseAuth.createProviderConfig}.
*/
export interface SAMLAuthProviderConfig extends BaseAuthProviderConfig {
/**
* The SAML IdP entity identifier.
*/
idpEntityId: string;
/**
* The SAML IdP SSO URL. This must be a valid URL.
*/
ssoURL: string;
/**
* The list of SAML IdP X.509 certificates issued by CA for this provider.
* Multiple certificates are accepted to prevent outages during
* IdP key rotation (for example ADFS rotates every 10 days). When the Auth
* server receives a SAML response, it will match the SAML response with the
* certificate on record. Otherwise the response is rejected.
* Developers are expected to manage the certificate updates as keys are
* rotated.
*/
x509Certificates: string[];
/**
* The SAML relying party (service provider) entity ID.
* This is defined by the developer but needs to be provided to the SAML IdP.
*/
rpEntityId: string;
/**
* This is fixed and must always be the same as the OAuth redirect URL
* provisioned by Firebase Auth,
* `https://project-id.firebaseapp.com/__/auth/handler` unless a custom
* `authDomain` is used.
* The callback URL should also be provided to the SAML IdP during
* configuration.
*/
callbackURL?: string;
}
/**
* The interface representing OIDC provider's response object for OAuth
* authorization flow.
* One of the following settings is required:
* <ul>
* <li>Set <code>code</code> to <code>true</code> for the code flow.</li>
* <li>Set <code>idToken</code> to <code>true</code> for the ID token flow.</li>
* </ul>
*/
export interface OAuthResponseType {
/**
* Whether ID token is returned from IdP's authorization endpoint.
*/
idToken?: boolean;
/**
* Whether authorization code is returned from IdP's authorization endpoint.
*/
code?: boolean;
}
/**
* The [OIDC](https://openid.net/specs/openid-connect-core-1_0-final.html) Auth
* provider configuration interface. An OIDC provider can be created via
* {@link BaseAuth.createProviderConfig}.
*/
export interface OIDCAuthProviderConfig extends BaseAuthProviderConfig {
/**
* This is the required client ID used to confirm the audience of an OIDC
* provider's
* [ID token](https://openid.net/specs/openid-connect-core-1_0-final.html#IDToken).
*/
clientId: string;
/**
* This is the required provider issuer used to match the provider issuer of
* the ID token and to determine the corresponding OIDC discovery document, eg.
* [`/.well-known/openid-configuration`](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig).
* This is needed for the following:
* <ul>
* <li>To verify the provided issuer.</li>
* <li>Determine the authentication/authorization endpoint during the OAuth
* `id_token` authentication flow.</li>
* <li>To retrieve the public signing keys via `jwks_uri` to verify the OIDC
* provider's ID token's signature.</li>
* <li>To determine the claims_supported to construct the user attributes to be
* returned in the additional user info response.</li>
* </ul>
* ID token validation will be performed as defined in the
* [spec](https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation).
*/
issuer: string;
/**
* The OIDC provider's client secret to enable OIDC code flow.
*/
clientSecret?: string;
/**
* The OIDC provider's response object for OAuth authorization flow.
*/
responseType?: OAuthResponseType;
}
/**
* The Auth provider configuration type.
* {@link BaseAuth.createProviderConfig}.
*/
export type AuthProviderConfig = SAMLAuthProviderConfig | OIDCAuthProviderConfig;
/**
* The request interface for updating a SMS Region Config.
* Configures the regions where users are allowed to send verification SMS.
* This is based on the calling code of the destination phone number.
*/
export type SmsRegionConfig = AllowByDefaultWrap | AllowlistOnlyWrap;
/**
* Mutual exclusive SMS Region Config of AllowByDefault interface
*/
export interface AllowByDefaultWrap {
/**
* Allow every region by default.
*/
allowByDefault: AllowByDefault;
/** @alpha */
allowlistOnly?: never;
}
/**
* Mutually exclusive SMS Region Config of AllowlistOnly interface
*/
export interface AllowlistOnlyWrap {
/**
* Only allowing regions by explicitly adding them to an
* allowlist.
*/
allowlistOnly: AllowlistOnly;
/** @alpha */
allowByDefault?: never;
}
/**
* Defines a policy of allowing every region by default and adding disallowed
* regions to a disallow list.
*/
export interface AllowByDefault {
/**
* Two letter unicode region codes to disallow as defined by
* https://cldr.unicode.org/
* The full list of these region codes is here:
* https://github.com/unicode-cldr/cldr-localenames-full/blob/master/main/en/territories.json
*/
disallowedRegions: string[];
}
/**
* Defines a policy of only allowing regions by explicitly adding them to an
* allowlist.
*/
export interface AllowlistOnly {
/**
* Two letter unicode region codes to allow as defined by
* https://cldr.unicode.org/
* The full list of these region codes is here:
* https://github.com/unicode-cldr/cldr-localenames-full/blob/master/main/en/territories.json
*/
allowedRegions: string[];
}
/**
* Enforcement state of reCAPTCHA protection.
* - 'OFF': Unenforced.
* - 'AUDIT': Create assessment but don't enforce the result.
* - 'ENFORCE': Create assessment and enforce the result.
*/
export type RecaptchaProviderEnforcementState = 'OFF' | 'AUDIT' | 'ENFORCE';
/**
* The actions to take for reCAPTCHA-protected requests.
* - 'BLOCK': The reCAPTCHA-protected request will be blocked.
*/
export type RecaptchaAction = 'BLOCK';
/**
* The config for a reCAPTCHA action rule.
*/
export interface RecaptchaManagedRule {
/**
* The action will be enforced if the reCAPTCHA score of a request is larger than endScore.
*/
endScore: number;
/**
* The action for reCAPTCHA-protected requests.
*/
action?: RecaptchaAction;
}
/**
* The managed rules for toll fraud provider, containing the enforcement status.
* The toll fraud provider contains all SMS related user flows.
*/
export interface RecaptchaTollFraudManagedRule {
/**
* The action will be enforced if the reCAPTCHA score of a request is larger than startScore.
*/
startScore: number;
/**
* The action for reCAPTCHA-protected requests.
*/
action?: RecaptchaAction;
}
/**
* The key's platform type.
*/
export type RecaptchaKeyClientType = 'WEB' | 'IOS' | 'ANDROID';
/**
* The reCAPTCHA key config.
*/
export interface RecaptchaKey {
/**
* The key's client platform type.
*/
type?: RecaptchaKeyClientType;
/**
* The reCAPTCHA site key.
*/
key: string;
}
/**
* The request interface for updating a reCAPTCHA Config.
* By enabling reCAPTCHA Enterprise Integration you are
* agreeing to reCAPTCHA Enterprise
* {@link https://cloud.google.com/terms/service-terms | Term of Service}.
*/
export interface RecaptchaConfig {
/**
* The enforcement state of the email password provider.
*/
emailPasswordEnforcementState?: RecaptchaProviderEnforcementState;
/**
* The enforcement state of the phone provider.
*/
phoneEnforcementState?: RecaptchaProviderEnforcementState;
/**
* The reCAPTCHA managed rules.
*/
managedRules?: RecaptchaManagedRule[];
/**
* The reCAPTCHA keys.
*/
recaptchaKeys?: RecaptchaKey[];
/**
* Whether to use account defender for reCAPTCHA assessment.
* The default value is false.
*/
useAccountDefender?: boolean;
/**
* Whether to use the rCE bot score for reCAPTCHA phone provider.
* Can only be true when the phone_enforcement_state is AUDIT or ENFORCE.
*/
useSmsBotScore?: boolean;
/**
* Whether to use the rCE SMS toll fraud protection risk score for reCAPTCHA phone provider.
* Can only be true when the phone_enforcement_state is AUDIT or ENFORCE.
*/
useSmsTollFraudProtection?: boolean;
/**
* The managed rules for toll fraud provider, containing the enforcement status.
* The toll fraud provider contains all SMS related user flows.
*/
smsTollFraudManagedRules?: RecaptchaTollFraudManagedRule[];
}
/**
* Server side recaptcha configuration.
*/
export interface RecaptchaAuthServerConfig {
emailPasswordEnforcementState?: RecaptchaProviderEnforcementState;
phoneEnforcementState?: RecaptchaProviderEnforcementState;
managedRules?: RecaptchaManagedRule[];
recaptchaKeys?: RecaptchaKey[];
useAccountDefender?: boolean;
useSmsBotScore?: boolean;
useSmsTollFraudProtection?: boolean;
tollFraudManagedRules?: RecaptchaTollFraudManagedRule[];
}
/**
* A password policy configuration for a project or tenant
*/
export interface PasswordPolicyConfig {
/**
* Enforcement state of the password policy
*/
enforcementState?: PasswordPolicyEnforcementState;
/**
* Require users to have a policy-compliant password to sign in
*/
forceUpgradeOnSignin?: boolean;
/**
* The constraints that make up the password strength policy
*/
constraints?: CustomStrengthOptionsConfig;
}
/**
* Configuration for settings related to univeral links (iOS)
* and app links (Android).
*/
export interface MobileLinksConfig {
/**
* Use Firebase Hosting or dynamic link domain as the out-of-band code domain.
*/
domain?: MobileLinksDomain;
}
/**
* Open code in app domain to use for app links and universal links.
*/
export type MobileLinksDomain = 'HOSTING_DOMAIN' | 'FIREBASE_DYNAMIC_LINK_DOMAIN';
/**
* A password policy's enforcement state.
*/
export type PasswordPolicyEnforcementState = 'ENFORCE' | 'OFF';
/**
* Constraints to be enforced on the password policy
*/
export interface CustomStrengthOptionsConfig {
/**
* The password must contain an upper case character
*/
requireUppercase?: boolean;
/**
* The password must contain a lower case character
*/
requireLowercase?: boolean;
/**
* The password must contain a non-alphanumeric character
*/
requireNonAlphanumeric?: boolean;
/**
* The password must contain a number
*/
requireNumeric?: boolean;
/**
* Minimum password length. Valid values are from 6 to 30
*/
minLength?: number;
/**
* Maximum password length. No default max length
*/
maxLength?: number;
}
/**
* Server side password policy configuration.
*/
export interface PasswordPolicyAuthServerConfig {
passwordPolicyEnforcementState?: PasswordPolicyEnforcementState;
passwordPolicyVersions?: PasswordPolicyVersionsAuthServerConfig[];
forceUpgradeOnSignin?: boolean;
}
/**
* Server side password policy versions configuration.
*/
export interface PasswordPolicyVersionsAuthServerConfig {
customStrengthOptions?: CustomStrengthOptionsAuthServerConfig;
}
/**
* Server side password policy constraints configuration.
*/
export interface CustomStrengthOptionsAuthServerConfig {
containsLowercaseCharacter?: boolean;
containsUppercaseCharacter?: boolean;
containsNumericCharacter?: boolean;
containsNonAlphanumericCharacter?: boolean;
minPasswordLength?: number;
maxPasswordLength?: number;
}
/**
* The email privacy configuration of a project or tenant.
*/
export interface EmailPrivacyConfig {
/**
* Whether enhanced email privacy is enabled.
*/
enableImprovedEmailPrivacy?: boolean;
}
export {};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,257 @@
/*! firebase-admin v13.5.0 */
/*!
* 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.
*/
import { App } from '../app/index';
import { ActionCodeSettings as TActionCodeSettings } from './action-code-settings-builder';
import { Auth as TAuth } from './auth';
import { AuthFactorType as TAuthFactorType, AuthProviderConfig as TAuthProviderConfig, AuthProviderConfigFilter as TAuthProviderConfigFilter, CreateRequest as TCreateRequest, CreateMultiFactorInfoRequest as TCreateMultiFactorInfoRequest, CreatePhoneMultiFactorInfoRequest as TCreatePhoneMultiFactorInfoRequest, EmailSignInProviderConfig as TEmailSignInProviderConfig, ListProviderConfigResults as TListProviderConfigResults, MultiFactorCreateSettings as TMultiFactorCreateSettings, MultiFactorConfig as TMultiFactorConfig, MultiFactorConfigState as TMultiFactorConfigState, MultiFactorUpdateSettings as TMultiFactorUpdateSettings, OIDCAuthProviderConfig as TOIDCAuthProviderConfig, OIDCUpdateAuthProviderRequest as TOIDCUpdateAuthProviderRequest, SAMLAuthProviderConfig as TSAMLAuthProviderConfig, SAMLUpdateAuthProviderRequest as TSAMLUpdateAuthProviderRequest, UpdateAuthProviderRequest as TUpdateAuthProviderRequest, UpdateMultiFactorInfoRequest as TUpdateMultiFactorInfoRequest, UpdatePhoneMultiFactorInfoRequest as TUpdatePhoneMultiFactorInfoRequest, UpdateRequest as TUpdateRequest } from './auth-config';
import { BaseAuth as TBaseAuth, DeleteUsersResult as TDeleteUsersResult, GetUsersResult as TGetUsersResult, ListUsersResult as TListUsersResult, SessionCookieOptions as TSessionCookieOptions } from './base-auth';
import { EmailIdentifier as TEmailIdentifier, PhoneIdentifier as TPhoneIdentifier, ProviderIdentifier as TProviderIdentifier, UserIdentifier as TUserIdentifier, UidIdentifier as TUidIdentifier } from './identifier';
import { CreateTenantRequest as TCreateTenantRequest, Tenant as TTenant, UpdateTenantRequest as TUpdateTenantRequest } from './tenant';
import { ListTenantsResult as TListTenantsResult, TenantAwareAuth as TTenantAwareAuth, TenantManager as TTenantManager } from './tenant-manager';
import { DecodedIdToken as TDecodedIdToken, DecodedAuthBlockingToken as TDecodedAuthBlockingToken } from './token-verifier';
import { HashAlgorithmType as THashAlgorithmType, UserImportOptions as TUserImportOptions, UserImportRecord as TUserImportRecord, UserImportResult as TUserImportResult, UserMetadataRequest as TUserMetadataRequest, UserProviderRequest as TUserProviderRequest } from './user-import-builder';
import { MultiFactorInfo as TMultiFactorInfo, MultiFactorSettings as TMultiFactorSettings, PhoneMultiFactorInfo as TPhoneMultiFactorInfo, UserInfo as TUserInfo, UserMetadata as TUserMetadata, UserRecord as TUserRecord } from './user-record';
/**
* Gets the {@link firebase-admin.auth#Auth} service for the default app or a
* given app.
*
* `admin.auth()` can be called with no arguments to access the default app's
* {@link firebase-admin.auth#Auth} service or as `admin.auth(app)` to access the
* {@link firebase-admin.auth#Auth} service associated with a specific app.
*
* @example
* ```javascript
* // Get the Auth service for the default app
* var defaultAuth = admin.auth();
* ```
*
* @example
* ```javascript
* // Get the Auth service for a given app
* var otherAuth = admin.auth(otherApp);
* ```
*
*/
export declare function auth(app?: App): auth.Auth;
export declare namespace auth {
/**
* Type alias to {@link firebase-admin.auth#ActionCodeSettings}.
*/
type ActionCodeSettings = TActionCodeSettings;
/**
* Type alias to {@link firebase-admin.auth#Auth}.
*/
type Auth = TAuth;
/**
* Type alias to {@link firebase-admin.auth#AuthFactorType}.
*/
type AuthFactorType = TAuthFactorType;
/**
* Type alias to {@link firebase-admin.auth#AuthProviderConfig}.
*/
type AuthProviderConfig = TAuthProviderConfig;
/**
* Type alias to {@link firebase-admin.auth#AuthProviderConfigFilter}.
*/
type AuthProviderConfigFilter = TAuthProviderConfigFilter;
/**
* Type alias to {@link firebase-admin.auth#BaseAuth}.
*/
type BaseAuth = TBaseAuth;
/**
* Type alias to {@link firebase-admin.auth#CreateMultiFactorInfoRequest}.
*/
type CreateMultiFactorInfoRequest = TCreateMultiFactorInfoRequest;
/**
* Type alias to {@link firebase-admin.auth#CreatePhoneMultiFactorInfoRequest}.
*/
type CreatePhoneMultiFactorInfoRequest = TCreatePhoneMultiFactorInfoRequest;
/**
* Type alias to {@link firebase-admin.auth#CreateRequest}.
*/
type CreateRequest = TCreateRequest;
/**
* Type alias to {@link firebase-admin.auth#CreateTenantRequest}.
*/
type CreateTenantRequest = TCreateTenantRequest;
/**
* Type alias to {@link firebase-admin.auth#DecodedIdToken}.
*/
type DecodedIdToken = TDecodedIdToken;
/** @alpha */
type DecodedAuthBlockingToken = TDecodedAuthBlockingToken;
/**
* Type alias to {@link firebase-admin.auth#DeleteUsersResult}.
*/
type DeleteUsersResult = TDeleteUsersResult;
/**
* Type alias to {@link firebase-admin.auth#EmailIdentifier}.
*/
type EmailIdentifier = TEmailIdentifier;
/**
* Type alias to {@link firebase-admin.auth#EmailSignInProviderConfig}.
*/
type EmailSignInProviderConfig = TEmailSignInProviderConfig;
/**
* Type alias to {@link firebase-admin.auth#GetUsersResult}.
*/
type GetUsersResult = TGetUsersResult;
/**
* Type alias to {@link firebase-admin.auth#HashAlgorithmType}.
*/
type HashAlgorithmType = THashAlgorithmType;
/**
* Type alias to {@link firebase-admin.auth#ListProviderConfigResults}.
*/
type ListProviderConfigResults = TListProviderConfigResults;
/**
* Type alias to {@link firebase-admin.auth#ListTenantsResult}.
*/
type ListTenantsResult = TListTenantsResult;
/**
* Type alias to {@link firebase-admin.auth#ListUsersResult}.
*/
type ListUsersResult = TListUsersResult;
/**
* Type alias to {@link firebase-admin.auth#MultiFactorCreateSettings}.
*/
type MultiFactorCreateSettings = TMultiFactorCreateSettings;
/**
* Type alias to {@link firebase-admin.auth#MultiFactorConfig}.
*/
type MultiFactorConfig = TMultiFactorConfig;
/**
* Type alias to {@link firebase-admin.auth#MultiFactorConfigState}.
*/
type MultiFactorConfigState = TMultiFactorConfigState;
/**
* Type alias to {@link firebase-admin.auth#MultiFactorInfo}.
*/
type MultiFactorInfo = TMultiFactorInfo;
/**
* Type alias to {@link firebase-admin.auth#MultiFactorUpdateSettings}.
*/
type MultiFactorUpdateSettings = TMultiFactorUpdateSettings;
/**
* Type alias to {@link firebase-admin.auth#MultiFactorSettings}.
*/
type MultiFactorSettings = TMultiFactorSettings;
/**
* Type alias to {@link firebase-admin.auth#OIDCAuthProviderConfig}.
*/
type OIDCAuthProviderConfig = TOIDCAuthProviderConfig;
/**
* Type alias to {@link firebase-admin.auth#OIDCUpdateAuthProviderRequest}.
*/
type OIDCUpdateAuthProviderRequest = TOIDCUpdateAuthProviderRequest;
/**
* Type alias to {@link firebase-admin.auth#PhoneIdentifier}.
*/
type PhoneIdentifier = TPhoneIdentifier;
/**
* Type alias to {@link firebase-admin.auth#PhoneMultiFactorInfo}.
*/
type PhoneMultiFactorInfo = TPhoneMultiFactorInfo;
/**
* Type alias to {@link firebase-admin.auth#ProviderIdentifier}.
*/
type ProviderIdentifier = TProviderIdentifier;
/**
* Type alias to {@link firebase-admin.auth#SAMLAuthProviderConfig}.
*/
type SAMLAuthProviderConfig = TSAMLAuthProviderConfig;
/**
* Type alias to {@link firebase-admin.auth#SAMLUpdateAuthProviderRequest}.
*/
type SAMLUpdateAuthProviderRequest = TSAMLUpdateAuthProviderRequest;
/**
* Type alias to {@link firebase-admin.auth#SessionCookieOptions}.
*/
type SessionCookieOptions = TSessionCookieOptions;
/**
* Type alias to {@link firebase-admin.auth#Tenant}.
*/
type Tenant = TTenant;
/**
* Type alias to {@link firebase-admin.auth#TenantAwareAuth}.
*/
type TenantAwareAuth = TTenantAwareAuth;
/**
* Type alias to {@link firebase-admin.auth#TenantManager}.
*/
type TenantManager = TTenantManager;
/**
* Type alias to {@link firebase-admin.auth#UidIdentifier}.
*/
type UidIdentifier = TUidIdentifier;
/**
* Type alias to {@link firebase-admin.auth#UpdateAuthProviderRequest}.
*/
type UpdateAuthProviderRequest = TUpdateAuthProviderRequest;
/**
* Type alias to {@link firebase-admin.auth#UpdateMultiFactorInfoRequest}.
*/
type UpdateMultiFactorInfoRequest = TUpdateMultiFactorInfoRequest;
/**
* Type alias to {@link firebase-admin.auth#UpdatePhoneMultiFactorInfoRequest}.
*/
type UpdatePhoneMultiFactorInfoRequest = TUpdatePhoneMultiFactorInfoRequest;
/**
* Type alias to {@link firebase-admin.auth#UpdateRequest}.
*/
type UpdateRequest = TUpdateRequest;
/**
* Type alias to {@link firebase-admin.auth#UpdateTenantRequest}.
*/
type UpdateTenantRequest = TUpdateTenantRequest;
/**
* Type alias to {@link firebase-admin.auth#UserIdentifier}.
*/
type UserIdentifier = TUserIdentifier;
/**
* Type alias to {@link firebase-admin.auth#UserImportOptions}.
*/
type UserImportOptions = TUserImportOptions;
/**
* Type alias to {@link firebase-admin.auth#UserImportRecord}.
*/
type UserImportRecord = TUserImportRecord;
/**
* Type alias to {@link firebase-admin.auth#UserImportResult}.
*/
type UserImportResult = TUserImportResult;
/**
* Type alias to {@link firebase-admin.auth#UserInfo}.
*/
type UserInfo = TUserInfo;
/**
* Type alias to {@link firebase-admin.auth#UserMetadata}.
*/
type UserMetadata = TUserMetadata;
/**
* Type alias to {@link firebase-admin.auth#UserMetadataRequest}.
*/
type UserMetadataRequest = TUserMetadataRequest;
/**
* Type alias to {@link firebase-admin.auth#UserProviderRequest}.
*/
type UserProviderRequest = TUserProviderRequest;
/**
* Type alias to {@link firebase-admin.auth#UserRecord}.
*/
type UserRecord = TUserRecord;
}

View File

@@ -0,0 +1,18 @@
/*! firebase-admin v13.5.0 */
"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 });

48
server/node_modules/firebase-admin/lib/auth/auth.d.ts generated vendored Normal file
View File

@@ -0,0 +1,48 @@
/*! firebase-admin v13.5.0 */
/*!
* @license
* Copyright 2017 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.
*/
import { App } from '../app/index';
import { TenantManager } from './tenant-manager';
import { BaseAuth } from './base-auth';
import { ProjectConfigManager } from './project-config-manager';
/**
* Auth service bound to the provided app.
* An Auth instance can have multiple tenants.
*/
export declare class Auth extends BaseAuth {
private readonly tenantManager_;
private readonly projectConfigManager_;
private readonly app_;
/**
* Returns the app associated with this Auth instance.
*
* @returns The app associated with this Auth instance.
*/
get app(): App;
/**
* Returns the tenant manager instance associated with the current project.
*
* @returns The tenant manager instance associated with the current project.
*/
tenantManager(): TenantManager;
/**
* Returns the project config manager instance associated with the current project.
*
* @returns The project config manager instance associated with the current project.
*/
projectConfigManager(): ProjectConfigManager;
}

66
server/node_modules/firebase-admin/lib/auth/auth.js generated vendored Normal file
View File

@@ -0,0 +1,66 @@
/*! firebase-admin v13.5.0 */
"use strict";
/*!
* @license
* Copyright 2017 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.Auth = void 0;
const auth_api_request_1 = require("./auth-api-request");
const tenant_manager_1 = require("./tenant-manager");
const base_auth_1 = require("./base-auth");
const project_config_manager_1 = require("./project-config-manager");
/**
* Auth service bound to the provided app.
* An Auth instance can have multiple tenants.
*/
class Auth extends base_auth_1.BaseAuth {
/**
* @param app - The app for this Auth service.
* @constructor
* @internal
*/
constructor(app) {
super(app, new auth_api_request_1.AuthRequestHandler(app));
this.app_ = app;
this.tenantManager_ = new tenant_manager_1.TenantManager(app);
this.projectConfigManager_ = new project_config_manager_1.ProjectConfigManager(app);
}
/**
* Returns the app associated with this Auth instance.
*
* @returns The app associated with this Auth instance.
*/
get app() {
return this.app_;
}
/**
* Returns the tenant manager instance associated with the current project.
*
* @returns The tenant manager instance associated with the current project.
*/
tenantManager() {
return this.tenantManager_;
}
/**
* Returns the project config manager instance associated with the current project.
*
* @returns The project config manager instance associated with the current project.
*/
projectConfigManager() {
return this.projectConfigManager_;
}
}
exports.Auth = Auth;

View File

@@ -0,0 +1,640 @@
/*! firebase-admin v13.5.0 */
/*!
* 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.
*/
import { FirebaseArrayIndexError } from '../app';
import { DecodedIdToken, DecodedAuthBlockingToken } from './token-verifier';
import { AuthProviderConfig, AuthProviderConfigFilter, ListProviderConfigResults, UpdateAuthProviderRequest, CreateRequest, UpdateRequest } from './auth-config';
import { UserRecord } from './user-record';
import { UserIdentifier } from './identifier';
import { UserImportOptions, UserImportRecord, UserImportResult } from './user-import-builder';
import { ActionCodeSettings } from './action-code-settings-builder';
/** Represents the result of the {@link BaseAuth.getUsers} API. */
export interface GetUsersResult {
/**
* Set of user records, corresponding to the set of users that were
* requested. Only users that were found are listed here. The result set is
* unordered.
*/
users: UserRecord[];
/** Set of identifiers that were requested, but not found. */
notFound: UserIdentifier[];
}
/**
* Interface representing the object returned from a
* {@link BaseAuth.listUsers} operation. Contains the list
* of users for the current batch and the next page token if available.
*/
export interface ListUsersResult {
/**
* The list of {@link UserRecord} objects for the
* current downloaded batch.
*/
users: UserRecord[];
/**
* The next page token if available. This is needed for the next batch download.
*/
pageToken?: string;
}
/**
* Represents the result of the {@link BaseAuth.deleteUsers}.
* API.
*/
export interface DeleteUsersResult {
/**
* The number of user records that failed to be deleted (possibly zero).
*/
failureCount: number;
/**
* The number of users that were deleted successfully (possibly zero).
* Users that did not exist prior to calling `deleteUsers()` are
* considered to be successfully deleted.
*/
successCount: number;
/**
* A list of `FirebaseArrayIndexError` instances describing the errors that
* were encountered during the deletion. Length of this list is equal to
* the return value of {@link DeleteUsersResult.failureCount}.
*/
errors: FirebaseArrayIndexError[];
}
/**
* Interface representing the session cookie options needed for the
* {@link BaseAuth.createSessionCookie} method.
*/
export interface SessionCookieOptions {
/**
* The session cookie custom expiration in milliseconds. The minimum allowed is
* 5 minutes and the maxium allowed is 2 weeks.
*/
expiresIn: number;
}
/**
* Common parent interface for both `Auth` and `TenantAwareAuth` APIs.
*/
export declare abstract class BaseAuth {
/**
* 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: string, developerClaims?: object): Promise<string>;
/**
* 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: string, checkRevoked?: boolean): Promise<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: string): Promise<UserRecord>;
/**
* 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: string): Promise<UserRecord>;
/**
* 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: string): Promise<UserRecord>;
/**
* 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: string, uid: string): Promise<UserRecord>;
/**
* 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: UserIdentifier[]): Promise<GetUsersResult>;
/**
* 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?: number, pageToken?: string): Promise<ListUsersResult>;
/**
* 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: CreateRequest): Promise<UserRecord>;
/**
* 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: string): Promise<void>;
/**
* 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: string[]): Promise<DeleteUsersResult>;
/**
* 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: string, properties: UpdateRequest): Promise<UserRecord>;
/**
* 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: string, customUserClaims: object | null): Promise<void>;
/**
* 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: string): Promise<void>;
/**
* 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: UserImportRecord[], options?: UserImportOptions): Promise<UserImportResult>;
/**
* 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: string, sessionCookieOptions: SessionCookieOptions): Promise<string>;
/**
* 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: string, checkRevoked?: boolean): Promise<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,
* linkDomain: 'project-id.firebaseapp.com'
* };
* 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: string, actionCodeSettings?: ActionCodeSettings): Promise<string>;
/**
* 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,
* linkDomain: 'project-id.firebaseapp.com'
* };
* 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: string, actionCodeSettings?: ActionCodeSettings): Promise<string>;
/**
* 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: string, newEmail: string, actionCodeSettings?: ActionCodeSettings): Promise<string>;
/**
* 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,
* linkDomain: 'project-id.firebaseapp.com'
* };
* 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: string, actionCodeSettings: ActionCodeSettings): Promise<string>;
/**
* 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: AuthProviderConfigFilter): Promise<ListProviderConfigResults>;
/**
* 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: string): Promise<AuthProviderConfig>;
/**
* 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: string): Promise<void>;
/**
* 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: string, updatedConfig: UpdateAuthProviderRequest): Promise<AuthProviderConfig>;
/**
* 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: AuthProviderConfig): Promise<AuthProviderConfig>;
/** @alpha */
_verifyAuthBlockingToken(token: string, audience?: string): Promise<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.
*/
private verifyDecodedJWTNotRevokedOrDisabled;
}

View File

@@ -0,0 +1,981 @@
/*! firebase-admin v13.5.0 */
"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 = void 0;
exports.createFirebaseTokenGenerator = createFirebaseTokenGenerator;
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);
}
}
/**
* 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,
* linkDomain: 'project-id.firebaseapp.com'
* };
* 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,
* linkDomain: 'project-id.firebaseapp.com'
* };
* 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,
* linkDomain: 'project-id.firebaseapp.com'
* };
* 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;

View File

@@ -0,0 +1,57 @@
/*! firebase-admin v13.5.0 */
/*!
* Copyright 2020 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.
*/
/**
* Used for looking up an account by uid.
*
* See {@link BaseAuth.getUsers}.
*/
export interface UidIdentifier {
uid: string;
}
/**
* Used for looking up an account by email.
*
* See {@link BaseAuth.getUsers}.
*/
export interface EmailIdentifier {
email: string;
}
/**
* Used for looking up an account by phone number.
*
* See {@link BaseAuth.getUsers}.
*/
export interface PhoneIdentifier {
phoneNumber: string;
}
/**
* Used for looking up an account by federated provider.
*
* See {@link BaseAuth.getUsers}.
*/
export interface ProviderIdentifier {
providerId: string;
providerUid: string;
}
/**
* Identifies a user to be looked up.
*/
export type UserIdentifier = UidIdentifier | EmailIdentifier | PhoneIdentifier | ProviderIdentifier;
export declare function isUidIdentifier(id: UserIdentifier): id is UidIdentifier;
export declare function isEmailIdentifier(id: UserIdentifier): id is EmailIdentifier;
export declare function isPhoneIdentifier(id: UserIdentifier): id is PhoneIdentifier;
export declare function isProviderIdentifier(id: ProviderIdentifier): id is ProviderIdentifier;

View File

@@ -0,0 +1,39 @@
/*! firebase-admin v13.5.0 */
"use strict";
/*!
* Copyright 2020 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.isUidIdentifier = isUidIdentifier;
exports.isEmailIdentifier = isEmailIdentifier;
exports.isPhoneIdentifier = isPhoneIdentifier;
exports.isProviderIdentifier = isProviderIdentifier;
/*
* User defined type guards. See
* https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards
*/
function isUidIdentifier(id) {
return id.uid !== undefined;
}
function isEmailIdentifier(id) {
return id.email !== undefined;
}
function isPhoneIdentifier(id) {
return id.phoneNumber !== undefined;
}
function isProviderIdentifier(id) {
const pid = id;
return pid.providerId !== undefined && pid.providerUid !== undefined;
}

58
server/node_modules/firebase-admin/lib/auth/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,58 @@
/*! firebase-admin v13.5.0 */
/*!
* Copyright 2020 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.
*/
/**
* Firebase Authentication.
*
* @packageDocumentation
*/
import { App } from '../app/index';
import { Auth } from './auth';
/**
* Gets the {@link Auth} service for the default app or a
* given app.
*
* `getAuth()` can be called with no arguments to access the default app's
* {@link Auth} service or as `getAuth(app)` to access the
* {@link Auth} service associated with a specific app.
*
* @example
* ```javascript
* // Get the Auth service for the default app
* const defaultAuth = getAuth();
* ```
*
* @example
* ```javascript
* // Get the Auth service for a given app
* const otherAuth = getAuth(otherApp);
* ```
*
*/
export declare function getAuth(app?: App): Auth;
export { ActionCodeSettings } from './action-code-settings-builder';
export { Auth, } from './auth';
export { AllowByDefault, AllowByDefaultWrap, AllowlistOnly, AllowlistOnlyWrap, AuthFactorType, AuthProviderConfig, AuthProviderConfigFilter, BaseAuthProviderConfig, BaseCreateMultiFactorInfoRequest, BaseUpdateMultiFactorInfoRequest, CreateMultiFactorInfoRequest, CreatePhoneMultiFactorInfoRequest, CreateRequest, EmailSignInProviderConfig, ListProviderConfigResults, MultiFactorConfig, MultiFactorConfigState, MultiFactorCreateSettings, MultiFactorUpdateSettings, MultiFactorProviderConfig, OAuthResponseType, OIDCAuthProviderConfig, OIDCUpdateAuthProviderRequest, RecaptchaAction, RecaptchaConfig, RecaptchaKey, RecaptchaKeyClientType, RecaptchaManagedRule, RecaptchaTollFraudManagedRule, RecaptchaProviderEnforcementState, SAMLAuthProviderConfig, SAMLUpdateAuthProviderRequest, SmsRegionConfig, UserProvider, UpdateAuthProviderRequest, UpdateMultiFactorInfoRequest, UpdatePhoneMultiFactorInfoRequest, UpdateRequest, TotpMultiFactorProviderConfig, PasswordPolicyConfig, PasswordPolicyEnforcementState, CustomStrengthOptionsConfig, EmailPrivacyConfig, MobileLinksConfig, MobileLinksDomain, } from './auth-config';
export { BaseAuth, DeleteUsersResult, GetUsersResult, ListUsersResult, SessionCookieOptions, } from './base-auth';
export { EmailIdentifier, PhoneIdentifier, ProviderIdentifier, UidIdentifier, UserIdentifier, } from './identifier';
export { CreateTenantRequest, Tenant, UpdateTenantRequest, } from './tenant';
export { ListTenantsResult, TenantAwareAuth, TenantManager, } from './tenant-manager';
export { UpdateProjectConfigRequest, ProjectConfig, } from './project-config';
export { ProjectConfigManager, } from './project-config-manager';
export { DecodedIdToken, DecodedAuthBlockingToken } from './token-verifier';
export { HashAlgorithmType, UserImportOptions, UserImportRecord, UserImportResult, UserMetadataRequest, UserProviderRequest, } from './user-import-builder';
export { MultiFactorInfo, MultiFactorSettings, PhoneMultiFactorInfo, UserInfo, UserMetadata, UserRecord, } from './user-record';
export { FirebaseAuthError, AuthClientErrorCode, } from '../utils/error';

78
server/node_modules/firebase-admin/lib/auth/index.js generated vendored Normal file
View File

@@ -0,0 +1,78 @@
/*! firebase-admin v13.5.0 */
"use strict";
/*!
* Copyright 2020 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.AuthClientErrorCode = exports.FirebaseAuthError = exports.UserRecord = exports.UserMetadata = exports.UserInfo = exports.PhoneMultiFactorInfo = exports.MultiFactorSettings = exports.MultiFactorInfo = exports.ProjectConfigManager = exports.ProjectConfig = exports.TenantManager = exports.TenantAwareAuth = exports.Tenant = exports.BaseAuth = exports.Auth = void 0;
exports.getAuth = getAuth;
/**
* Firebase Authentication.
*
* @packageDocumentation
*/
const index_1 = require("../app/index");
const auth_1 = require("./auth");
/**
* Gets the {@link Auth} service for the default app or a
* given app.
*
* `getAuth()` can be called with no arguments to access the default app's
* {@link Auth} service or as `getAuth(app)` to access the
* {@link Auth} service associated with a specific app.
*
* @example
* ```javascript
* // Get the Auth service for the default app
* const defaultAuth = getAuth();
* ```
*
* @example
* ```javascript
* // Get the Auth service for a given app
* const otherAuth = getAuth(otherApp);
* ```
*
*/
function getAuth(app) {
if (typeof app === 'undefined') {
app = (0, index_1.getApp)();
}
const firebaseApp = app;
return firebaseApp.getOrInitService('auth', (app) => new auth_1.Auth(app));
}
var auth_2 = require("./auth");
Object.defineProperty(exports, "Auth", { enumerable: true, get: function () { return auth_2.Auth; } });
var base_auth_1 = require("./base-auth");
Object.defineProperty(exports, "BaseAuth", { enumerable: true, get: function () { return base_auth_1.BaseAuth; } });
var tenant_1 = require("./tenant");
Object.defineProperty(exports, "Tenant", { enumerable: true, get: function () { return tenant_1.Tenant; } });
var tenant_manager_1 = require("./tenant-manager");
Object.defineProperty(exports, "TenantAwareAuth", { enumerable: true, get: function () { return tenant_manager_1.TenantAwareAuth; } });
Object.defineProperty(exports, "TenantManager", { enumerable: true, get: function () { return tenant_manager_1.TenantManager; } });
var project_config_1 = require("./project-config");
Object.defineProperty(exports, "ProjectConfig", { enumerable: true, get: function () { return project_config_1.ProjectConfig; } });
var project_config_manager_1 = require("./project-config-manager");
Object.defineProperty(exports, "ProjectConfigManager", { enumerable: true, get: function () { return project_config_manager_1.ProjectConfigManager; } });
var user_record_1 = require("./user-record");
Object.defineProperty(exports, "MultiFactorInfo", { enumerable: true, get: function () { return user_record_1.MultiFactorInfo; } });
Object.defineProperty(exports, "MultiFactorSettings", { enumerable: true, get: function () { return user_record_1.MultiFactorSettings; } });
Object.defineProperty(exports, "PhoneMultiFactorInfo", { enumerable: true, get: function () { return user_record_1.PhoneMultiFactorInfo; } });
Object.defineProperty(exports, "UserInfo", { enumerable: true, get: function () { return user_record_1.UserInfo; } });
Object.defineProperty(exports, "UserMetadata", { enumerable: true, get: function () { return user_record_1.UserMetadata; } });
Object.defineProperty(exports, "UserRecord", { enumerable: true, get: function () { return user_record_1.UserRecord; } });
var error_1 = require("../utils/error");
Object.defineProperty(exports, "FirebaseAuthError", { enumerable: true, get: function () { return error_1.FirebaseAuthError; } });
Object.defineProperty(exports, "AuthClientErrorCode", { enumerable: true, get: function () { return error_1.AuthClientErrorCode; } });

View File

@@ -0,0 +1,22 @@
/*! firebase-admin v13.5.0 */
import { ProjectConfig, UpdateProjectConfigRequest } from './project-config';
/**
* Manages (gets and updates) the current project config.
*/
export declare class ProjectConfigManager {
private readonly authRequestHandler;
/**
* Get the project configuration.
*
* @returns A promise fulfilled with the project configuration.
*/
getProjectConfig(): Promise<ProjectConfig>;
/**
* Updates an existing project configuration.
*
* @param projectConfigOptions - The properties to update on the project.
*
* @returns A promise fulfilled with the updated project config.
*/
updateProjectConfig(projectConfigOptions: UpdateProjectConfigRequest): Promise<ProjectConfig>;
}

View File

@@ -0,0 +1,47 @@
/*! firebase-admin v13.5.0 */
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProjectConfigManager = void 0;
const project_config_1 = require("./project-config");
const auth_api_request_1 = require("./auth-api-request");
/**
* Manages (gets and updates) the current project config.
*/
class ProjectConfigManager {
/**
* Initializes a ProjectConfigManager instance for a specified FirebaseApp.
*
* @param app - The app for this ProjectConfigManager instance.
*
* @constructor
* @internal
*/
constructor(app) {
this.authRequestHandler = new auth_api_request_1.AuthRequestHandler(app);
}
/**
* Get the project configuration.
*
* @returns A promise fulfilled with the project configuration.
*/
getProjectConfig() {
return this.authRequestHandler.getProjectConfig()
.then((response) => {
return new project_config_1.ProjectConfig(response);
});
}
/**
* Updates an existing project configuration.
*
* @param projectConfigOptions - The properties to update on the project.
*
* @returns A promise fulfilled with the updated project config.
*/
updateProjectConfig(projectConfigOptions) {
return this.authRequestHandler.updateProjectConfig(projectConfigOptions)
.then((response) => {
return new project_config_1.ProjectConfig(response);
});
}
}
exports.ProjectConfigManager = ProjectConfigManager;

View File

@@ -0,0 +1,111 @@
/*! firebase-admin v13.5.0 */
import { SmsRegionConfig, MultiFactorConfig, MultiFactorAuthServerConfig, RecaptchaConfig, RecaptchaAuthServerConfig, PasswordPolicyAuthServerConfig, PasswordPolicyConfig, EmailPrivacyConfig, MobileLinksConfig } from './auth-config';
/**
* Interface representing the properties to update on the provided project config.
*/
export interface UpdateProjectConfigRequest {
/**
* The SMS configuration to update on the project.
*/
smsRegionConfig?: SmsRegionConfig;
/**
* The multi-factor auth configuration to update on the project.
*/
multiFactorConfig?: MultiFactorConfig;
/**
* The reCAPTCHA configuration to update on the project.
* By enabling reCAPTCHA Enterprise integration, you are
* agreeing to the reCAPTCHA Enterprise
* {@link https://cloud.google.com/terms/service-terms | Term of Service}.
*/
recaptchaConfig?: RecaptchaConfig;
/**
* The password policy configuration to update on the project
*/
passwordPolicyConfig?: PasswordPolicyConfig;
/**
* The email privacy configuration to update on the project
*/
emailPrivacyConfig?: EmailPrivacyConfig;
/**
* The mobile links configuration for the project
*/
mobileLinksConfig?: MobileLinksConfig;
}
/**
* Response received when getting or updating the project config.
*/
export interface ProjectConfigServerResponse {
smsRegionConfig?: SmsRegionConfig;
mfa?: MultiFactorAuthServerConfig;
recaptchaConfig?: RecaptchaAuthServerConfig;
passwordPolicyConfig?: PasswordPolicyAuthServerConfig;
emailPrivacyConfig?: EmailPrivacyConfig;
mobileLinksConfig?: MobileLinksConfig;
}
/**
* Request to update the project config.
*/
export interface ProjectConfigClientRequest {
smsRegionConfig?: SmsRegionConfig;
mfa?: MultiFactorAuthServerConfig;
recaptchaConfig?: RecaptchaAuthServerConfig;
passwordPolicyConfig?: PasswordPolicyAuthServerConfig;
emailPrivacyConfig?: EmailPrivacyConfig;
mobileLinksConfig?: MobileLinksConfig;
}
/**
* Represents a project configuration.
*/
export declare class ProjectConfig {
/**
* The SMS Regions Config for the project.
* Configures the regions where users are allowed to send verification SMS.
* This is based on the calling code of the destination phone number.
*/
readonly smsRegionConfig?: SmsRegionConfig;
/**
* The project's multi-factor auth configuration.
* Supports only phone and TOTP.
*/
private readonly multiFactorConfig_?;
/**
* The multi-factor auth configuration.
*/
get multiFactorConfig(): MultiFactorConfig | undefined;
/**
* The reCAPTCHA configuration to update on the project.
* By enabling reCAPTCHA Enterprise integration, you are
* agreeing to the reCAPTCHA Enterprise
* {@link https://cloud.google.com/terms/service-terms | Term of Service}.
*/
private readonly recaptchaConfig_?;
/**
* The reCAPTCHA configuration.
*/
get recaptchaConfig(): RecaptchaConfig | undefined;
/**
* The password policy configuration for the project
*/
readonly passwordPolicyConfig?: PasswordPolicyConfig;
/**
* The email privacy configuration for the project
*/
readonly emailPrivacyConfig?: EmailPrivacyConfig;
/**
* The mobile links configuration for the project
*/
readonly mobileLinksConfig?: MobileLinksConfig;
/**
* Validates a project config options object. Throws an error on failure.
*
* @param request - The project config options object to validate.
*/
private static validate;
/**
* Returns a JSON-serializable representation of this object.
*
* @returns A JSON-serializable representation of this object.
*/
toJSON(): object;
}

View File

@@ -0,0 +1,183 @@
/*! firebase-admin v13.5.0 */
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProjectConfig = void 0;
/*!
* Copyright 2022 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.
*/
const validator = require("../utils/validator");
const error_1 = require("../utils/error");
const auth_config_1 = require("./auth-config");
const deep_copy_1 = require("../utils/deep-copy");
/**
* Represents a project configuration.
*/
class ProjectConfig {
/**
* The multi-factor auth configuration.
*/
get multiFactorConfig() {
return this.multiFactorConfig_;
}
/**
* The reCAPTCHA configuration.
*/
get recaptchaConfig() {
return this.recaptchaConfig_;
}
/**
* Validates a project config options object. Throws an error on failure.
*
* @param request - The project config options object to validate.
*/
static validate(request) {
if (!validator.isNonNullObject(request)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"UpdateProjectConfigRequest" must be a valid non-null object.');
}
const validKeys = {
smsRegionConfig: true,
multiFactorConfig: true,
recaptchaConfig: true,
passwordPolicyConfig: true,
emailPrivacyConfig: true,
mobileLinksConfig: true,
};
// Check for unsupported top level attributes.
for (const key in request) {
if (!(key in validKeys)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, `"${key}" is not a valid UpdateProjectConfigRequest parameter.`);
}
}
// Validate SMS Regions Config if provided.
if (typeof request.smsRegionConfig !== 'undefined') {
auth_config_1.SmsRegionsAuthConfig.validate(request.smsRegionConfig);
}
// Validate Multi Factor Config if provided
if (typeof request.multiFactorConfig !== 'undefined') {
auth_config_1.MultiFactorAuthConfig.validate(request.multiFactorConfig);
}
// Validate reCAPTCHA config attribute.
if (typeof request.recaptchaConfig !== 'undefined') {
auth_config_1.RecaptchaAuthConfig.validate(request.recaptchaConfig);
}
// Validate Password policy Config if provided
if (typeof request.passwordPolicyConfig !== 'undefined') {
auth_config_1.PasswordPolicyAuthConfig.validate(request.passwordPolicyConfig);
}
// Validate Email Privacy Config if provided.
if (typeof request.emailPrivacyConfig !== 'undefined') {
auth_config_1.EmailPrivacyAuthConfig.validate(request.emailPrivacyConfig);
}
// Validate Mobile Links Config if provided.
if (typeof request.mobileLinksConfig !== 'undefined') {
auth_config_1.MobileLinksAuthConfig.validate(request.mobileLinksConfig);
}
}
/**
* Build the corresponding server request for a UpdateProjectConfigRequest object.
* @param configOptions - The properties to convert to a server request.
* @returns The equivalent server request.
*
* @internal
*/
static buildServerRequest(configOptions) {
ProjectConfig.validate(configOptions);
const request = {};
if (typeof configOptions.smsRegionConfig !== 'undefined') {
request.smsRegionConfig = configOptions.smsRegionConfig;
}
if (typeof configOptions.multiFactorConfig !== 'undefined') {
request.mfa = auth_config_1.MultiFactorAuthConfig.buildServerRequest(configOptions.multiFactorConfig);
}
if (typeof configOptions.recaptchaConfig !== 'undefined') {
request.recaptchaConfig = auth_config_1.RecaptchaAuthConfig.buildServerRequest(configOptions.recaptchaConfig);
}
if (typeof configOptions.passwordPolicyConfig !== 'undefined') {
request.passwordPolicyConfig = auth_config_1.PasswordPolicyAuthConfig.buildServerRequest(configOptions.passwordPolicyConfig);
}
if (typeof configOptions.emailPrivacyConfig !== 'undefined') {
request.emailPrivacyConfig = configOptions.emailPrivacyConfig;
}
if (typeof configOptions.mobileLinksConfig !== 'undefined') {
request.mobileLinksConfig = configOptions.mobileLinksConfig;
}
return request;
}
/**
* The Project Config object constructor.
*
* @param response - The server side response used to initialize the Project Config object.
* @constructor
* @internal
*/
constructor(response) {
if (typeof response.smsRegionConfig !== 'undefined') {
this.smsRegionConfig = response.smsRegionConfig;
}
//Backend API returns "mfa" in case of project config and "mfaConfig" in case of tenant config.
//The SDK exposes it as multiFactorConfig always.
if (typeof response.mfa !== 'undefined') {
this.multiFactorConfig_ = new auth_config_1.MultiFactorAuthConfig(response.mfa);
}
if (typeof response.recaptchaConfig !== 'undefined') {
this.recaptchaConfig_ = new auth_config_1.RecaptchaAuthConfig(response.recaptchaConfig);
}
if (typeof response.passwordPolicyConfig !== 'undefined') {
this.passwordPolicyConfig = new auth_config_1.PasswordPolicyAuthConfig(response.passwordPolicyConfig);
}
if (typeof response.emailPrivacyConfig !== 'undefined') {
this.emailPrivacyConfig = response.emailPrivacyConfig;
}
if (typeof response.mobileLinksConfig !== 'undefined') {
this.mobileLinksConfig = response.mobileLinksConfig;
}
}
/**
* Returns a JSON-serializable representation of this object.
*
* @returns A JSON-serializable representation of this object.
*/
toJSON() {
// JSON serialization
const json = {
smsRegionConfig: (0, deep_copy_1.deepCopy)(this.smsRegionConfig),
multiFactorConfig: (0, deep_copy_1.deepCopy)(this.multiFactorConfig),
recaptchaConfig: (0, deep_copy_1.deepCopy)(this.recaptchaConfig),
passwordPolicyConfig: (0, deep_copy_1.deepCopy)(this.passwordPolicyConfig),
emailPrivacyConfig: (0, deep_copy_1.deepCopy)(this.emailPrivacyConfig),
mobileLinksConfig: (0, deep_copy_1.deepCopy)(this.mobileLinksConfig),
};
if (typeof json.smsRegionConfig === 'undefined') {
delete json.smsRegionConfig;
}
if (typeof json.multiFactorConfig === 'undefined') {
delete json.multiFactorConfig;
}
if (typeof json.recaptchaConfig === 'undefined') {
delete json.recaptchaConfig;
}
if (typeof json.passwordPolicyConfig === 'undefined') {
delete json.passwordPolicyConfig;
}
if (typeof json.emailPrivacyConfig === 'undefined') {
delete json.emailPrivacyConfig;
}
if (typeof json.mobileLinksConfig === 'undefined') {
delete json.mobileLinksConfig;
}
return json;
}
}
exports.ProjectConfig = ProjectConfig;

View File

@@ -0,0 +1,146 @@
/*! firebase-admin v13.5.0 */
/*!
* Copyright 2019 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.
*/
import { BaseAuth, SessionCookieOptions } from './base-auth';
import { Tenant, CreateTenantRequest, UpdateTenantRequest } from './tenant';
import { DecodedIdToken } from './token-verifier';
/**
* Interface representing the object returned from a
* {@link TenantManager.listTenants}
* operation.
* Contains the list of tenants for the current batch and the next page token if available.
*/
export interface ListTenantsResult {
/**
* The list of {@link Tenant} objects for the downloaded batch.
*/
tenants: Tenant[];
/**
* The next page token if available. This is needed for the next batch download.
*/
pageToken?: string;
}
/**
* Tenant-aware `Auth` interface used for managing users, configuring SAML/OIDC providers,
* generating email links for password reset, email verification, etc for specific tenants.
*
* Multi-tenancy 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}.
*
* Each tenant contains its own identity providers, settings and sets of users.
* Using `TenantAwareAuth`, users for a specific tenant and corresponding OIDC/SAML
* configurations can also be managed, ID tokens for users signed in to a specific tenant
* can be verified, and email action links can also be generated for users belonging to the
* tenant.
*
* `TenantAwareAuth` instances for a specific `tenantId` can be instantiated by calling
* {@link TenantManager.authForTenant}.
*/
export declare class TenantAwareAuth extends BaseAuth {
/**
* The tenant identifier corresponding to this `TenantAwareAuth` instance.
* All calls to the user management APIs, OIDC/SAML provider management APIs, email link
* generation APIs, etc will only be applied within the scope of this tenant.
*/
readonly tenantId: string;
/**
* {@inheritdoc BaseAuth.verifyIdToken}
*/
verifyIdToken(idToken: string, checkRevoked?: boolean): Promise<DecodedIdToken>;
/**
* {@inheritdoc BaseAuth.createSessionCookie}
*/
createSessionCookie(idToken: string, sessionCookieOptions: SessionCookieOptions): Promise<string>;
/**
* {@inheritdoc BaseAuth.verifySessionCookie}
*/
verifySessionCookie(sessionCookie: string, checkRevoked?: boolean): Promise<DecodedIdToken>;
}
/**
* Defines the tenant manager used to help manage tenant related operations.
* This includes:
* <ul>
* <li>The ability to create, update, list, get and delete tenants for the underlying
* project.</li>
* <li>Getting a `TenantAwareAuth` instance for running Auth related operations
* (user management, provider configuration management, token verification,
* email link generation, etc) in the context of a specified tenant.</li>
* </ul>
*/
export declare class TenantManager {
private readonly app;
private readonly authRequestHandler;
private readonly tenantsMap;
/**
* Returns a `TenantAwareAuth` instance bound to the given tenant ID.
*
* @param tenantId - The tenant ID whose `TenantAwareAuth` instance is to be returned.
*
* @returns The `TenantAwareAuth` instance corresponding to this tenant identifier.
*/
authForTenant(tenantId: string): TenantAwareAuth;
/**
* Gets the tenant configuration for the tenant corresponding to a given `tenantId`.
*
* @param tenantId - The tenant identifier corresponding to the tenant whose data to fetch.
*
* @returns A promise fulfilled with the tenant configuration to the provided `tenantId`.
*/
getTenant(tenantId: string): Promise<Tenant>;
/**
* Retrieves a list of tenants (single batch only) with a size of `maxResults`
* starting from the offset as specified by `pageToken`. This is used to
* retrieve all the tenants of a specified project in batches.
*
* @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
* tenants starting without any offset.
*
* @returns A promise that resolves with
* a batch of downloaded tenants and the next page token.
*/
listTenants(maxResults?: number, pageToken?: string): Promise<ListTenantsResult>;
/**
* Deletes an existing tenant.
*
* @param tenantId - The `tenantId` corresponding to the tenant to delete.
*
* @returns An empty promise fulfilled once the tenant has been deleted.
*/
deleteTenant(tenantId: string): Promise<void>;
/**
* Creates a new tenant.
* When creating new tenants, tenants that use separate billing and quota will require their
* own project and must be defined as `full_service`.
*
* @param tenantOptions - The properties to set on the new tenant configuration to be created.
*
* @returns A promise fulfilled with the tenant configuration corresponding to the newly
* created tenant.
*/
createTenant(tenantOptions: CreateTenantRequest): Promise<Tenant>;
/**
* Updates an existing tenant configuration.
*
* @param tenantId - The `tenantId` corresponding to the tenant to delete.
* @param tenantOptions - The properties to update on the provided tenant.
*
* @returns A promise fulfilled with the update tenant data.
*/
updateTenant(tenantId: string, tenantOptions: UpdateTenantRequest): Promise<Tenant>;
}

View File

@@ -0,0 +1,230 @@
/*! firebase-admin v13.5.0 */
"use strict";
/*!
* Copyright 2019 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.TenantManager = exports.TenantAwareAuth = void 0;
const validator = require("../utils/validator");
const utils = require("../utils/index");
const error_1 = require("../utils/error");
const base_auth_1 = require("./base-auth");
const tenant_1 = require("./tenant");
const auth_api_request_1 = require("./auth-api-request");
/**
* Tenant-aware `Auth` interface used for managing users, configuring SAML/OIDC providers,
* generating email links for password reset, email verification, etc for specific tenants.
*
* Multi-tenancy 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}.
*
* Each tenant contains its own identity providers, settings and sets of users.
* Using `TenantAwareAuth`, users for a specific tenant and corresponding OIDC/SAML
* configurations can also be managed, ID tokens for users signed in to a specific tenant
* can be verified, and email action links can also be generated for users belonging to the
* tenant.
*
* `TenantAwareAuth` instances for a specific `tenantId` can be instantiated by calling
* {@link TenantManager.authForTenant}.
*/
class TenantAwareAuth extends base_auth_1.BaseAuth {
/**
* The TenantAwareAuth class constructor.
*
* @param app - The app that created this tenant.
* @param tenantId - The corresponding tenant ID.
* @constructor
* @internal
*/
constructor(app, tenantId) {
super(app, new auth_api_request_1.TenantAwareAuthRequestHandler(app, tenantId), (0, base_auth_1.createFirebaseTokenGenerator)(app, tenantId));
utils.addReadonlyGetter(this, 'tenantId', tenantId);
}
/**
* {@inheritdoc BaseAuth.verifyIdToken}
*/
verifyIdToken(idToken, checkRevoked = false) {
return super.verifyIdToken(idToken, checkRevoked)
.then((decodedClaims) => {
// Validate tenant ID.
if (decodedClaims.firebase.tenant !== this.tenantId) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISMATCHING_TENANT_ID);
}
return decodedClaims;
});
}
/**
* {@inheritdoc BaseAuth.createSessionCookie}
*/
createSessionCookie(idToken, sessionCookieOptions) {
// Validate arguments before processing.
if (!validator.isNonEmptyString(idToken)) {
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ID_TOKEN));
}
if (!validator.isNonNullObject(sessionCookieOptions) ||
!validator.isNumber(sessionCookieOptions.expiresIn)) {
return Promise.reject(new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_SESSION_COOKIE_DURATION));
}
// This will verify the ID token and then match the tenant ID before creating the session cookie.
return this.verifyIdToken(idToken)
.then(() => {
return super.createSessionCookie(idToken, sessionCookieOptions);
});
}
/**
* {@inheritdoc BaseAuth.verifySessionCookie}
*/
verifySessionCookie(sessionCookie, checkRevoked = false) {
return super.verifySessionCookie(sessionCookie, checkRevoked)
.then((decodedClaims) => {
if (decodedClaims.firebase.tenant !== this.tenantId) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISMATCHING_TENANT_ID);
}
return decodedClaims;
});
}
}
exports.TenantAwareAuth = TenantAwareAuth;
/**
* Defines the tenant manager used to help manage tenant related operations.
* This includes:
* <ul>
* <li>The ability to create, update, list, get and delete tenants for the underlying
* project.</li>
* <li>Getting a `TenantAwareAuth` instance for running Auth related operations
* (user management, provider configuration management, token verification,
* email link generation, etc) in the context of a specified tenant.</li>
* </ul>
*/
class TenantManager {
/**
* Initializes a TenantManager instance for a specified FirebaseApp.
*
* @param app - The app for this TenantManager instance.
*
* @constructor
* @internal
*/
constructor(app) {
this.app = app;
this.authRequestHandler = new auth_api_request_1.AuthRequestHandler(app);
this.tenantsMap = {};
}
/**
* Returns a `TenantAwareAuth` instance bound to the given tenant ID.
*
* @param tenantId - The tenant ID whose `TenantAwareAuth` instance is to be returned.
*
* @returns The `TenantAwareAuth` instance corresponding to this tenant identifier.
*/
authForTenant(tenantId) {
if (!validator.isNonEmptyString(tenantId)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_TENANT_ID);
}
if (typeof this.tenantsMap[tenantId] === 'undefined') {
this.tenantsMap[tenantId] = new TenantAwareAuth(this.app, tenantId);
}
return this.tenantsMap[tenantId];
}
/**
* Gets the tenant configuration for the tenant corresponding to a given `tenantId`.
*
* @param tenantId - The tenant identifier corresponding to the tenant whose data to fetch.
*
* @returns A promise fulfilled with the tenant configuration to the provided `tenantId`.
*/
getTenant(tenantId) {
return this.authRequestHandler.getTenant(tenantId)
.then((response) => {
return new tenant_1.Tenant(response);
});
}
/**
* Retrieves a list of tenants (single batch only) with a size of `maxResults`
* starting from the offset as specified by `pageToken`. This is used to
* retrieve all the tenants of a specified project in batches.
*
* @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
* tenants starting without any offset.
*
* @returns A promise that resolves with
* a batch of downloaded tenants and the next page token.
*/
listTenants(maxResults, pageToken) {
return this.authRequestHandler.listTenants(maxResults, pageToken)
.then((response) => {
// List of tenants to return.
const tenants = [];
// Convert each user response to a Tenant.
response.tenants.forEach((tenantResponse) => {
tenants.push(new tenant_1.Tenant(tenantResponse));
});
// Return list of tenants and the next page token if available.
const result = {
tenants,
pageToken: response.nextPageToken,
};
// Delete result.pageToken if undefined.
if (typeof result.pageToken === 'undefined') {
delete result.pageToken;
}
return result;
});
}
/**
* Deletes an existing tenant.
*
* @param tenantId - The `tenantId` corresponding to the tenant to delete.
*
* @returns An empty promise fulfilled once the tenant has been deleted.
*/
deleteTenant(tenantId) {
return this.authRequestHandler.deleteTenant(tenantId);
}
/**
* Creates a new tenant.
* When creating new tenants, tenants that use separate billing and quota will require their
* own project and must be defined as `full_service`.
*
* @param tenantOptions - The properties to set on the new tenant configuration to be created.
*
* @returns A promise fulfilled with the tenant configuration corresponding to the newly
* created tenant.
*/
createTenant(tenantOptions) {
return this.authRequestHandler.createTenant(tenantOptions)
.then((response) => {
return new tenant_1.Tenant(response);
});
}
/**
* Updates an existing tenant configuration.
*
* @param tenantId - The `tenantId` corresponding to the tenant to delete.
* @param tenantOptions - The properties to update on the provided tenant.
*
* @returns A promise fulfilled with the update tenant data.
*/
updateTenant(tenantId, tenantOptions) {
return this.authRequestHandler.updateTenant(tenantId, tenantOptions)
.then((response) => {
return new tenant_1.Tenant(response);
});
}
}
exports.TenantManager = TenantManager;

182
server/node_modules/firebase-admin/lib/auth/tenant.d.ts generated vendored Normal file
View File

@@ -0,0 +1,182 @@
/*! firebase-admin v13.5.0 */
/*!
* Copyright 2019 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.
*/
import { EmailSignInConfigServerRequest, MultiFactorAuthServerConfig, MultiFactorConfig, EmailSignInProviderConfig, SmsRegionConfig, RecaptchaConfig, RecaptchaAuthServerConfig, PasswordPolicyConfig, PasswordPolicyAuthServerConfig, EmailPrivacyConfig } from './auth-config';
/**
* Interface representing the properties to update on the provided tenant.
*/
export interface UpdateTenantRequest {
/**
* The tenant display name.
*/
displayName?: string;
/**
* The email sign in configuration.
*/
emailSignInConfig?: EmailSignInProviderConfig;
/**
* Whether the anonymous provider is enabled.
*/
anonymousSignInEnabled?: boolean;
/**
* The multi-factor auth configuration to update on the tenant.
*/
multiFactorConfig?: MultiFactorConfig;
/**
* The updated map containing the test phone number / code pairs for the tenant.
* Passing null clears the previously save phone number / code pairs.
*/
testPhoneNumbers?: {
[phoneNumber: string]: string;
} | null;
/**
* The SMS configuration to update on the project.
*/
smsRegionConfig?: SmsRegionConfig;
/**
* The reCAPTCHA configuration to update on the tenant.
* By enabling reCAPTCHA Enterprise integration, you are
* agreeing to the reCAPTCHA Enterprise
* {@link https://cloud.google.com/terms/service-terms | Term of Service}.
*/
recaptchaConfig?: RecaptchaConfig;
/**
* The password policy configuration for the tenant
*/
passwordPolicyConfig?: PasswordPolicyConfig;
/**
* The email privacy configuration for the tenant
*/
emailPrivacyConfig?: EmailPrivacyConfig;
}
/**
* Interface representing the properties to set on a new tenant.
*/
export type CreateTenantRequest = UpdateTenantRequest;
/** The corresponding server side representation of a TenantOptions object. */
export interface TenantOptionsServerRequest extends EmailSignInConfigServerRequest {
displayName?: string;
enableAnonymousUser?: boolean;
mfaConfig?: MultiFactorAuthServerConfig;
testPhoneNumbers?: {
[key: string]: string;
};
smsRegionConfig?: SmsRegionConfig;
recaptchaConfig?: RecaptchaAuthServerConfig;
passwordPolicyConfig?: PasswordPolicyAuthServerConfig;
emailPrivacyConfig?: EmailPrivacyConfig;
}
/** The tenant server response interface. */
export interface TenantServerResponse {
name: string;
displayName?: string;
allowPasswordSignup?: boolean;
enableEmailLinkSignin?: boolean;
enableAnonymousUser?: boolean;
mfaConfig?: MultiFactorAuthServerConfig;
testPhoneNumbers?: {
[key: string]: string;
};
smsRegionConfig?: SmsRegionConfig;
recaptchaConfig?: RecaptchaAuthServerConfig;
passwordPolicyConfig?: PasswordPolicyAuthServerConfig;
emailPrivacyConfig?: EmailPrivacyConfig;
}
/**
* Represents a tenant configuration.
*
* Multi-tenancy 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}.
*
* Before multi-tenancy can be used on a Google Cloud Identity Platform project,
* tenants must be allowed on that project via the Cloud Console UI.
*
* A tenant configuration provides information such as the display name, tenant
* identifier and email authentication configuration.
* For OIDC/SAML provider configuration management, `TenantAwareAuth` instances should
* be used instead of a `Tenant` to retrieve the list of configured IdPs on a tenant.
* When configuring these providers, note that tenants will inherit
* whitelisted domains and authenticated redirect URIs of their parent project.
*
* All other settings of a tenant will also be inherited. These will need to be managed
* from the Cloud Console UI.
*/
export declare class Tenant {
/**
* The tenant identifier.
*/
readonly tenantId: string;
/**
* The tenant display name.
*/
readonly displayName?: string;
readonly anonymousSignInEnabled: boolean;
/**
* The map containing the test phone number / code pairs for the tenant.
*/
readonly testPhoneNumbers?: {
[phoneNumber: string]: string;
};
private readonly emailSignInConfig_?;
private readonly multiFactorConfig_?;
/**
* The map conatining the reCAPTCHA config.
* By enabling reCAPTCHA Enterprise Integration you are
* agreeing to reCAPTCHA Enterprise
* {@link https://cloud.google.com/terms/service-terms | Term of Service}.
*/
private readonly recaptchaConfig_?;
/**
* The SMS Regions Config to update a tenant.
* Configures the regions where users are allowed to send verification SMS.
* This is based on the calling code of the destination phone number.
*/
readonly smsRegionConfig?: SmsRegionConfig;
/**
* The password policy configuration for the tenant
*/
readonly passwordPolicyConfig?: PasswordPolicyConfig;
/**
* The email privacy configuration for the tenant
*/
readonly emailPrivacyConfig?: EmailPrivacyConfig;
/**
* Validates a tenant options object. Throws an error on failure.
*
* @param request - The tenant options object to validate.
* @param createRequest - Whether this is a create request.
*/
private static validate;
/**
* The email sign in provider configuration.
*/
get emailSignInConfig(): EmailSignInProviderConfig | undefined;
/**
* The multi-factor auth configuration on the current tenant.
*/
get multiFactorConfig(): MultiFactorConfig | undefined;
/**
* The recaptcha config auth configuration of the current tenant.
*/
get recaptchaConfig(): RecaptchaConfig | undefined;
/**
* Returns a JSON-serializable representation of this object.
*
* @returns A JSON-serializable representation of this object.
*/
toJSON(): object;
}

273
server/node_modules/firebase-admin/lib/auth/tenant.js generated vendored Normal file
View File

@@ -0,0 +1,273 @@
/*! firebase-admin v13.5.0 */
"use strict";
/*!
* Copyright 2019 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.Tenant = void 0;
const validator = require("../utils/validator");
const deep_copy_1 = require("../utils/deep-copy");
const error_1 = require("../utils/error");
const auth_config_1 = require("./auth-config");
/**
* Represents a tenant configuration.
*
* Multi-tenancy 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}.
*
* Before multi-tenancy can be used on a Google Cloud Identity Platform project,
* tenants must be allowed on that project via the Cloud Console UI.
*
* A tenant configuration provides information such as the display name, tenant
* identifier and email authentication configuration.
* For OIDC/SAML provider configuration management, `TenantAwareAuth` instances should
* be used instead of a `Tenant` to retrieve the list of configured IdPs on a tenant.
* When configuring these providers, note that tenants will inherit
* whitelisted domains and authenticated redirect URIs of their parent project.
*
* All other settings of a tenant will also be inherited. These will need to be managed
* from the Cloud Console UI.
*/
class Tenant {
/**
* Builds the corresponding server request for a TenantOptions object.
*
* @param tenantOptions - The properties to convert to a server request.
* @param createRequest - Whether this is a create request.
* @returns The equivalent server request.
*
* @internal
*/
static buildServerRequest(tenantOptions, createRequest) {
Tenant.validate(tenantOptions, createRequest);
let request = {};
if (typeof tenantOptions.emailSignInConfig !== 'undefined') {
request = auth_config_1.EmailSignInConfig.buildServerRequest(tenantOptions.emailSignInConfig);
}
if (typeof tenantOptions.displayName !== 'undefined') {
request.displayName = tenantOptions.displayName;
}
if (typeof tenantOptions.anonymousSignInEnabled !== 'undefined') {
request.enableAnonymousUser = tenantOptions.anonymousSignInEnabled;
}
if (typeof tenantOptions.multiFactorConfig !== 'undefined') {
request.mfaConfig = auth_config_1.MultiFactorAuthConfig.buildServerRequest(tenantOptions.multiFactorConfig);
}
if (typeof tenantOptions.testPhoneNumbers !== 'undefined') {
// null will clear existing test phone numbers. Translate to empty object.
request.testPhoneNumbers = tenantOptions.testPhoneNumbers ?? {};
}
if (typeof tenantOptions.smsRegionConfig !== 'undefined') {
request.smsRegionConfig = tenantOptions.smsRegionConfig;
}
if (typeof tenantOptions.recaptchaConfig !== 'undefined') {
request.recaptchaConfig = auth_config_1.RecaptchaAuthConfig.buildServerRequest(tenantOptions.recaptchaConfig);
}
if (typeof tenantOptions.passwordPolicyConfig !== 'undefined') {
request.passwordPolicyConfig = auth_config_1.PasswordPolicyAuthConfig.buildServerRequest(tenantOptions.passwordPolicyConfig);
}
if (typeof tenantOptions.emailPrivacyConfig !== 'undefined') {
request.emailPrivacyConfig = tenantOptions.emailPrivacyConfig;
}
return request;
}
/**
* Returns the tenant ID corresponding to the resource name if available.
*
* @param resourceName - The server side resource name
* @returns The tenant ID corresponding to the resource, null otherwise.
*
* @internal
*/
static getTenantIdFromResourceName(resourceName) {
// name is of form projects/project1/tenants/tenant1
const matchTenantRes = resourceName.match(/\/tenants\/(.*)$/);
if (!matchTenantRes || matchTenantRes.length < 2) {
return null;
}
return matchTenantRes[1];
}
/**
* Validates a tenant options object. Throws an error on failure.
*
* @param request - The tenant options object to validate.
* @param createRequest - Whether this is a create request.
*/
static validate(request, createRequest) {
const validKeys = {
displayName: true,
emailSignInConfig: true,
anonymousSignInEnabled: true,
multiFactorConfig: true,
testPhoneNumbers: true,
smsRegionConfig: true,
recaptchaConfig: true,
passwordPolicyConfig: true,
emailPrivacyConfig: true,
};
const label = createRequest ? 'CreateTenantRequest' : 'UpdateTenantRequest';
if (!validator.isNonNullObject(request)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, `"${label}" must be a valid non-null object.`);
}
// Check for unsupported top level attributes.
for (const key in request) {
if (!(key in validKeys)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, `"${key}" is not a valid ${label} parameter.`);
}
}
// Validate displayName type if provided.
if (typeof request.displayName !== 'undefined' &&
!validator.isNonEmptyString(request.displayName)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, `"${label}.displayName" must be a valid non-empty string.`);
}
// Validate emailSignInConfig type if provided.
if (typeof request.emailSignInConfig !== 'undefined') {
// This will throw an error if invalid.
auth_config_1.EmailSignInConfig.buildServerRequest(request.emailSignInConfig);
}
// Validate test phone numbers if provided.
if (typeof request.testPhoneNumbers !== 'undefined' &&
request.testPhoneNumbers !== null) {
(0, auth_config_1.validateTestPhoneNumbers)(request.testPhoneNumbers);
}
else if (request.testPhoneNumbers === null && createRequest) {
// null allowed only for update operations.
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, `"${label}.testPhoneNumbers" must be a non-null object.`);
}
// Validate multiFactorConfig type if provided.
if (typeof request.multiFactorConfig !== 'undefined') {
// This will throw an error if invalid.
auth_config_1.MultiFactorAuthConfig.buildServerRequest(request.multiFactorConfig);
}
// Validate SMS Regions Config if provided.
if (typeof request.smsRegionConfig !== 'undefined') {
auth_config_1.SmsRegionsAuthConfig.validate(request.smsRegionConfig);
}
// Validate reCAPTCHAConfig type if provided.
if (typeof request.recaptchaConfig !== 'undefined') {
auth_config_1.RecaptchaAuthConfig.buildServerRequest(request.recaptchaConfig);
}
// Validate passwordPolicyConfig type if provided.
if (typeof request.passwordPolicyConfig !== 'undefined') {
// This will throw an error if invalid.
auth_config_1.PasswordPolicyAuthConfig.buildServerRequest(request.passwordPolicyConfig);
}
// Validate Email Privacy Config if provided.
if (typeof request.emailPrivacyConfig !== 'undefined') {
auth_config_1.EmailPrivacyAuthConfig.validate(request.emailPrivacyConfig);
}
}
/**
* The Tenant object constructor.
*
* @param response - The server side response used to initialize the Tenant object.
* @constructor
* @internal
*/
constructor(response) {
const tenantId = Tenant.getTenantIdFromResourceName(response.name);
if (!tenantId) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Invalid tenant response');
}
this.tenantId = tenantId;
this.displayName = response.displayName;
try {
this.emailSignInConfig_ = new auth_config_1.EmailSignInConfig(response);
}
catch (e) {
// If allowPasswordSignup is undefined, it is disabled by default.
this.emailSignInConfig_ = new auth_config_1.EmailSignInConfig({
allowPasswordSignup: false,
});
}
this.anonymousSignInEnabled = !!response.enableAnonymousUser;
if (typeof response.mfaConfig !== 'undefined') {
this.multiFactorConfig_ = new auth_config_1.MultiFactorAuthConfig(response.mfaConfig);
}
if (typeof response.testPhoneNumbers !== 'undefined') {
this.testPhoneNumbers = (0, deep_copy_1.deepCopy)(response.testPhoneNumbers || {});
}
if (typeof response.smsRegionConfig !== 'undefined') {
this.smsRegionConfig = (0, deep_copy_1.deepCopy)(response.smsRegionConfig);
}
if (typeof response.recaptchaConfig !== 'undefined') {
this.recaptchaConfig_ = new auth_config_1.RecaptchaAuthConfig(response.recaptchaConfig);
}
if (typeof response.passwordPolicyConfig !== 'undefined') {
this.passwordPolicyConfig = new auth_config_1.PasswordPolicyAuthConfig(response.passwordPolicyConfig);
}
if (typeof response.emailPrivacyConfig !== 'undefined') {
this.emailPrivacyConfig = (0, deep_copy_1.deepCopy)(response.emailPrivacyConfig);
}
}
/**
* The email sign in provider configuration.
*/
get emailSignInConfig() {
return this.emailSignInConfig_;
}
/**
* The multi-factor auth configuration on the current tenant.
*/
get multiFactorConfig() {
return this.multiFactorConfig_;
}
/**
* The recaptcha config auth configuration of the current tenant.
*/
get recaptchaConfig() {
return this.recaptchaConfig_;
}
/**
* Returns a JSON-serializable representation of this object.
*
* @returns A JSON-serializable representation of this object.
*/
toJSON() {
const json = {
tenantId: this.tenantId,
displayName: this.displayName,
emailSignInConfig: this.emailSignInConfig_?.toJSON(),
multiFactorConfig: this.multiFactorConfig_?.toJSON(),
anonymousSignInEnabled: this.anonymousSignInEnabled,
testPhoneNumbers: this.testPhoneNumbers,
smsRegionConfig: (0, deep_copy_1.deepCopy)(this.smsRegionConfig),
recaptchaConfig: (0, deep_copy_1.deepCopy)(this.recaptchaConfig),
passwordPolicyConfig: (0, deep_copy_1.deepCopy)(this.passwordPolicyConfig),
emailPrivacyConfig: (0, deep_copy_1.deepCopy)(this.emailPrivacyConfig),
};
if (typeof json.multiFactorConfig === 'undefined') {
delete json.multiFactorConfig;
}
if (typeof json.testPhoneNumbers === 'undefined') {
delete json.testPhoneNumbers;
}
if (typeof json.smsRegionConfig === 'undefined') {
delete json.smsRegionConfig;
}
if (typeof json.recaptchaConfig === 'undefined') {
delete json.recaptchaConfig;
}
if (typeof json.passwordPolicyConfig === 'undefined') {
delete json.passwordPolicyConfig;
}
if (typeof json.emailPrivacyConfig === 'undefined') {
delete json.emailPrivacyConfig;
}
return json;
}
}
exports.Tenant = Tenant;

View File

@@ -0,0 +1,43 @@
/*! firebase-admin v13.5.0 */
/*!
* @license
* Copyright 2017 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.
*/
import { CryptoSigner } from '../utils/crypto-signer';
import { Algorithm } from 'jsonwebtoken';
export declare const BLACKLISTED_CLAIMS: string[];
/**
* A CryptoSigner implementation that is used when communicating with the Auth emulator.
* It produces unsigned tokens.
*/
export declare class EmulatedSigner implements CryptoSigner {
algorithm: Algorithm;
/**
* @inheritDoc
*/
sign(buffer: Buffer): Promise<Buffer>;
/**
* @inheritDoc
*/
getAccountId(): Promise<string>;
}
/**
* Creates a new FirebaseAuthError by extracting the error code, message and other relevant
* details from a CryptoSignerError.
*
* @param err - The Error to convert into a FirebaseAuthError error
* @returns A Firebase Auth error that can be returned to the user.
*/
export declare function handleCryptoSignerError(err: Error): Error;

View File

@@ -0,0 +1,198 @@
/*! firebase-admin v13.5.0 */
"use strict";
/*!
* @license
* Copyright 2017 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.FirebaseTokenGenerator = exports.EmulatedSigner = exports.BLACKLISTED_CLAIMS = void 0;
exports.handleCryptoSignerError = handleCryptoSignerError;
const error_1 = require("../utils/error");
const crypto_signer_1 = require("../utils/crypto-signer");
const validator = require("../utils/validator");
const utils_1 = require("../utils");
const ALGORITHM_NONE = 'none';
const ONE_HOUR_IN_SECONDS = 60 * 60;
// List of blacklisted claims which cannot be provided when creating a custom token
exports.BLACKLISTED_CLAIMS = [
'acr', 'amr', 'at_hash', 'aud', 'auth_time', 'azp', 'cnf', 'c_hash', 'exp', 'iat', 'iss', 'jti',
'nbf', 'nonce',
];
// Audience to use for Firebase Auth Custom tokens
const FIREBASE_AUDIENCE = 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit';
/**
* A CryptoSigner implementation that is used when communicating with the Auth emulator.
* It produces unsigned tokens.
*/
class EmulatedSigner {
constructor() {
this.algorithm = ALGORITHM_NONE;
}
/**
* @inheritDoc
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
sign(buffer) {
return Promise.resolve(Buffer.from(''));
}
/**
* @inheritDoc
*/
getAccountId() {
return Promise.resolve('firebase-auth-emulator@example.com');
}
}
exports.EmulatedSigner = EmulatedSigner;
/**
* Class for generating different types of Firebase Auth tokens (JWTs).
*
* @internal
*/
class FirebaseTokenGenerator {
/**
* @param tenantId - The tenant ID to use for the generated Firebase Auth
* Custom token. If absent, then no tenant ID claim will be set in the
* resulting JWT.
*/
constructor(signer, tenantId) {
this.tenantId = tenantId;
if (!validator.isNonNullObject(signer)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREDENTIAL, 'INTERNAL ASSERT: Must provide a CryptoSigner to use FirebaseTokenGenerator.');
}
if (typeof this.tenantId !== 'undefined' && !validator.isNonEmptyString(this.tenantId)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '`tenantId` argument must be a non-empty string.');
}
this.signer = signer;
}
/**
* Creates a new Firebase Auth Custom token.
*
* @param uid - The user ID to use for the generated Firebase Auth Custom token.
* @param developerClaims - Optional developer claims to include in the generated Firebase
* Auth Custom token.
* @returns A Promise fulfilled with a Firebase Auth Custom token signed with a
* service account key and containing the provided payload.
*/
createCustomToken(uid, developerClaims) {
let errorMessage;
if (!validator.isNonEmptyString(uid)) {
errorMessage = '`uid` argument must be a non-empty string uid.';
}
else if (uid.length > 128) {
errorMessage = '`uid` argument must a uid with less than or equal to 128 characters.';
}
else if (!this.isDeveloperClaimsValid_(developerClaims)) {
errorMessage = '`developerClaims` argument must be a valid, non-null object containing the developer claims.';
}
if (errorMessage) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, errorMessage);
}
const claims = {};
if (typeof developerClaims !== 'undefined') {
for (const key in developerClaims) {
/* istanbul ignore else */
if (Object.prototype.hasOwnProperty.call(developerClaims, key)) {
if (exports.BLACKLISTED_CLAIMS.indexOf(key) !== -1) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, `Developer claim "${key}" is reserved and cannot be specified.`);
}
claims[key] = developerClaims[key];
}
}
}
return this.signer.getAccountId().then((account) => {
const header = {
alg: this.signer.algorithm,
typ: 'JWT',
};
const iat = Math.floor(Date.now() / 1000);
const body = {
aud: FIREBASE_AUDIENCE,
iat,
exp: iat + ONE_HOUR_IN_SECONDS,
iss: account,
sub: account,
uid,
};
if (this.tenantId) {
body.tenant_id = this.tenantId;
}
if (Object.keys(claims).length > 0) {
body.claims = claims;
}
const token = `${this.encodeSegment(header)}.${this.encodeSegment(body)}`;
const signPromise = this.signer.sign(Buffer.from(token));
return Promise.all([token, signPromise]);
}).then(([token, signature]) => {
return `${token}.${this.encodeSegment(signature)}`;
}).catch((err) => {
throw handleCryptoSignerError(err);
});
}
encodeSegment(segment) {
const buffer = (segment instanceof Buffer) ? segment : Buffer.from(JSON.stringify(segment));
return (0, utils_1.toWebSafeBase64)(buffer).replace(/=+$/, '');
}
/**
* Returns whether or not the provided developer claims are valid.
*
* @param developerClaims - Optional developer claims to validate.
* @returns True if the provided claims are valid; otherwise, false.
*/
// eslint-disable-next-line @typescript-eslint/naming-convention
isDeveloperClaimsValid_(developerClaims) {
if (typeof developerClaims === 'undefined') {
return true;
}
return validator.isNonNullObject(developerClaims);
}
}
exports.FirebaseTokenGenerator = FirebaseTokenGenerator;
/**
* Creates a new FirebaseAuthError by extracting the error code, message and other relevant
* details from a CryptoSignerError.
*
* @param err - The Error to convert into a FirebaseAuthError error
* @returns A Firebase Auth error that can be returned to the user.
*/
function handleCryptoSignerError(err) {
if (!(err instanceof crypto_signer_1.CryptoSignerError)) {
return err;
}
if (err.code === crypto_signer_1.CryptoSignerErrorCode.SERVER_ERROR && validator.isNonNullObject(err.cause)) {
const httpError = err.cause;
const errorResponse = httpError.response.data;
if (validator.isNonNullObject(errorResponse) && errorResponse.error) {
const errorCode = errorResponse.error.status;
const description = 'Please refer to https://firebase.google.com/docs/auth/admin/create-custom-tokens ' +
'for more details on how to use and troubleshoot this feature.';
const errorMsg = `${errorResponse.error.message}; ${description}`;
return error_1.FirebaseAuthError.fromServerError(errorCode, errorMsg, errorResponse);
}
return new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'Error returned from server: ' + errorResponse + '. Additionally, an ' +
'internal error occurred while attempting to extract the ' +
'errorcode from the error.');
}
return new error_1.FirebaseAuthError(mapToAuthClientErrorCode(err.code), err.message);
}
function mapToAuthClientErrorCode(code) {
switch (code) {
case crypto_signer_1.CryptoSignerErrorCode.INVALID_CREDENTIAL:
return error_1.AuthClientErrorCode.INVALID_CREDENTIAL;
case crypto_signer_1.CryptoSignerErrorCode.INVALID_ARGUMENT:
return error_1.AuthClientErrorCode.INVALID_ARGUMENT;
default:
return error_1.AuthClientErrorCode.INTERNAL_ERROR;
}
}

View File

@@ -0,0 +1,219 @@
/*! firebase-admin v13.5.0 */
/*!
* Copyright 2018 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.
*/
/**
* Interface representing a decoded Firebase ID token, returned from the
* {@link BaseAuth.verifyIdToken} method.
*
* Firebase ID tokens are OpenID Connect spec-compliant JSON Web Tokens (JWTs).
* See the
* [ID Token section of the OpenID Connect spec](http://openid.net/specs/openid-connect-core-1_0.html#IDToken)
* for more information about the specific properties below.
*/
export interface DecodedIdToken {
/**
* The audience for which this token is intended.
*
* This value is a string equal to your Firebase project ID, the unique
* identifier for your Firebase project, which can be found in [your project's
* settings](https://console.firebase.google.com/project/_/settings/general/android:com.random.android).
*/
aud: string;
/**
* Time, in seconds since the Unix epoch, when the end-user authentication
* occurred.
*
* This value is not set when this particular ID token was created, but when the
* user initially logged in to this session. In a single session, the Firebase
* SDKs will refresh a user's ID tokens every hour. Each ID token will have a
* different [`iat`](#iat) value, but the same `auth_time` value.
*/
auth_time: number;
/**
* The email of the user to whom the ID token belongs, if available.
*/
email?: string;
/**
* Whether or not the email of the user to whom the ID token belongs is
* verified, provided the user has an email.
*/
email_verified?: boolean;
/**
* The ID token's expiration time, in seconds since the Unix epoch. That is, the
* time at which this ID token expires and should no longer be considered valid.
*
* The Firebase SDKs transparently refresh ID tokens every hour, issuing a new
* ID token with up to a one hour expiration.
*/
exp: number;
/**
* Information about the sign in event, including which sign in provider was
* used and provider-specific identity details.
*
* This data is provided by the Firebase Authentication service and is a
* reserved claim in the ID token.
*/
firebase: {
/**
* Provider-specific identity details corresponding
* to the provider used to sign in the user.
*/
identities: {
[key: string]: any;
};
/**
* The ID of the provider used to sign in the user.
* One of `"anonymous"`, `"password"`, `"facebook.com"`, `"github.com"`,
* `"google.com"`, `"twitter.com"`, `"apple.com"`, `"microsoft.com"`,
* `"yahoo.com"`, `"phone"`, `"playgames.google.com"`, `"gc.apple.com"`,
* or `"custom"`.
*
* Additional Identity Platform provider IDs include `"linkedin.com"`,
* OIDC and SAML identity providers prefixed with `"saml."` and `"oidc."`
* respectively.
*/
sign_in_provider: string;
/**
* The type identifier or `factorId` of the second factor, provided the
* ID token was obtained from a multi-factor authenticated user.
* For phone, this is `"phone"`.
*/
sign_in_second_factor?: string;
/**
* The `uid` of the second factor used to sign in, provided the
* ID token was obtained from a multi-factor authenticated user.
*/
second_factor_identifier?: string;
/**
* The ID of the tenant the user belongs to, if available.
*/
tenant?: string;
[key: string]: any;
};
/**
* The ID token's issued-at time, in seconds since the Unix epoch. That is, the
* time at which this ID token was issued and should start to be considered
* valid.
*
* The Firebase SDKs transparently refresh ID tokens every hour, issuing a new
* ID token with a new issued-at time. If you want to get the time at which the
* user session corresponding to the ID token initially occurred, see the
* [`auth_time`](#auth_time) property.
*/
iat: number;
/**
* The issuer identifier for the issuer of the response.
*
* This value is a URL with the format
* `https://securetoken.google.com/<PROJECT_ID>`, where `<PROJECT_ID>` is the
* same project ID specified in the [`aud`](#aud) property.
*/
iss: string;
/**
* The phone number of the user to whom the ID token belongs, if available.
*/
phone_number?: string;
/**
* The photo URL for the user to whom the ID token belongs, if available.
*/
picture?: string;
/**
* The `uid` corresponding to the user who the ID token belonged to.
*
* As a convenience, this value is copied over to the [`uid`](#uid) property.
*/
sub: string;
/**
* The `uid` corresponding to the user who the ID token belonged to.
*
* This value is not actually in the JWT token claims itself. It is added as a
* convenience, and is set as the value of the [`sub`](#sub) property.
*/
uid: string;
/**
* Other arbitrary claims included in the ID token.
*/
[key: string]: any;
}
/** @alpha */
export interface DecodedAuthBlockingSharedUserInfo {
uid: string;
display_name?: string;
email?: string;
photo_url?: string;
phone_number?: string;
}
/** @alpha */
export interface DecodedAuthBlockingMetadata {
creation_time?: number;
last_sign_in_time?: number;
}
/** @alpha */
export interface DecodedAuthBlockingUserInfo extends DecodedAuthBlockingSharedUserInfo {
provider_id: string;
}
/** @alpha */
export interface DecodedAuthBlockingMfaInfo {
uid: string;
display_name?: string;
phone_number?: string;
enrollment_time?: string;
factor_id?: string;
}
/** @alpha */
export interface DecodedAuthBlockingEnrolledFactors {
enrolled_factors?: DecodedAuthBlockingMfaInfo[];
}
/** @alpha */
export interface DecodedAuthBlockingUserRecord extends DecodedAuthBlockingSharedUserInfo {
email_verified?: boolean;
disabled?: boolean;
metadata?: DecodedAuthBlockingMetadata;
password_hash?: string;
password_salt?: string;
provider_data?: DecodedAuthBlockingUserInfo[];
multi_factor?: DecodedAuthBlockingEnrolledFactors;
custom_claims?: any;
tokens_valid_after_time?: number;
tenant_id?: string;
[key: string]: any;
}
/** @alpha */
export interface DecodedAuthBlockingToken {
aud: string;
exp: number;
iat: number;
iss: string;
sub: string;
event_id: string;
event_type: string;
ip_address: string;
user_agent?: string;
locale?: string;
sign_in_method?: string;
user_record?: DecodedAuthBlockingUserRecord;
tenant_id?: string;
raw_user_info?: string;
sign_in_attributes?: {
[key: string]: any;
};
oauth_id_token?: string;
oauth_access_token?: string;
oauth_refresh_token?: string;
oauth_token_secret?: string;
oauth_expires_in?: number;
[key: string]: any;
}

View File

@@ -0,0 +1,316 @@
/*! firebase-admin v13.5.0 */
"use strict";
/*!
* Copyright 2018 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.FirebaseTokenVerifier = exports.SESSION_COOKIE_INFO = exports.AUTH_BLOCKING_TOKEN_INFO = exports.ID_TOKEN_INFO = void 0;
exports.createIdTokenVerifier = createIdTokenVerifier;
exports.createAuthBlockingTokenVerifier = createAuthBlockingTokenVerifier;
exports.createSessionCookieVerifier = createSessionCookieVerifier;
const error_1 = require("../utils/error");
const util = require("../utils/index");
const validator = require("../utils/validator");
const jwt_1 = require("../utils/jwt");
// Audience to use for Firebase Auth Custom tokens
const FIREBASE_AUDIENCE = 'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit';
// URL containing the public keys for the Google certs (whose private keys are used to sign Firebase
// Auth ID tokens)
const CLIENT_CERT_URL = 'https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com';
// URL containing the public keys for Firebase session cookies. This will be updated to a different URL soon.
const SESSION_COOKIE_CERT_URL = 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/publicKeys';
const EMULATOR_VERIFIER = new jwt_1.EmulatorSignatureVerifier();
/**
* User facing token information related to the Firebase ID token.
*
* @internal
*/
exports.ID_TOKEN_INFO = {
url: 'https://firebase.google.com/docs/auth/admin/verify-id-tokens',
verifyApiName: 'verifyIdToken()',
jwtName: 'Firebase ID token',
shortName: 'ID token',
expiredErrorCode: error_1.AuthClientErrorCode.ID_TOKEN_EXPIRED,
};
/**
* User facing token information related to the Firebase Auth Blocking token.
*
* @internal
*/
exports.AUTH_BLOCKING_TOKEN_INFO = {
url: 'https://cloud.google.com/identity-platform/docs/blocking-functions',
verifyApiName: '_verifyAuthBlockingToken()',
jwtName: 'Firebase Auth Blocking token',
shortName: 'Auth Blocking token',
expiredErrorCode: error_1.AuthClientErrorCode.AUTH_BLOCKING_TOKEN_EXPIRED,
};
/**
* User facing token information related to the Firebase session cookie.
*
* @internal
*/
exports.SESSION_COOKIE_INFO = {
url: 'https://firebase.google.com/docs/auth/admin/manage-cookies',
verifyApiName: 'verifySessionCookie()',
jwtName: 'Firebase session cookie',
shortName: 'session cookie',
expiredErrorCode: error_1.AuthClientErrorCode.SESSION_COOKIE_EXPIRED,
};
/**
* Class for verifying general purpose Firebase JWTs. This verifies ID tokens and session cookies.
*
* @internal
*/
class FirebaseTokenVerifier {
constructor(clientCertUrl, issuer, tokenInfo, app) {
this.issuer = issuer;
this.tokenInfo = tokenInfo;
this.app = app;
if (!validator.isURL(clientCertUrl)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'The provided public client certificate URL is an invalid URL.');
}
else if (!validator.isURL(issuer)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'The provided JWT issuer is an invalid URL.');
}
else if (!validator.isNonNullObject(tokenInfo)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'The provided JWT information is not an object or null.');
}
else if (!validator.isURL(tokenInfo.url)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'The provided JWT verification documentation URL is invalid.');
}
else if (!validator.isNonEmptyString(tokenInfo.verifyApiName)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'The JWT verify API name must be a non-empty string.');
}
else if (!validator.isNonEmptyString(tokenInfo.jwtName)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'The JWT public full name must be a non-empty string.');
}
else if (!validator.isNonEmptyString(tokenInfo.shortName)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'The JWT public short name must be a non-empty string.');
}
else if (!validator.isNonNullObject(tokenInfo.expiredErrorCode) || !('code' in tokenInfo.expiredErrorCode)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, 'The JWT expiration error code must be a non-null ErrorInfo object.');
}
this.shortNameArticle = tokenInfo.shortName.charAt(0).match(/[aeiou]/i) ? 'an' : 'a';
this.signatureVerifier =
jwt_1.PublicKeySignatureVerifier.withCertificateUrl(clientCertUrl, app.options.httpAgent);
// For backward compatibility, the project ID is validated in the verification call.
}
/**
* Verifies the format and signature of a Firebase Auth JWT token.
*
* @param jwtToken - The Firebase Auth JWT token to verify.
* @param isEmulator - Whether to accept Auth Emulator tokens.
* @returns A promise fulfilled with the decoded claims of the Firebase Auth ID token.
*/
verifyJWT(jwtToken, isEmulator = false) {
if (!validator.isString(jwtToken)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, `First argument to ${this.tokenInfo.verifyApiName} must be a ${this.tokenInfo.jwtName} string.`);
}
return this.ensureProjectId()
.then((projectId) => {
return this.decodeAndVerify(jwtToken, projectId, isEmulator);
})
.then((decoded) => {
const decodedIdToken = decoded.payload;
decodedIdToken.uid = decodedIdToken.sub;
return decodedIdToken;
});
}
/** @alpha */
// eslint-disable-next-line @typescript-eslint/naming-convention
_verifyAuthBlockingToken(jwtToken, isEmulator, audience) {
if (!validator.isString(jwtToken)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, `First argument to ${this.tokenInfo.verifyApiName} must be a ${this.tokenInfo.jwtName} string.`);
}
return this.ensureProjectId()
.then((projectId) => {
if (typeof audience === 'undefined') {
audience = `${projectId}.cloudfunctions.net/`;
}
return this.decodeAndVerify(jwtToken, projectId, isEmulator, audience);
})
.then((decoded) => {
const decodedAuthBlockingToken = decoded.payload;
decodedAuthBlockingToken.uid = decodedAuthBlockingToken.sub;
return decodedAuthBlockingToken;
});
}
ensureProjectId() {
return util.findProjectId(this.app)
.then((projectId) => {
if (!validator.isNonEmptyString(projectId)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_CREDENTIAL, 'Must initialize app with a cert credential or set your Firebase project ID as the ' +
`GOOGLE_CLOUD_PROJECT environment variable to call ${this.tokenInfo.verifyApiName}.`);
}
return Promise.resolve(projectId);
});
}
decodeAndVerify(token, projectId, isEmulator, audience) {
return this.safeDecode(token)
.then((decodedToken) => {
this.verifyContent(decodedToken, projectId, isEmulator, audience);
return this.verifySignature(token, isEmulator)
.then(() => decodedToken);
});
}
safeDecode(jwtToken) {
return (0, jwt_1.decodeJwt)(jwtToken)
.catch((err) => {
if (err.code === jwt_1.JwtErrorCode.INVALID_ARGUMENT) {
const verifyJwtTokenDocsMessage = ` See ${this.tokenInfo.url} ` +
`for details on how to retrieve ${this.shortNameArticle} ${this.tokenInfo.shortName}.`;
const errorMessage = `Decoding ${this.tokenInfo.jwtName} failed. Make sure you passed ` +
`the entire string JWT which represents ${this.shortNameArticle} ` +
`${this.tokenInfo.shortName}.` + verifyJwtTokenDocsMessage;
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, errorMessage);
}
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, err.message);
});
}
/**
* Verifies the content of a Firebase Auth JWT.
*
* @param fullDecodedToken - The decoded JWT.
* @param projectId - The Firebase Project Id.
* @param isEmulator - Whether the token is an Emulator token.
*/
verifyContent(fullDecodedToken, projectId, isEmulator, audience) {
const header = fullDecodedToken && fullDecodedToken.header;
const payload = fullDecodedToken && fullDecodedToken.payload;
const projectIdMatchMessage = ` Make sure the ${this.tokenInfo.shortName} comes from the same ` +
'Firebase project as the service account used to authenticate this SDK.';
const verifyJwtTokenDocsMessage = ` See ${this.tokenInfo.url} ` +
`for details on how to retrieve ${this.shortNameArticle} ${this.tokenInfo.shortName}.`;
let errorMessage;
if (!isEmulator && typeof header.kid === 'undefined') {
const isCustomToken = (payload.aud === FIREBASE_AUDIENCE);
const isLegacyCustomToken = (header.alg === 'HS256' && payload.v === 0 && 'd' in payload && 'uid' in payload.d);
if (isCustomToken) {
errorMessage = `${this.tokenInfo.verifyApiName} expects ${this.shortNameArticle} ` +
`${this.tokenInfo.shortName}, but was given a custom token.`;
}
else if (isLegacyCustomToken) {
errorMessage = `${this.tokenInfo.verifyApiName} expects ${this.shortNameArticle} ` +
`${this.tokenInfo.shortName}, but was given a legacy custom token.`;
}
else {
errorMessage = `${this.tokenInfo.jwtName} has no "kid" claim.`;
}
errorMessage += verifyJwtTokenDocsMessage;
}
else if (!isEmulator && header.alg !== jwt_1.ALGORITHM_RS256) {
errorMessage = `${this.tokenInfo.jwtName} has incorrect algorithm. Expected "` + jwt_1.ALGORITHM_RS256 + '" but got ' +
'"' + header.alg + '".' + verifyJwtTokenDocsMessage;
}
else if (typeof audience !== 'undefined' && !payload.aud.includes(audience)) {
errorMessage = `${this.tokenInfo.jwtName} has incorrect "aud" (audience) claim. Expected "` +
audience + '" but got "' + payload.aud + '".' + verifyJwtTokenDocsMessage;
}
else if (typeof audience === 'undefined' && payload.aud !== projectId) {
errorMessage = `${this.tokenInfo.jwtName} has incorrect "aud" (audience) claim. Expected "` +
projectId + '" but got "' + payload.aud + '".' + projectIdMatchMessage +
verifyJwtTokenDocsMessage;
}
else if (payload.iss !== this.issuer + projectId) {
errorMessage = `${this.tokenInfo.jwtName} has incorrect "iss" (issuer) claim. Expected ` +
`"${this.issuer}` + projectId + '" but got "' +
payload.iss + '".' + projectIdMatchMessage + verifyJwtTokenDocsMessage;
}
else if (!(payload.event_type !== undefined &&
(payload.event_type === 'beforeSendSms' || payload.event_type === 'beforeSendEmail'))) {
// excluding `beforeSendSms` and `beforeSendEmail` from processing `sub` as there is no user record available.
// `sub` is the same as `uid` which is part of the user record.
if (typeof payload.sub !== 'string') {
errorMessage = `${this.tokenInfo.jwtName} has no "sub" (subject) claim.` + verifyJwtTokenDocsMessage;
}
else if (payload.sub === '') {
errorMessage = `${this.tokenInfo.jwtName} has an empty "sub" (subject) claim.` +
verifyJwtTokenDocsMessage;
}
else if (payload.sub.length > 128) {
errorMessage = `${this.tokenInfo.jwtName} has a "sub" (subject) claim longer than 128 characters.` +
verifyJwtTokenDocsMessage;
}
}
if (errorMessage) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, errorMessage);
}
}
verifySignature(jwtToken, isEmulator) {
const verifier = isEmulator ? EMULATOR_VERIFIER : this.signatureVerifier;
return verifier.verify(jwtToken)
.catch((error) => {
throw this.mapJwtErrorToAuthError(error);
});
}
/**
* Maps JwtError to FirebaseAuthError
*
* @param error - JwtError to be mapped.
* @returns FirebaseAuthError or Error instance.
*/
mapJwtErrorToAuthError(error) {
const verifyJwtTokenDocsMessage = ` See ${this.tokenInfo.url} ` +
`for details on how to retrieve ${this.shortNameArticle} ${this.tokenInfo.shortName}.`;
if (error.code === jwt_1.JwtErrorCode.TOKEN_EXPIRED) {
const errorMessage = `${this.tokenInfo.jwtName} has expired. Get a fresh ${this.tokenInfo.shortName}` +
` from your client app and try again (auth/${this.tokenInfo.expiredErrorCode.code}).` +
verifyJwtTokenDocsMessage;
return new error_1.FirebaseAuthError(this.tokenInfo.expiredErrorCode, errorMessage);
}
else if (error.code === jwt_1.JwtErrorCode.INVALID_SIGNATURE) {
const errorMessage = `${this.tokenInfo.jwtName} has invalid signature.` + verifyJwtTokenDocsMessage;
return new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, errorMessage);
}
else if (error.code === jwt_1.JwtErrorCode.NO_MATCHING_KID) {
const errorMessage = `${this.tokenInfo.jwtName} has "kid" claim which does not ` +
`correspond to a known public key. Most likely the ${this.tokenInfo.shortName} ` +
'is expired, so get a fresh token from your client app and try again.';
return new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, errorMessage);
}
return new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, error.message);
}
}
exports.FirebaseTokenVerifier = FirebaseTokenVerifier;
/**
* Creates a new FirebaseTokenVerifier to verify Firebase ID tokens.
*
* @internal
* @param app - Firebase app instance.
* @returns FirebaseTokenVerifier
*/
function createIdTokenVerifier(app) {
return new FirebaseTokenVerifier(CLIENT_CERT_URL, 'https://securetoken.google.com/', exports.ID_TOKEN_INFO, app);
}
/**
* Creates a new FirebaseTokenVerifier to verify Firebase Auth Blocking tokens.
*
* @internal
* @param app - Firebase app instance.
* @returns FirebaseTokenVerifier
*/
function createAuthBlockingTokenVerifier(app) {
return new FirebaseTokenVerifier(CLIENT_CERT_URL, 'https://securetoken.google.com/', exports.AUTH_BLOCKING_TOKEN_INFO, app);
}
/**
* Creates a new FirebaseTokenVerifier to verify Firebase session cookies.
*
* @internal
* @param app - Firebase app instance.
* @returns FirebaseTokenVerifier
*/
function createSessionCookieVerifier(app) {
return new FirebaseTokenVerifier(SESSION_COOKIE_CERT_URL, 'https://session.firebase.google.com/', exports.SESSION_COOKIE_INFO, app);
}

View File

@@ -0,0 +1,321 @@
/*! firebase-admin v13.5.0 */
/*!
* Copyright 2018 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.
*/
import { FirebaseArrayIndexError } from '../app/index';
import { UpdateMultiFactorInfoRequest, MultiFactorUpdateSettings } from './auth-config';
export type HashAlgorithmType = 'SCRYPT' | 'STANDARD_SCRYPT' | 'HMAC_SHA512' | 'HMAC_SHA256' | 'HMAC_SHA1' | 'HMAC_MD5' | 'MD5' | 'PBKDF_SHA1' | 'BCRYPT' | 'PBKDF2_SHA256' | 'SHA512' | 'SHA256' | 'SHA1';
/**
* Interface representing the user import options needed for
* {@link BaseAuth.importUsers} method. This is used to
* provide the password hashing algorithm information.
*/
export interface UserImportOptions {
/**
* The password hashing information.
*/
hash: {
/**
* The password hashing algorithm identifier. The following algorithm
* identifiers are supported:
* `SCRYPT`, `STANDARD_SCRYPT`, `HMAC_SHA512`, `HMAC_SHA256`, `HMAC_SHA1`,
* `HMAC_MD5`, `MD5`, `PBKDF_SHA1`, `BCRYPT`, `PBKDF2_SHA256`, `SHA512`,
* `SHA256` and `SHA1`.
*/
algorithm: HashAlgorithmType;
/**
* The signing key used in the hash algorithm in buffer bytes.
* Required by hashing algorithms `SCRYPT`, `HMAC_SHA512`, `HMAC_SHA256`,
* `HAMC_SHA1` and `HMAC_MD5`.
*/
key?: Buffer;
/**
* The salt separator in buffer bytes which is appended to salt when
* verifying a password. This is only used by the `SCRYPT` algorithm.
*/
saltSeparator?: Buffer;
/**
* The number of rounds for hashing calculation.
* Required for `SCRYPT`, `MD5`, `SHA512`, `SHA256`, `SHA1`, `PBKDF_SHA1` and
* `PBKDF2_SHA256`.
*/
rounds?: number;
/**
* The memory cost required for `SCRYPT` algorithm, or the CPU/memory cost.
* Required for `STANDARD_SCRYPT` algorithm.
*/
memoryCost?: number;
/**
* The parallelization of the hashing algorithm. Required for the
* `STANDARD_SCRYPT` algorithm.
*/
parallelization?: number;
/**
* The block size (normally 8) of the hashing algorithm. Required for the
* `STANDARD_SCRYPT` algorithm.
*/
blockSize?: number;
/**
* The derived key length of the hashing algorithm. Required for the
* `STANDARD_SCRYPT` algorithm.
*/
derivedKeyLength?: number;
};
}
/**
* Interface representing a user to import to Firebase Auth via the
* {@link BaseAuth.importUsers} method.
*/
export interface UserImportRecord {
/**
* The user's `uid`.
*/
uid: string;
/**
* The user's primary email, if set.
*/
email?: string;
/**
* Whether or not the user's primary email is verified.
*/
emailVerified?: boolean;
/**
* The user's display name.
*/
displayName?: string;
/**
* The user's primary phone number, if set.
*/
phoneNumber?: string;
/**
* The user's photo URL.
*/
photoURL?: string;
/**
* Whether or not the user is disabled: `true` for disabled; `false` for
* enabled.
*/
disabled?: boolean;
/**
* Additional metadata about the user.
*/
metadata?: UserMetadataRequest;
/**
* An array of providers (for example, Google, Facebook) linked to the user.
*/
providerData?: UserProviderRequest[];
/**
* The user's custom claims object if available, typically used to define
* user roles and propagated to an authenticated user's ID token.
*/
customClaims?: {
[key: string]: any;
};
/**
* The buffer of bytes representing the user's hashed password.
* When a user is to be imported with a password hash,
* {@link UserImportOptions} are required to be
* specified to identify the hashing algorithm used to generate this hash.
*/
passwordHash?: Buffer;
/**
* The buffer of bytes representing the user's password salt.
*/
passwordSalt?: Buffer;
/**
* The identifier of the tenant where user is to be imported to.
* When not provided in an `admin.auth.Auth` context, the user is uploaded to
* the default parent project.
* When not provided in an `admin.auth.TenantAwareAuth` context, the user is uploaded
* to the tenant corresponding to that `TenantAwareAuth` instance's tenant ID.
*/
tenantId?: string;
/**
* The user's multi-factor related properties.
*/
multiFactor?: MultiFactorUpdateSettings;
}
/**
* User metadata to include when importing a user.
*/
export interface UserMetadataRequest {
/**
* The date the user last signed in, formatted as a UTC string.
*/
lastSignInTime?: string;
/**
* The date the user was created, formatted as a UTC string.
*/
creationTime?: string;
}
/**
* User provider data to include when importing a user.
*/
export interface UserProviderRequest {
/**
* The user identifier for the linked provider.
*/
uid: string;
/**
* The display name for the linked provider.
*/
displayName?: string;
/**
* The email for the linked provider.
*/
email?: string;
/**
* The phone number for the linked provider.
*/
phoneNumber?: string;
/**
* The photo URL for the linked provider.
*/
photoURL?: string;
/**
* The linked provider ID (for example, "google.com" for the Google provider).
*/
providerId: string;
}
/**
* Interface representing the response from the
* {@link BaseAuth.importUsers} method for batch
* importing users to Firebase Auth.
*/
export interface UserImportResult {
/**
* The number of user records that failed to import to Firebase Auth.
*/
failureCount: number;
/**
* The number of user records that successfully imported to Firebase Auth.
*/
successCount: number;
/**
* An array of errors corresponding to the provided users to import. The
* length of this array is equal to [`failureCount`](#failureCount).
*/
errors: FirebaseArrayIndexError[];
}
/** Interface representing an Auth second factor in Auth server format. */
export interface AuthFactorInfo {
mfaEnrollmentId?: string;
displayName?: string;
phoneInfo?: string;
enrolledAt?: string;
[key: string]: any;
}
/** UploadAccount endpoint request user interface. */
interface UploadAccountUser {
localId: string;
email?: string;
emailVerified?: boolean;
displayName?: string;
disabled?: boolean;
photoUrl?: string;
phoneNumber?: string;
providerUserInfo?: Array<{
rawId: string;
providerId: string;
email?: string;
displayName?: string;
photoUrl?: string;
}>;
mfaInfo?: AuthFactorInfo[];
passwordHash?: string;
salt?: string;
lastLoginAt?: number;
createdAt?: number;
customAttributes?: string;
tenantId?: string;
}
/** UploadAccount endpoint request hash options. */
export interface UploadAccountOptions {
hashAlgorithm?: string;
signerKey?: string;
rounds?: number;
memoryCost?: number;
saltSeparator?: string;
cpuMemCost?: number;
parallelization?: number;
blockSize?: number;
dkLen?: number;
}
/** UploadAccount endpoint complete request interface. */
export interface UploadAccountRequest extends UploadAccountOptions {
users?: UploadAccountUser[];
}
/** Callback function to validate an UploadAccountUser object. */
export type ValidatorFunction = (data: UploadAccountUser) => void;
/**
* Converts a client format second factor object to server format.
* @param multiFactorInfo - The client format second factor.
* @returns The corresponding AuthFactorInfo server request format.
*/
export declare function convertMultiFactorInfoToServerFormat(multiFactorInfo: UpdateMultiFactorInfoRequest): AuthFactorInfo;
/**
* Class that provides a helper for building/validating uploadAccount requests and
* UserImportResult responses.
*/
export declare class UserImportBuilder {
private requiresHashOptions;
private validatedUsers;
private validatedOptions;
private indexMap;
private userImportResultErrors;
/**
* @param {UserImportRecord[]} users The list of user records to import.
* @param {UserImportOptions=} options The import options which includes hashing
* algorithm details.
* @param {ValidatorFunction=} userRequestValidator The user request validator function.
* @constructor
*/
constructor(users: UserImportRecord[], options?: UserImportOptions, userRequestValidator?: ValidatorFunction);
/**
* Returns the corresponding constructed uploadAccount request.
* @returns {UploadAccountRequest} The constructed uploadAccount request.
*/
buildRequest(): UploadAccountRequest;
/**
* Populates the UserImportResult using the client side detected errors and the server
* side returned errors.
* @returns {UserImportResult} The user import result based on the returned failed
* uploadAccount response.
*/
buildResponse(failedUploads: Array<{
index: number;
message: string;
}>): UserImportResult;
/**
* Validates and returns the hashing options of the uploadAccount request.
* Throws an error whenever an invalid or missing options is detected.
* @param {UserImportOptions} options The UserImportOptions.
* @param {boolean} requiresHashOptions Whether to require hash options.
* @returns {UploadAccountOptions} The populated UploadAccount options.
*/
private populateOptions;
/**
* Validates and returns the users list of the uploadAccount request.
* Whenever a user with an error is detected, the error is cached and will later be
* merged into the user import result. This allows the processing of valid users without
* failing early on the first error detected.
* @param {UserImportRecord[]} users The UserImportRecords to convert to UnploadAccountUser
* objects.
* @param {ValidatorFunction=} userValidator The user validator function.
* @returns {UploadAccountUser[]} The populated uploadAccount users.
*/
private populateUsers;
}
export {};

View File

@@ -0,0 +1,384 @@
/*! firebase-admin v13.5.0 */
"use strict";
/*!
* Copyright 2018 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.UserImportBuilder = void 0;
exports.convertMultiFactorInfoToServerFormat = convertMultiFactorInfoToServerFormat;
const deep_copy_1 = require("../utils/deep-copy");
const utils = require("../utils");
const validator = require("../utils/validator");
const error_1 = require("../utils/error");
/**
* Converts a client format second factor object to server format.
* @param multiFactorInfo - The client format second factor.
* @returns The corresponding AuthFactorInfo server request format.
*/
function convertMultiFactorInfoToServerFormat(multiFactorInfo) {
let enrolledAt;
if (typeof multiFactorInfo.enrollmentTime !== 'undefined') {
if (validator.isUTCDateString(multiFactorInfo.enrollmentTime)) {
// Convert from UTC date string (client side format) to ISO date string (server side format).
enrolledAt = new Date(multiFactorInfo.enrollmentTime).toISOString();
}
else {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ENROLLMENT_TIME, `The second factor "enrollmentTime" for "${multiFactorInfo.uid}" must be a valid ` +
'UTC date string.');
}
}
// Currently only phone second factors are supported.
if (isPhoneFactor(multiFactorInfo)) {
// If any required field is missing or invalid, validation will still fail later.
const authFactorInfo = {
mfaEnrollmentId: multiFactorInfo.uid,
displayName: multiFactorInfo.displayName,
// Required for all phone second factors.
phoneInfo: multiFactorInfo.phoneNumber,
enrolledAt,
};
for (const objKey in authFactorInfo) {
if (typeof authFactorInfo[objKey] === 'undefined') {
delete authFactorInfo[objKey];
}
}
return authFactorInfo;
}
else {
// Unsupported second factor.
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.UNSUPPORTED_SECOND_FACTOR, `Unsupported second factor "${JSON.stringify(multiFactorInfo)}" provided.`);
}
}
function isPhoneFactor(multiFactorInfo) {
return multiFactorInfo.factorId === 'phone';
}
/**
* @param {any} obj The object to check for number field within.
* @param {string} key The entry key.
* @returns {number} The corresponding number if available. Otherwise, NaN.
*/
function getNumberField(obj, key) {
if (typeof obj[key] !== 'undefined' && obj[key] !== null) {
return parseInt(obj[key].toString(), 10);
}
return NaN;
}
/**
* Converts a UserImportRecord to a UploadAccountUser object. Throws an error when invalid
* fields are provided.
* @param {UserImportRecord} user The UserImportRecord to conver to UploadAccountUser.
* @param {ValidatorFunction=} userValidator The user validator function.
* @returns {UploadAccountUser} The corresponding UploadAccountUser to return.
*/
function populateUploadAccountUser(user, userValidator) {
const result = {
localId: user.uid,
email: user.email,
emailVerified: user.emailVerified,
displayName: user.displayName,
disabled: user.disabled,
photoUrl: user.photoURL,
phoneNumber: user.phoneNumber,
providerUserInfo: [],
mfaInfo: [],
tenantId: user.tenantId,
customAttributes: user.customClaims && JSON.stringify(user.customClaims),
};
if (typeof user.passwordHash !== 'undefined') {
if (!validator.isBuffer(user.passwordHash)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD_HASH);
}
result.passwordHash = utils.toWebSafeBase64(user.passwordHash);
}
if (typeof user.passwordSalt !== 'undefined') {
if (!validator.isBuffer(user.passwordSalt)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_PASSWORD_SALT);
}
result.salt = utils.toWebSafeBase64(user.passwordSalt);
}
if (validator.isNonNullObject(user.metadata)) {
if (validator.isNonEmptyString(user.metadata.creationTime)) {
result.createdAt = new Date(user.metadata.creationTime).getTime();
}
if (validator.isNonEmptyString(user.metadata.lastSignInTime)) {
result.lastLoginAt = new Date(user.metadata.lastSignInTime).getTime();
}
}
if (validator.isArray(user.providerData)) {
user.providerData.forEach((providerData) => {
result.providerUserInfo.push({
providerId: providerData.providerId,
rawId: providerData.uid,
email: providerData.email,
displayName: providerData.displayName,
photoUrl: providerData.photoURL,
});
});
}
// Convert user.multiFactor.enrolledFactors to server format.
if (validator.isNonNullObject(user.multiFactor) &&
validator.isNonEmptyArray(user.multiFactor.enrolledFactors)) {
user.multiFactor.enrolledFactors.forEach((multiFactorInfo) => {
result.mfaInfo.push(convertMultiFactorInfoToServerFormat(multiFactorInfo));
});
}
// Remove blank fields.
let key;
for (key in result) {
if (typeof result[key] === 'undefined') {
delete result[key];
}
}
if (result.providerUserInfo.length === 0) {
delete result.providerUserInfo;
}
if (result.mfaInfo.length === 0) {
delete result.mfaInfo;
}
// Validate the constructured user individual request. This will throw if an error
// is detected.
if (typeof userValidator === 'function') {
userValidator(result);
}
return result;
}
/**
* Class that provides a helper for building/validating uploadAccount requests and
* UserImportResult responses.
*/
class UserImportBuilder {
/**
* @param {UserImportRecord[]} users The list of user records to import.
* @param {UserImportOptions=} options The import options which includes hashing
* algorithm details.
* @param {ValidatorFunction=} userRequestValidator The user request validator function.
* @constructor
*/
constructor(users, options, userRequestValidator) {
this.requiresHashOptions = false;
this.validatedUsers = [];
this.userImportResultErrors = [];
this.indexMap = {};
this.validatedUsers = this.populateUsers(users, userRequestValidator);
this.validatedOptions = this.populateOptions(options, this.requiresHashOptions);
}
/**
* Returns the corresponding constructed uploadAccount request.
* @returns {UploadAccountRequest} The constructed uploadAccount request.
*/
buildRequest() {
const users = this.validatedUsers.map((user) => {
return (0, deep_copy_1.deepCopy)(user);
});
return (0, deep_copy_1.deepExtend)({ users }, (0, deep_copy_1.deepCopy)(this.validatedOptions));
}
/**
* Populates the UserImportResult using the client side detected errors and the server
* side returned errors.
* @returns {UserImportResult} The user import result based on the returned failed
* uploadAccount response.
*/
buildResponse(failedUploads) {
// Initialize user import result.
const importResult = {
successCount: this.validatedUsers.length,
failureCount: this.userImportResultErrors.length,
errors: (0, deep_copy_1.deepCopy)(this.userImportResultErrors),
};
importResult.failureCount += failedUploads.length;
importResult.successCount -= failedUploads.length;
failedUploads.forEach((failedUpload) => {
importResult.errors.push({
// Map backend request index to original developer provided array index.
index: this.indexMap[failedUpload.index],
error: new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_USER_IMPORT, failedUpload.message),
});
});
// Sort errors by index.
importResult.errors.sort((a, b) => {
return a.index - b.index;
});
// Return sorted result.
return importResult;
}
/**
* Validates and returns the hashing options of the uploadAccount request.
* Throws an error whenever an invalid or missing options is detected.
* @param {UserImportOptions} options The UserImportOptions.
* @param {boolean} requiresHashOptions Whether to require hash options.
* @returns {UploadAccountOptions} The populated UploadAccount options.
*/
populateOptions(options, requiresHashOptions) {
let populatedOptions;
if (!requiresHashOptions) {
return {};
}
if (!validator.isNonNullObject(options)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_ARGUMENT, '"UserImportOptions" are required when importing users with passwords.');
}
if (!validator.isNonNullObject(options.hash)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.MISSING_HASH_ALGORITHM, '"hash.algorithm" is missing from the provided "UserImportOptions".');
}
if (typeof options.hash.algorithm === 'undefined' ||
!validator.isNonEmptyString(options.hash.algorithm)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_ALGORITHM, '"hash.algorithm" must be a string matching the list of supported algorithms.');
}
let rounds;
switch (options.hash.algorithm) {
case 'HMAC_SHA512':
case 'HMAC_SHA256':
case 'HMAC_SHA1':
case 'HMAC_MD5':
if (!validator.isBuffer(options.hash.key)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_KEY, 'A non-empty "hash.key" byte buffer must be provided for ' +
`hash algorithm ${options.hash.algorithm}.`);
}
populatedOptions = {
hashAlgorithm: options.hash.algorithm,
signerKey: utils.toWebSafeBase64(options.hash.key),
};
break;
case 'MD5':
case 'SHA1':
case 'SHA256':
case 'SHA512': {
// MD5 is [0,8192] but SHA1, SHA256, and SHA512 are [1,8192]
rounds = getNumberField(options.hash, 'rounds');
const minRounds = options.hash.algorithm === 'MD5' ? 0 : 1;
if (isNaN(rounds) || rounds < minRounds || rounds > 8192) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_ROUNDS, `A valid "hash.rounds" number between ${minRounds} and 8192 must be provided for ` +
`hash algorithm ${options.hash.algorithm}.`);
}
populatedOptions = {
hashAlgorithm: options.hash.algorithm,
rounds,
};
break;
}
case 'PBKDF_SHA1':
case 'PBKDF2_SHA256':
rounds = getNumberField(options.hash, 'rounds');
if (isNaN(rounds) || rounds < 0 || rounds > 120000) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_ROUNDS, 'A valid "hash.rounds" number between 0 and 120000 must be provided for ' +
`hash algorithm ${options.hash.algorithm}.`);
}
populatedOptions = {
hashAlgorithm: options.hash.algorithm,
rounds,
};
break;
case 'SCRYPT': {
if (!validator.isBuffer(options.hash.key)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_KEY, 'A "hash.key" byte buffer must be provided for ' +
`hash algorithm ${options.hash.algorithm}.`);
}
rounds = getNumberField(options.hash, 'rounds');
if (isNaN(rounds) || rounds <= 0 || rounds > 8) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_ROUNDS, 'A valid "hash.rounds" number between 1 and 8 must be provided for ' +
`hash algorithm ${options.hash.algorithm}.`);
}
const memoryCost = getNumberField(options.hash, 'memoryCost');
if (isNaN(memoryCost) || memoryCost <= 0 || memoryCost > 14) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_MEMORY_COST, 'A valid "hash.memoryCost" number between 1 and 14 must be provided for ' +
`hash algorithm ${options.hash.algorithm}.`);
}
if (typeof options.hash.saltSeparator !== 'undefined' &&
!validator.isBuffer(options.hash.saltSeparator)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_SALT_SEPARATOR, '"hash.saltSeparator" must be a byte buffer.');
}
populatedOptions = {
hashAlgorithm: options.hash.algorithm,
signerKey: utils.toWebSafeBase64(options.hash.key),
rounds,
memoryCost,
saltSeparator: utils.toWebSafeBase64(options.hash.saltSeparator || Buffer.from('')),
};
break;
}
case 'BCRYPT':
populatedOptions = {
hashAlgorithm: options.hash.algorithm,
};
break;
case 'STANDARD_SCRYPT': {
const cpuMemCost = getNumberField(options.hash, 'memoryCost');
if (isNaN(cpuMemCost)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_MEMORY_COST, 'A valid "hash.memoryCost" number must be provided for ' +
`hash algorithm ${options.hash.algorithm}.`);
}
const parallelization = getNumberField(options.hash, 'parallelization');
if (isNaN(parallelization)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_PARALLELIZATION, 'A valid "hash.parallelization" number must be provided for ' +
`hash algorithm ${options.hash.algorithm}.`);
}
const blockSize = getNumberField(options.hash, 'blockSize');
if (isNaN(blockSize)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_BLOCK_SIZE, 'A valid "hash.blockSize" number must be provided for ' +
`hash algorithm ${options.hash.algorithm}.`);
}
const dkLen = getNumberField(options.hash, 'derivedKeyLength');
if (isNaN(dkLen)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_DERIVED_KEY_LENGTH, 'A valid "hash.derivedKeyLength" number must be provided for ' +
`hash algorithm ${options.hash.algorithm}.`);
}
populatedOptions = {
hashAlgorithm: options.hash.algorithm,
cpuMemCost,
parallelization,
blockSize,
dkLen,
};
break;
}
default:
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INVALID_HASH_ALGORITHM, `Unsupported hash algorithm provider "${options.hash.algorithm}".`);
}
return populatedOptions;
}
/**
* Validates and returns the users list of the uploadAccount request.
* Whenever a user with an error is detected, the error is cached and will later be
* merged into the user import result. This allows the processing of valid users without
* failing early on the first error detected.
* @param {UserImportRecord[]} users The UserImportRecords to convert to UnploadAccountUser
* objects.
* @param {ValidatorFunction=} userValidator The user validator function.
* @returns {UploadAccountUser[]} The populated uploadAccount users.
*/
populateUsers(users, userValidator) {
const populatedUsers = [];
users.forEach((user, index) => {
try {
const result = populateUploadAccountUser(user, userValidator);
if (typeof result.passwordHash !== 'undefined') {
this.requiresHashOptions = true;
}
// Only users that pass client screening will be passed to backend for processing.
populatedUsers.push(result);
// Map user's index (the one to be sent to backend) to original developer provided array.
this.indexMap[populatedUsers.length - 1] = index;
}
catch (error) {
// Save the client side error with respect to the developer provided array.
this.userImportResultErrors.push({
index,
error,
});
}
});
return populatedUsers;
}
}
exports.UserImportBuilder = UserImportBuilder;

View File

@@ -0,0 +1,289 @@
/*! firebase-admin v13.5.0 */
/*!
* @license
* Copyright 2017 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.
*/
export interface MultiFactorInfoResponse {
mfaEnrollmentId: string;
displayName?: string;
phoneInfo?: string;
totpInfo?: TotpInfoResponse;
enrolledAt?: string;
[key: string]: unknown;
}
export interface TotpInfoResponse {
[key: string]: unknown;
}
export interface ProviderUserInfoResponse {
rawId: string;
displayName?: string;
email?: string;
photoUrl?: string;
phoneNumber?: string;
providerId: string;
federatedId?: string;
}
export interface GetAccountInfoUserResponse {
localId: string;
email?: string;
emailVerified?: boolean;
phoneNumber?: string;
displayName?: string;
photoUrl?: string;
disabled?: boolean;
passwordHash?: string;
salt?: string;
customAttributes?: string;
validSince?: string;
tenantId?: string;
providerUserInfo?: ProviderUserInfoResponse[];
mfaInfo?: MultiFactorInfoResponse[];
createdAt?: string;
lastLoginAt?: string;
lastRefreshAt?: string;
[key: string]: any;
}
/**
* Interface representing the common properties of a user-enrolled second factor.
*/
export declare abstract class MultiFactorInfo {
/**
* The ID of the enrolled second factor. This ID is unique to the user.
*/
readonly uid: string;
/**
* The optional display name of the enrolled second factor.
*/
readonly displayName?: string;
/**
* The type identifier of the second factor.
* For SMS second factors, this is `phone`.
* For TOTP second factors, this is `totp`.
*/
readonly factorId: string;
/**
* The optional date the second factor was enrolled, formatted as a UTC string.
*/
readonly enrollmentTime?: string;
/**
* Returns a JSON-serializable representation of this object.
*
* @returns A JSON-serializable representation of this object.
*/
toJSON(): object;
/**
* Initializes the MultiFactorInfo object using the provided server response.
*
* @param response - The server side response.
*/
private initFromServerResponse;
}
/**
* Interface representing a phone specific user-enrolled second factor.
*/
export declare class PhoneMultiFactorInfo extends MultiFactorInfo {
/**
* The phone number associated with a phone second factor.
*/
readonly phoneNumber: string;
/**
* {@inheritdoc MultiFactorInfo.toJSON}
*/
toJSON(): object;
}
/**
* `TotpInfo` struct associated with a second factor
*/
export declare class TotpInfo {
}
/**
* Interface representing a TOTP specific user-enrolled second factor.
*/
export declare class TotpMultiFactorInfo extends MultiFactorInfo {
/**
* `TotpInfo` struct associated with a second factor
*/
readonly totpInfo: TotpInfo;
/**
* {@inheritdoc MultiFactorInfo.toJSON}
*/
toJSON(): object;
}
/**
* The multi-factor related user settings.
*/
export declare class MultiFactorSettings {
/**
* List of second factors enrolled with the current user.
* Currently only phone and TOTP second factors are supported.
*/
enrolledFactors: MultiFactorInfo[];
/**
* Returns a JSON-serializable representation of this multi-factor object.
*
* @returns A JSON-serializable representation of this multi-factor object.
*/
toJSON(): object;
}
/**
* Represents a user's metadata.
*/
export declare class UserMetadata {
/**
* The date the user was created, formatted as a UTC string.
*/
readonly creationTime: string;
/**
* The date the user last signed in, formatted as a UTC string.
*/
readonly lastSignInTime: string;
/**
* The time at which the user was last active (ID token refreshed),
* formatted as a UTC Date string (eg 'Sat, 03 Feb 2001 04:05:06 GMT').
* Returns null if the user was never active.
*/
readonly lastRefreshTime?: string | null;
/**
* Returns a JSON-serializable representation of this object.
*
* @returns A JSON-serializable representation of this object.
*/
toJSON(): object;
}
/**
* Represents a user's info from a third-party identity provider
* such as Google or Facebook.
*/
export declare class UserInfo {
/**
* The user identifier for the linked provider.
*/
readonly uid: string;
/**
* The display name for the linked provider.
*/
readonly displayName: string;
/**
* The email for the linked provider.
*/
readonly email: string;
/**
* The photo URL for the linked provider.
*/
readonly photoURL: string;
/**
* The linked provider ID (for example, "google.com" for the Google provider).
*/
readonly providerId: string;
/**
* The phone number for the linked provider.
*/
readonly phoneNumber: string;
/**
* Returns a JSON-serializable representation of this object.
*
* @returns A JSON-serializable representation of this object.
*/
toJSON(): object;
}
/**
* Represents a user.
*/
export declare class UserRecord {
/**
* The user's `uid`.
*/
readonly uid: string;
/**
* The user's primary email, if set.
*/
readonly email?: string;
/**
* Whether or not the user's primary email is verified.
*/
readonly emailVerified: boolean;
/**
* The user's display name.
*/
readonly displayName?: string;
/**
* The user's photo URL.
*/
readonly photoURL?: string;
/**
* The user's primary phone number, if set.
*/
readonly phoneNumber?: string;
/**
* Whether or not the user is disabled: `true` for disabled; `false` for
* enabled.
*/
readonly disabled: boolean;
/**
* Additional metadata about the user.
*/
readonly metadata: UserMetadata;
/**
* An array of providers (for example, Google, Facebook) linked to the user.
*/
readonly providerData: UserInfo[];
/**
* The user's hashed password (base64-encoded), only if Firebase Auth hashing
* algorithm (SCRYPT) is used. If a different hashing algorithm had been used
* when uploading this user, as is typical when migrating from another Auth
* system, this will be an empty string. If no password is set, this is
* null. This is only available when the user is obtained from
* {@link BaseAuth.listUsers}.
*/
readonly passwordHash?: string;
/**
* The user's password salt (base64-encoded), only if Firebase Auth hashing
* algorithm (SCRYPT) is used. If a different hashing algorithm had been used to
* upload this user, typical when migrating from another Auth system, this will
* be an empty string. If no password is set, this is null. This is only
* available when the user is obtained from {@link BaseAuth.listUsers}.
*/
readonly passwordSalt?: string;
/**
* The user's custom claims object if available, typically used to define
* user roles and propagated to an authenticated user's ID token.
* This is set via {@link BaseAuth.setCustomUserClaims}
*/
readonly customClaims?: {
[key: string]: any;
};
/**
* The ID of the tenant the user belongs to, if available.
*/
readonly tenantId?: string | null;
/**
* The date the user's tokens are valid after, formatted as a UTC string.
* This is updated every time the user's refresh token are revoked either
* from the {@link BaseAuth.revokeRefreshTokens}
* API or from the Firebase Auth backend on big account changes (password
* resets, password or email updates, etc).
*/
readonly tokensValidAfterTime?: string;
/**
* The multi-factor related properties for the current user, if available.
*/
readonly multiFactor?: MultiFactorSettings;
/**
* Returns a JSON-serializable representation of this object.
*
* @returns A JSON-serializable representation of this object.
*/
toJSON(): object;
}

View File

@@ -0,0 +1,411 @@
/*! firebase-admin v13.5.0 */
"use strict";
/*!
* @license
* Copyright 2017 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.UserRecord = exports.UserInfo = exports.UserMetadata = exports.MultiFactorSettings = exports.TotpMultiFactorInfo = exports.TotpInfo = exports.PhoneMultiFactorInfo = exports.MultiFactorInfo = void 0;
const deep_copy_1 = require("../utils/deep-copy");
const validator_1 = require("../utils/validator");
const utils = require("../utils");
const error_1 = require("../utils/error");
/**
* 'REDACTED', encoded as a base64 string.
*/
const B64_REDACTED = Buffer.from('REDACTED').toString('base64');
/**
* Parses a time stamp string or number and returns the corresponding date if valid.
*
* @param time - The unix timestamp string or number in milliseconds.
* @returns The corresponding date as a UTC string, if valid. Otherwise, null.
*/
function parseDate(time) {
try {
const date = new Date(parseInt(time, 10));
if (!isNaN(date.getTime())) {
return date.toUTCString();
}
}
catch (e) {
// Do nothing. null will be returned.
}
return null;
}
var MultiFactorId;
(function (MultiFactorId) {
MultiFactorId["Phone"] = "phone";
MultiFactorId["Totp"] = "totp";
})(MultiFactorId || (MultiFactorId = {}));
/**
* Interface representing the common properties of a user-enrolled second factor.
*/
class MultiFactorInfo {
/**
* Initializes the MultiFactorInfo associated subclass using the server side.
* If no MultiFactorInfo is associated with the response, null is returned.
*
* @param response - The server side response.
* @internal
*/
static initMultiFactorInfo(response) {
let multiFactorInfo = null;
// PhoneMultiFactorInfo, TotpMultiFactorInfo currently available.
try {
if (response.phoneInfo !== undefined) {
multiFactorInfo = new PhoneMultiFactorInfo(response);
}
else if (response.totpInfo !== undefined) {
multiFactorInfo = new TotpMultiFactorInfo(response);
}
else {
// Ignore the other SDK unsupported MFA factors to prevent blocking developers using the current SDK.
}
}
catch (e) {
// Ignore error.
}
return multiFactorInfo;
}
/**
* Initializes the MultiFactorInfo object using the server side response.
*
* @param response - The server side response.
* @constructor
* @internal
*/
constructor(response) {
this.initFromServerResponse(response);
}
/**
* Returns a JSON-serializable representation of this object.
*
* @returns A JSON-serializable representation of this object.
*/
toJSON() {
return {
uid: this.uid,
displayName: this.displayName,
factorId: this.factorId,
enrollmentTime: this.enrollmentTime,
};
}
/**
* Initializes the MultiFactorInfo object using the provided server response.
*
* @param response - The server side response.
*/
initFromServerResponse(response) {
const factorId = response && this.getFactorId(response);
if (!factorId || !response || !response.mfaEnrollmentId) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Invalid multi-factor info response');
}
utils.addReadonlyGetter(this, 'uid', response.mfaEnrollmentId);
utils.addReadonlyGetter(this, 'factorId', factorId);
utils.addReadonlyGetter(this, 'displayName', response.displayName);
// Encoded using [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format.
// For example, "2017-01-15T01:30:15.01Z".
// This can be parsed directly via Date constructor.
// This can be computed using Data.prototype.toISOString.
if (response.enrolledAt) {
utils.addReadonlyGetter(this, 'enrollmentTime', new Date(response.enrolledAt).toUTCString());
}
else {
utils.addReadonlyGetter(this, 'enrollmentTime', null);
}
}
}
exports.MultiFactorInfo = MultiFactorInfo;
/**
* Interface representing a phone specific user-enrolled second factor.
*/
class PhoneMultiFactorInfo extends MultiFactorInfo {
/**
* Initializes the PhoneMultiFactorInfo object using the server side response.
*
* @param response - The server side response.
* @constructor
* @internal
*/
constructor(response) {
super(response);
utils.addReadonlyGetter(this, 'phoneNumber', response.phoneInfo);
}
/**
* {@inheritdoc MultiFactorInfo.toJSON}
*/
toJSON() {
return Object.assign(super.toJSON(), {
phoneNumber: this.phoneNumber,
});
}
/**
* Returns the factor ID based on the response provided.
*
* @param response - The server side response.
* @returns The multi-factor ID associated with the provided response. If the response is
* not associated with any known multi-factor ID, null is returned.
*
* @internal
*/
getFactorId(response) {
return (response && response.phoneInfo) ? MultiFactorId.Phone : null;
}
}
exports.PhoneMultiFactorInfo = PhoneMultiFactorInfo;
/**
* `TotpInfo` struct associated with a second factor
*/
class TotpInfo {
}
exports.TotpInfo = TotpInfo;
/**
* Interface representing a TOTP specific user-enrolled second factor.
*/
class TotpMultiFactorInfo extends MultiFactorInfo {
/**
* Initializes the `TotpMultiFactorInfo` object using the server side response.
*
* @param response - The server side response.
* @constructor
* @internal
*/
constructor(response) {
super(response);
utils.addReadonlyGetter(this, 'totpInfo', response.totpInfo);
}
/**
* {@inheritdoc MultiFactorInfo.toJSON}
*/
toJSON() {
return Object.assign(super.toJSON(), {
totpInfo: this.totpInfo,
});
}
/**
* Returns the factor ID based on the response provided.
*
* @param response - The server side response.
* @returns The multi-factor ID associated with the provided response. If the response is
* not associated with any known multi-factor ID, `null` is returned.
*
* @internal
*/
getFactorId(response) {
return (response && response.totpInfo) ? MultiFactorId.Totp : null;
}
}
exports.TotpMultiFactorInfo = TotpMultiFactorInfo;
/**
* The multi-factor related user settings.
*/
class MultiFactorSettings {
/**
* Initializes the `MultiFactor` object using the server side or JWT format response.
*
* @param response - The server side response.
* @constructor
* @internal
*/
constructor(response) {
const parsedEnrolledFactors = [];
if (!(0, validator_1.isNonNullObject)(response)) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Invalid multi-factor response');
}
else if (response.mfaInfo) {
response.mfaInfo.forEach((factorResponse) => {
const multiFactorInfo = MultiFactorInfo.initMultiFactorInfo(factorResponse);
if (multiFactorInfo) {
parsedEnrolledFactors.push(multiFactorInfo);
}
});
}
// Make enrolled factors immutable.
utils.addReadonlyGetter(this, 'enrolledFactors', Object.freeze(parsedEnrolledFactors));
}
/**
* Returns a JSON-serializable representation of this multi-factor object.
*
* @returns A JSON-serializable representation of this multi-factor object.
*/
toJSON() {
return {
enrolledFactors: this.enrolledFactors.map((info) => info.toJSON()),
};
}
}
exports.MultiFactorSettings = MultiFactorSettings;
/**
* Represents a user's metadata.
*/
class UserMetadata {
/**
* @param response - The server side response returned from the `getAccountInfo`
* endpoint.
* @constructor
* @internal
*/
constructor(response) {
// Creation date should always be available but due to some backend bugs there
// were cases in the past where users did not have creation date properly set.
// This included legacy Firebase migrating project users and some anonymous users.
// These bugs have already been addressed since then.
utils.addReadonlyGetter(this, 'creationTime', parseDate(response.createdAt));
utils.addReadonlyGetter(this, 'lastSignInTime', parseDate(response.lastLoginAt));
const lastRefreshAt = response.lastRefreshAt ? new Date(response.lastRefreshAt).toUTCString() : null;
utils.addReadonlyGetter(this, 'lastRefreshTime', lastRefreshAt);
}
/**
* Returns a JSON-serializable representation of this object.
*
* @returns A JSON-serializable representation of this object.
*/
toJSON() {
return {
lastSignInTime: this.lastSignInTime,
creationTime: this.creationTime,
lastRefreshTime: this.lastRefreshTime,
};
}
}
exports.UserMetadata = UserMetadata;
/**
* Represents a user's info from a third-party identity provider
* such as Google or Facebook.
*/
class UserInfo {
/**
* @param response - The server side response returned from the `getAccountInfo`
* endpoint.
* @constructor
* @internal
*/
constructor(response) {
// Provider user id and provider id are required.
if (!response.rawId || !response.providerId) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Invalid user info response');
}
utils.addReadonlyGetter(this, 'uid', response.rawId);
utils.addReadonlyGetter(this, 'displayName', response.displayName);
utils.addReadonlyGetter(this, 'email', response.email);
utils.addReadonlyGetter(this, 'photoURL', response.photoUrl);
utils.addReadonlyGetter(this, 'providerId', response.providerId);
utils.addReadonlyGetter(this, 'phoneNumber', response.phoneNumber);
}
/**
* Returns a JSON-serializable representation of this object.
*
* @returns A JSON-serializable representation of this object.
*/
toJSON() {
return {
uid: this.uid,
displayName: this.displayName,
email: this.email,
photoURL: this.photoURL,
providerId: this.providerId,
phoneNumber: this.phoneNumber,
};
}
}
exports.UserInfo = UserInfo;
/**
* Represents a user.
*/
class UserRecord {
/**
* @param response - The server side response returned from the getAccountInfo
* endpoint.
* @constructor
* @internal
*/
constructor(response) {
// The Firebase user id is required.
if (!response.localId) {
throw new error_1.FirebaseAuthError(error_1.AuthClientErrorCode.INTERNAL_ERROR, 'INTERNAL ASSERT FAILED: Invalid user response');
}
utils.addReadonlyGetter(this, 'uid', response.localId);
utils.addReadonlyGetter(this, 'email', response.email);
utils.addReadonlyGetter(this, 'emailVerified', !!response.emailVerified);
utils.addReadonlyGetter(this, 'displayName', response.displayName);
utils.addReadonlyGetter(this, 'photoURL', response.photoUrl);
utils.addReadonlyGetter(this, 'phoneNumber', response.phoneNumber);
// If disabled is not provided, the account is enabled by default.
utils.addReadonlyGetter(this, 'disabled', response.disabled || false);
utils.addReadonlyGetter(this, 'metadata', new UserMetadata(response));
const providerData = [];
for (const entry of (response.providerUserInfo || [])) {
providerData.push(new UserInfo(entry));
}
utils.addReadonlyGetter(this, 'providerData', providerData);
// If the password hash is redacted (probably due to missing permissions)
// then clear it out, similar to how the salt is returned. (Otherwise, it
// *looks* like a b64-encoded hash is present, which is confusing.)
if (response.passwordHash === B64_REDACTED) {
utils.addReadonlyGetter(this, 'passwordHash', undefined);
}
else {
utils.addReadonlyGetter(this, 'passwordHash', response.passwordHash);
}
utils.addReadonlyGetter(this, 'passwordSalt', response.salt);
if (response.customAttributes) {
utils.addReadonlyGetter(this, 'customClaims', JSON.parse(response.customAttributes));
}
let validAfterTime = null;
// Convert validSince first to UTC milliseconds and then to UTC date string.
if (typeof response.validSince !== 'undefined') {
validAfterTime = parseDate(parseInt(response.validSince, 10) * 1000);
}
utils.addReadonlyGetter(this, 'tokensValidAfterTime', validAfterTime || undefined);
utils.addReadonlyGetter(this, 'tenantId', response.tenantId);
const multiFactor = new MultiFactorSettings(response);
if (multiFactor.enrolledFactors.length > 0) {
utils.addReadonlyGetter(this, 'multiFactor', multiFactor);
}
}
/**
* Returns a JSON-serializable representation of this object.
*
* @returns A JSON-serializable representation of this object.
*/
toJSON() {
const json = {
uid: this.uid,
email: this.email,
emailVerified: this.emailVerified,
displayName: this.displayName,
photoURL: this.photoURL,
phoneNumber: this.phoneNumber,
disabled: this.disabled,
// Convert metadata to json.
metadata: this.metadata.toJSON(),
passwordHash: this.passwordHash,
passwordSalt: this.passwordSalt,
customClaims: (0, deep_copy_1.deepCopy)(this.customClaims),
tokensValidAfterTime: this.tokensValidAfterTime,
tenantId: this.tenantId,
};
if (this.multiFactor) {
json.multiFactor = this.multiFactor.toJSON();
}
json.providerData = [];
for (const entry of this.providerData) {
// Convert each provider data to json.
json.providerData.push(entry.toJSON());
}
return json;
}
}
exports.UserRecord = UserRecord;