From 48fc76fd048c52771530539c619f8f993fb29323 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 20 Apr 2026 16:15:04 +0100 Subject: [PATCH 01/45] refactor(auth): convert package sources to TypeScript --- ...rmationResult.js => ConfirmationResult.ts} | 1 + ...ctorResolver.js => MultiFactorResolver.ts} | 1 + ...neAuthListener.js => PhoneAuthListener.ts} | 1 + ...erator.js => PhoneMultiFactorGenerator.ts} | 1 + .../auth/lib/{Settings.js => Settings.ts} | 1 + ...nerator.js => TotpMultiFactorGenerator.ts} | 1 + .../auth/lib/{TotpSecret.js => TotpSecret.ts} | 3 +- packages/auth/lib/{User.js => User.ts} | 1 + ...rResolver.js => getMultiFactorResolver.ts} | 1 + packages/auth/lib/index.d.ts | 2339 ----------------- packages/auth/lib/{index.js => index.ts} | 3 +- packages/auth/lib/modular/index.d.ts | 801 ------ .../auth/lib/modular/{index.js => index.ts} | 1 + .../lib/{multiFactor.js => multiFactor.ts} | 1 + ...ordPolicyImpl.js => PasswordPolicyImpl.ts} | 3 +- ...dPolicyMixin.js => PasswordPolicyMixin.ts} | 1 + ...swordPolicyApi.js => passwordPolicyApi.ts} | 1 + ...leAuthProvider.js => AppleAuthProvider.ts} | 1 + ...ilAuthProvider.js => EmailAuthProvider.ts} | 1 + ...uthProvider.js => FacebookAuthProvider.ts} | 1 + ...bAuthProvider.js => GithubAuthProvider.ts} | 1 + ...eAuthProvider.js => GoogleAuthProvider.ts} | 1 + .../{OAuthProvider.js => OAuthProvider.ts} | 1 + ...IDCAuthProvider.js => OIDCAuthProvider.ts} | 1 + ...neAuthProvider.js => PhoneAuthProvider.ts} | 1 + ...AuthProvider.js => TwitterAuthProvider.ts} | 1 + ...e.android.js => RNFBAuthModule.android.ts} | 1 + ...uthModule.ios.js => RNFBAuthModule.ios.ts} | 1 + .../{RNFBAuthModule.js => RNFBAuthModule.ts} | 1 + packages/auth/package.json | 44 +- packages/auth/tsconfig.json | 18 + yarn.lock | 1 + 32 files changed, 87 insertions(+), 3149 deletions(-) rename packages/auth/lib/{ConfirmationResult.js => ConfirmationResult.ts} (98%) rename packages/auth/lib/{MultiFactorResolver.js => MultiFactorResolver.ts} (97%) rename packages/auth/lib/{PhoneAuthListener.js => PhoneAuthListener.ts} (99%) rename packages/auth/lib/{PhoneMultiFactorGenerator.js => PhoneMultiFactorGenerator.ts} (98%) rename packages/auth/lib/{Settings.js => Settings.ts} (99%) rename packages/auth/lib/{TotpMultiFactorGenerator.js => TotpMultiFactorGenerator.ts} (99%) rename packages/auth/lib/{TotpSecret.js => TotpSecret.ts} (97%) rename packages/auth/lib/{User.js => User.ts} (99%) rename packages/auth/lib/{getMultiFactorResolver.js => getMultiFactorResolver.ts} (97%) delete mode 100644 packages/auth/lib/index.d.ts rename packages/auth/lib/{index.js => index.ts} (99%) delete mode 100644 packages/auth/lib/modular/index.d.ts rename packages/auth/lib/modular/{index.js => index.ts} (99%) rename packages/auth/lib/{multiFactor.js => multiFactor.ts} (99%) rename packages/auth/lib/password-policy/{PasswordPolicyImpl.js => PasswordPolicyImpl.ts} (98%) rename packages/auth/lib/password-policy/{PasswordPolicyMixin.js => PasswordPolicyMixin.ts} (99%) rename packages/auth/lib/password-policy/{passwordPolicyApi.js => passwordPolicyApi.ts} (99%) rename packages/auth/lib/providers/{AppleAuthProvider.js => AppleAuthProvider.ts} (98%) rename packages/auth/lib/providers/{EmailAuthProvider.js => EmailAuthProvider.ts} (98%) rename packages/auth/lib/providers/{FacebookAuthProvider.js => FacebookAuthProvider.ts} (98%) rename packages/auth/lib/providers/{GithubAuthProvider.js => GithubAuthProvider.ts} (98%) rename packages/auth/lib/providers/{GoogleAuthProvider.js => GoogleAuthProvider.ts} (98%) rename packages/auth/lib/providers/{OAuthProvider.js => OAuthProvider.ts} (99%) rename packages/auth/lib/providers/{OIDCAuthProvider.js => OIDCAuthProvider.ts} (98%) rename packages/auth/lib/providers/{PhoneAuthProvider.js => PhoneAuthProvider.ts} (99%) rename packages/auth/lib/providers/{TwitterAuthProvider.js => TwitterAuthProvider.ts} (98%) rename packages/auth/lib/web/{RNFBAuthModule.android.js => RNFBAuthModule.android.ts} (73%) rename packages/auth/lib/web/{RNFBAuthModule.ios.js => RNFBAuthModule.ios.ts} (71%) rename packages/auth/lib/web/{RNFBAuthModule.js => RNFBAuthModule.ts} (99%) create mode 100644 packages/auth/tsconfig.json diff --git a/packages/auth/lib/ConfirmationResult.js b/packages/auth/lib/ConfirmationResult.ts similarity index 98% rename from packages/auth/lib/ConfirmationResult.js rename to packages/auth/lib/ConfirmationResult.ts index 25b72a2cd7..b0d44c19a9 100644 --- a/packages/auth/lib/ConfirmationResult.js +++ b/packages/auth/lib/ConfirmationResult.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * diff --git a/packages/auth/lib/MultiFactorResolver.js b/packages/auth/lib/MultiFactorResolver.ts similarity index 97% rename from packages/auth/lib/MultiFactorResolver.js rename to packages/auth/lib/MultiFactorResolver.ts index 364c5d4ec5..1ec99aa1ad 100644 --- a/packages/auth/lib/MultiFactorResolver.js +++ b/packages/auth/lib/MultiFactorResolver.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /** * Base class to facilitate multi-factor authentication. */ diff --git a/packages/auth/lib/PhoneAuthListener.js b/packages/auth/lib/PhoneAuthListener.ts similarity index 99% rename from packages/auth/lib/PhoneAuthListener.js rename to packages/auth/lib/PhoneAuthListener.ts index eed1aa7021..90a014ae64 100644 --- a/packages/auth/lib/PhoneAuthListener.js +++ b/packages/auth/lib/PhoneAuthListener.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * diff --git a/packages/auth/lib/PhoneMultiFactorGenerator.js b/packages/auth/lib/PhoneMultiFactorGenerator.ts similarity index 98% rename from packages/auth/lib/PhoneMultiFactorGenerator.js rename to packages/auth/lib/PhoneMultiFactorGenerator.ts index 1f3bbdd4e4..01527e8f0a 100644 --- a/packages/auth/lib/PhoneMultiFactorGenerator.js +++ b/packages/auth/lib/PhoneMultiFactorGenerator.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * diff --git a/packages/auth/lib/Settings.js b/packages/auth/lib/Settings.ts similarity index 99% rename from packages/auth/lib/Settings.js rename to packages/auth/lib/Settings.ts index 28f1d44d48..2e45f29266 100644 --- a/packages/auth/lib/Settings.js +++ b/packages/auth/lib/Settings.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * diff --git a/packages/auth/lib/TotpMultiFactorGenerator.js b/packages/auth/lib/TotpMultiFactorGenerator.ts similarity index 99% rename from packages/auth/lib/TotpMultiFactorGenerator.js rename to packages/auth/lib/TotpMultiFactorGenerator.ts index 6d8a3561be..3e8fef6666 100644 --- a/packages/auth/lib/TotpMultiFactorGenerator.js +++ b/packages/auth/lib/TotpMultiFactorGenerator.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * diff --git a/packages/auth/lib/TotpSecret.js b/packages/auth/lib/TotpSecret.ts similarity index 97% rename from packages/auth/lib/TotpSecret.js rename to packages/auth/lib/TotpSecret.ts index 027e8d92d0..6131c0b83f 100644 --- a/packages/auth/lib/TotpSecret.js +++ b/packages/auth/lib/TotpSecret.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -60,7 +61,7 @@ export class TotpSecret { * @param qrCodeUrl the URL to open in the app, from generateQrCodeUrl */ openInOtpApp(qrCodeUrl) { - if (isString(qrCodeUrl) && !qrCodeUrl !== '') { + if (isString(qrCodeUrl) && qrCodeUrl !== '') { return this.auth.native.openInOtpApp(this.secretKey, qrCodeUrl); } } diff --git a/packages/auth/lib/User.js b/packages/auth/lib/User.ts similarity index 99% rename from packages/auth/lib/User.js rename to packages/auth/lib/User.ts index 3ac5591aed..7bfdfc4ca5 100644 --- a/packages/auth/lib/User.js +++ b/packages/auth/lib/User.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * diff --git a/packages/auth/lib/getMultiFactorResolver.js b/packages/auth/lib/getMultiFactorResolver.ts similarity index 97% rename from packages/auth/lib/getMultiFactorResolver.js rename to packages/auth/lib/getMultiFactorResolver.ts index 70c3a53265..5b9412f715 100644 --- a/packages/auth/lib/getMultiFactorResolver.js +++ b/packages/auth/lib/getMultiFactorResolver.ts @@ -1,3 +1,4 @@ +// @ts-nocheck import { isOther } from '@react-native-firebase/app/dist/module/common'; import MultiFactorResolver from './MultiFactorResolver.js'; diff --git a/packages/auth/lib/index.d.ts b/packages/auth/lib/index.d.ts deleted file mode 100644 index 7e87730bb7..0000000000 --- a/packages/auth/lib/index.d.ts +++ /dev/null @@ -1,2339 +0,0 @@ -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library 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 { ReactNativeFirebase } from '@react-native-firebase/app'; - -/** - * Firebase Authentication package for React Native. - * - * #### Example: Access the firebase export from the `auth` package: - * - * ```js - * import { firebase } from '@react-native-firebase/auth'; - * - * // firebase.auth().X - * ``` - * - * #### Example: Using the default export from the `auth` package: - * - * ```js - * import auth from '@react-native-firebase/auth'; - * - * // auth().X - * ``` - * - * #### Example: Using the default export from the `app` package: - * - * ```js - * import firebase from '@react-native-firebase/app'; - * import '@react-native-firebase/auth'; - * - * // firebase.auth().X - * ``` - * TODO @salakar @ehesp missing auth providers (PhoneAuthProvider, Facebook etc) - * - * @firebase auth - */ -export namespace FirebaseAuthTypes { - import FirebaseModule = ReactNativeFirebase.FirebaseModule; - import NativeFirebaseError = ReactNativeFirebase.NativeFirebaseError; - - export interface NativeFirebaseAuthError extends NativeFirebaseError { - userInfo: { - /** - * When trying to sign in or link with an AuthCredential which was already associated with an account, - * you might receive an updated credential (depending of provider) which you can use to recover from the error. - */ - authCredential: AuthCredential | null; - /** - * When trying to sign in the user might be prompted for a second factor confirmation. Can - * can use this object to initialize the second factor flow and recover from the error. - */ - resolver: MultiFactorResolver | null; - }; - } - - /** - * Interface that represents the credentials returned by an auth provider. Implementations specify the details - * about each auth provider's credential requirements. - * - * TODO Missing; signInMethod, toJSON, fromJSON - * - * #### Example - * - * ```js - * const provider = firebase.auth.EmailAuthProvider; - * const authCredential = provider.credential('foo@bar.com', '123456'); - * - * await firebase.auth().signInWithCredential(authCredential); - * ``` - */ - export interface AuthCredential { - /** - * The authentication provider ID for the credential. For example, 'facebook.com', or 'google.com'. - */ - providerId: string; - token: string; - secret: string; - } - - /** - * Interface that represents an auth provider. Implemented by other providers. - */ - export interface AuthProvider { - /** - * The provider ID of the provider. - */ - PROVIDER_ID: string; - /** - * Creates a new `AuthCredential`. - * - * @returns {@link AuthCredential}. - * @param token A provider token. - * @param secret A provider secret. - */ - credential: (token: string | null, secret?: string) => AuthCredential; - } - - /** - * Interface that represents an OAuth provider. Implemented by other providers. - */ - export interface OAuthProvider extends AuthProvider { - /** - * The provider ID of the provider. - * @param providerId - */ - // eslint-disable-next-line @typescript-eslint/no-misused-new - new (providerId: string): OAuthProvider; - /** - * Creates a new `AuthCredential`. - * - * @returns {@link AuthCredential}. - * @param token A provider token. - * @param secret A provider secret. - */ - credential: (token: string | null, secret?: string) => AuthCredential; - /** - * Sets the OAuth custom parameters to pass in an OAuth request for sign-in - * operations. - * - * @remarks - * For a detailed list, check the reserved required OAuth 2.0 parameters such as `client_id`, - * `redirect_uri`, `scope`, `response_type`, and `state` are not allowed and will be ignored. - * - * @param customOAuthParameters - The custom OAuth parameters to pass in the OAuth request. - */ - setCustomParameters: (customOAuthParameters: Record) => AuthProvider; - /** - * Retrieve the current list of custom parameters. - * @returns The current map of OAuth custom parameters. - */ - getCustomParameters: () => Record; - /** - * Add an OAuth scope to the credential. - * - * @param scope - Provider OAuth scope to add. - */ - addScope: (scope: string) => AuthProvider; - /** - * Retrieve the current list of OAuth scopes. - */ - getScopes: () => string[]; - } - - /** - * Interface that represents an Open ID Connect auth provider. Implemented by other providers. - */ - export interface OIDCProvider { - /** - * The provider ID of the provider. - */ - PROVIDER_ID: string; - /** - * Creates a new `OIDCProvider`. - * - * @returns {@link AuthCredential}. - * @param oidcSuffix this is the "Provider ID" value from the firebase console fx `azure_test`. - * @param token A provider token. - */ - credential: (oidcSuffix: string, idToken: string) => AuthCredential; - } - - /** - * Email and password auth provider implementation. - */ - export interface EmailAuthProvider { - /** - * The provider ID. Always returns `password`. - */ - PROVIDER_ID: string; - /** - * This corresponds to the sign-in method identifier as returned in {@link fetchSignInMethodsForEmail}. - * - * #### Example - * - * ```js - * const signInMethods = await firebase.auth().fetchSignInMethodsForEmail('...'); - * if (signInMethods.indexOf(firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD) != -1) { - * // User can sign in with email/link - * } - * ``` - */ - EMAIL_LINK_SIGN_IN_METHOD: string; - /** - * This corresponds to the sign-in method identifier as returned in {@link fetchSignInMethodsForEmail}. - * - * #### Example - * - * ```js - * const signInMethods = await firebase.auth().fetchSignInMethodsForEmail('...'); - * if (signInMethods.indexOf(firebase.auth.EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD) != -1) { - * // User can sign in with email/password - * } - * ``` - */ - EMAIL_PASSWORD_SIGN_IN_METHOD: string; - /** - * Returns the auth provider credential. - * - * #### Example - * - * ```js - * const authCredential = firebase.auth.EmailAuthProvider.credential('joe.bloggs@example.com', '123456'); - * ``` - * - * @returns {@link AuthCredential} - * @param email Users email address. - * @param password User account password. - */ - credential: (email: string, password: string) => AuthCredential; - /** - * Initialize an `EmailAuthProvider` credential using an email and an email link after a sign in with email link operation. - * - * #### Example - * - * ```js - * const authCredential = firebase.auth.EmailAuthProvider.credentialWithLink('joe.bloggs@example.com', 'https://myexample.com/invite'); - * ``` - * - * @param email Users email address. - * @param emailLink Sign-in email link. - */ - credentialWithLink: (email: string, emailLink: string) => AuthCredential; - } - - /** - * - */ - export interface PhoneAuthState { - /** - * SMS message with verification code sent to phone number. - */ - CODE_SENT: 'sent'; - /** - * The timeout specified in {@link verifyPhoneNumber} has expired. - */ - AUTO_VERIFY_TIMEOUT: 'timeout'; - /** - * Phone number auto-verification succeeded. - */ - AUTO_VERIFIED: 'verified'; - /** - * Phone number verification failed with an error. - */ - ERROR: 'error'; - } - - export interface MultiFactorSession { - // this is has no documented contents, it is simply returned from some APIs and passed to others - } - - export interface PhoneMultiFactorGenerator { - /** - * Identifies second factors of type phone. - */ - FACTOR_ID: FactorId.PHONE; - - /** - * Build a MultiFactorAssertion to resolve the multi-factor sign in process. - */ - assertion(credential: AuthCredential): MultiFactorAssertion; - } - - /** - * Represents a TOTP secret that is used for enrolling a TOTP second factor. - * Contains the shared secret key and other parameters to generate time-based - * one-time passwords. Implements methods to retrieve the shared secret key, - * generate a QR code URL, and open the QR code URL in an OTP authenticator app. - * - * Differs from standard firebase JS implementation in three ways: - * 1- there is no visibility into ony properties other than the secretKey - * 2- there is an added `openInOtpApp` method supported by native SDKs - * 3- the return value of generateQrCodeUrl is a Promise because react-native bridge is async - * @public - */ - export declare class TotpSecret { - /** used internally to support non-default auth instances */ - private readonly auth; - /** - * Shared secret key/seed used for enrolling in TOTP MFA and generating OTPs. - */ - readonly secretKey: string; - - private constructor(); - - /** - * Returns a QR code URL as described in - * https://github.com/google/google-authenticator/wiki/Key-Uri-Format - * This can be displayed to the user as a QR code to be scanned into a TOTP app like Google Authenticator. - * If the optional parameters are unspecified, an accountName of userEmail and issuer of firebaseAppName are used. - * - * @param accountName the name of the account/app along with a user identifier. - * @param issuer issuer of the TOTP (likely the app name). - * @returns A Promise that resolves to a QR code URL string. - */ - async generateQrCodeUrl(accountName?: string, issuer?: string): Promise; - - /** - * Opens the specified QR Code URL in an OTP authenticator app on the device. - * The shared secret key and account name will be populated in the OTP authenticator app. - * The URL uses the otpauth:// scheme and will be opened on an app that handles this scheme, - * if it exists on the device, possibly opening the ecocystem-specific app store with a generic - * query for compatible apps if no app exists on the device. - * - * @param qrCodeUrl the URL to open in the app, from generateQrCodeUrl - */ - openInOtpApp(qrCodeUrl: string): string; - } - - export interface TotpMultiFactorGenerator { - FACTOR_ID: FactorId.TOTP; - - assertionForSignIn(uid: string, totpSecret: string): MultiFactorAssertion; - - assertionForEnrollment(secret: TotpSecret, code: string): MultiFactorAssertion; - - /** - * @param auth - The Auth instance. Only used for native platforms, should be ignored on web. - */ - generateSecret( - session: FirebaseAuthTypes.MultiFactorSession, - auth: FirebaseAuthTypes.Auth, - ): Promise; - } - - export declare interface MultiFactorError extends AuthError { - /** Details about the MultiFactorError. */ - readonly customData: AuthError['customData'] & { - /** - * The type of operation (sign-in, linking, or re-authentication) that raised the error. - */ - readonly operationType: (typeof OperationType)[keyof typeof OperationType]; - }; - } - - /** - * firebase.auth.X - */ - export interface Statics { - /** - * Return the #{@link MultiFactorUser} instance for the current user. - */ - multiFactor: multiFactor; - /** - * Try and obtain a #{@link MultiFactorResolver} instance based on an error. - * Returns null if no resolver object could be found. - * - */ - getMultiFactorResolver: getMultiFactorResolver; - /** - * Email and password auth provider implementation. - * - * #### Example - * - * ```js - * firebase.auth.EmailAuthProvider; - * ``` - */ - EmailAuthProvider: EmailAuthProvider; - /** - * Phone auth provider implementation. - * - * #### Example - * - * ```js - * firebase.auth.PhoneAuthProvider; - * ``` - */ - PhoneAuthProvider: AuthProvider; - /** - * Google auth provider implementation. - * - * #### Example - * - * ```js - * firebase.auth.GoogleAuthProvider; - * ``` - */ - GoogleAuthProvider: AuthProvider; - /** - * Apple auth provider implementation. Currently this is iOS only. - * - * For Apple Authentication please see our [`@invertase/react-native-apple-authentication`](https://github.com/invertase/react-native-apple-authentication) library which integrates well with Firebase and provides Firebase + Apple Auth examples. - * - * #### Example - * - * ```js - * firebase.auth.AppleAuthProvider; - * ``` - */ - AppleAuthProvider: AuthProvider; - /** - * Github auth provider implementation. - * - * #### Example - * - * ```js - * firebase.auth.GithubAuthProvider; - * ``` - */ - GithubAuthProvider: AuthProvider; - /** - * Twitter auth provider implementation. - * - * #### Example - * - * ```js - * firebase.auth.TwitterAuthProvider; - * ``` - */ - TwitterAuthProvider: AuthProvider; - /** - * Facebook auth provider implementation. - * - * #### Example - * - * ```js - * firebase.auth.FacebookAuthProvider; - * ``` - */ - FacebookAuthProvider: AuthProvider; - /** - * Custom OAuth auth provider implementation. - * - * #### Example - * - * ```js - * firebase.auth.OAuthProvider; - * ``` - */ - OAuthProvider: OAuthProvider; - /** - * Custom Open ID connect auth provider implementation. - * - * #### Example - * - * ```js - * firebase.auth.OIDCAuthProvider; - * ``` - */ - OIDCAuthProvider: OIDCProvider; - /** - * A PhoneAuthState interface. - * - * #### Example - * - * ```js - * firebase.auth.PhoneAuthState; - * ``` - */ - PhoneAuthState: PhoneAuthState; - - /** - * A PhoneMultiFactorGenerator interface. - */ - PhoneMultiFactorGenerator: PhoneMultiFactorGenerator; - SDK_VERSION: string; - } - - /** - * A structure containing additional user information from a federated identity provider via {@link UserCredential}. - * - * #### Example - * - * ```js - * const userCredential = await firebase.auth().signInAnonymously(); - * console.log('Additional user info: ', userCredential.additionalUserInfo); - * ``` - * - * @error auth/operation-not-allowed Thrown if anonymous accounts are not enabled. Enable anonymous accounts in the Firebase Console, under the Auth tab. - */ - export interface AdditionalUserInfo { - /** - * Returns whether the user is new or existing. - */ - isNewUser: boolean; - /** - * Returns an Object containing IDP-specific user data if the provider is one of Facebook, - * GitHub, Google, Twitter, Microsoft, or Yahoo. - */ - profile?: Record; - /** - * Returns the provider ID for specifying which provider the information in `profile` is for. - */ - providerId: string; - /** - * Returns the username if the provider is GitHub or Twitter. - */ - username?: string; - } - - /** - * A structure containing a User, an AuthCredential, the operationType, and any additional user - * information that was returned from the identity provider. operationType could be 'signIn' for - * a sign-in operation, 'link' for a linking operation and 'reauthenticate' for a re-authentication operation. - * - * TODO @salakar; missing credential, operationType - */ - export interface UserCredential { - /** - * Any additional user information assigned to the user. - */ - additionalUserInfo?: AdditionalUserInfo; - /** - * Returns the {@link User} interface of this credential. - */ - user: User; - } - - /** - * Holds the user metadata for the current {@link User}. - * - * #### Example - * - * ```js - * const user = firebase.auth().currentUser; - * console.log('User metadata: ', user.metadata); - * ``` - */ - export interface UserMetadata { - /** - * Returns the timestamp at which this account was created as dictated by the server clock - * as an ISO Date string. - */ - creationTime?: string; - /** - * Returns the last signin timestamp as dictated by the server clock as an ISO Date string. - * This is only accurate up to a granularity of 2 minutes for consecutive sign-in attempts. - */ - lastSignInTime?: string; - } - - /** - * Identifies the type of a second factor. - */ - export enum FactorId { - PHONE = 'phone', - TOTP = 'totp', - } - - /** - * Contains information about a second factor. - */ - export type MultiFactorInfo = PhoneMultiFactorInfo | TotpMultiFactorInfo; - - export interface PhoneMultiFactorInfo extends MultiFactorInfoCommon { - factorId: 'phone'; - /** - * The phone number used for this factor. - */ - phoneNumber: string; - } - - export interface TotpMultiFactorInfo extends MultiFactorInfoCommon { - factorId: 'totp'; - } - - export interface MultiFactorInfoCommon { - /** - * User friendly name for this factor. - */ - displayName?: string; - /** - * Time the second factor was enrolled, in UTC. - */ - enrollmentTime: string; - /** - * Unique id for this factor. - */ - uid: string; - } - - export interface MultiFactorAssertion { - token: string; - secret: string; - } - - export interface PhoneMultiFactorEnrollInfoOptions { - phoneNumber: string; - session: MultiFactorSession; - } - - export interface PhoneMultiFactorSignInInfoOptions { - multiFactorHint?: MultiFactorInfo; - - /** - * Unused in react-native-firebase ipmlementation - */ - multiFactorUid?: string; - - session: MultiFactorSession; - } - - /** - * Facilitates the recovery when a user needs to provide a second factor to sign-in. - */ - export interface MultiFactorResolver { - /** - * A list of enrolled factors that can be used to complete the multi-factor challenge. - */ - hints: MultiFactorInfo[]; - /** - * Serialized session this resolver belongs to. - */ - session: MultiFactorSession; - - /** - * For testing purposes only - */ - _auth?: FirebaseAuthTypes.Module; - - /** - * Resolve the multi factor flow. - */ - resolveSignIn(assertion: MultiFactorAssertion): Promise; - } - - /** - * Try and obtain a #{@link MultiFactorResolver} instance based on an error. - * Returns null if no resolver object could be found. - * - * #### Example - * - * ```js - * const auth = firebase.auth(); - * auth.signInWithEmailAndPassword(email, password).then((user) => { - * // signed in - * }).catch((error) => { - * if (error.code === 'auth/multi-factor-auth-required') { - * const resolver = getMultiFactorResolver(auth, error); - * } - * }); - * ``` - */ - export type getMultiFactorResolver = ( - auth: FirebaseAuthTypes.Module, - error: unknown, - ) => MultiFactorResolver | null; - - /** - * The entry point for most multi-factor operations. - */ - export interface MultiFactorUser { - /** - * Returns the user's enrolled factors. - */ - enrolledFactors: MultiFactorInfo[]; - - /** - * Return the session for this user. - */ - getSession(): Promise; - - /** - * Enroll an additional factor. Provide an optional display name that can be shown to the user. - * The method will ensure the user state is reloaded after successfully enrolling a factor. - */ - enroll(assertion: MultiFactorAssertion, displayName?: string): Promise; - - /** - * Unenroll a previously enrolled multi-factor authentication factor. - * @param option The multi-factor option to unenroll. - */ - unenroll(option: MultiFactorInfo | string): Promise; - } - - /** - * Return the #{@link MultiFactorUser} instance for the current user. - */ - export type multiFactor = (auth: FirebaseAuthTypes.Module) => Promise; - - /** - * Holds information about the user's enrolled factors. - * - * #### Example - * - * ```js - * const user = firebase.auth().currentUser; - * console.log('User multi factors: ', user.multiFactor); - * ``` - */ - export interface MultiFactor { - /** - * Returns the enrolled factors - */ - enrolledFactors: MultiFactorInfo[]; - } - - /** - * Represents a collection of standard profile information for a user. Can be used to expose - * profile information returned by an identity provider, such as Google Sign-In or Facebook Login. - * - * TODO @salakar: isEmailVerified - * - * #### Example - * - * ```js - * const user = firebase.auth().currentUser; - * - * user.providerData.forEach((userInfo) => { - * console.log('User info for provider: ', userInfo); - * }); - * ``` - */ - export interface UserInfo { - /** - * Returns the user's display name, if available. - */ - displayName?: string; - /** - * Returns the email address corresponding to the user's account in the specified provider, if available. - */ - email?: string; - /** - * The phone number normalized based on the E.164 standard (e.g. +16505550101) for the current user. This is null if the user has no phone credential linked to the account. - */ - phoneNumber?: string; - /** - * Returns a url to the user's profile picture, if available. - */ - photoURL?: string; - /** - * Returns the unique identifier of the provider type that this instance corresponds to. - */ - providerId: string; - /** - * Returns a string representing the multi-tenant tenant id. This is null if the user is not associated with a tenant. - */ - tenantId?: string; - /** - * Returns a user identifier as specified by the authentication provider. - */ - uid: string; - } - - /** - * Interface representing ID token result obtained from {@link User#getIdTokenResult}. - * It contains the ID token JWT string and other helper properties for getting different data - * associated with the token as well as all the decoded payload claims. - * - * TODO @salakar validate timestamp types - * - * #### Example - * - * ```js - * const idTokenResult = await firebase.auth().currentUser.getIdTokenResult(); - * console.log('User JWT: ', idTokenResult.token); - * ``` - */ - export interface IdTokenResult { - /** - * The Firebase Auth ID token JWT string. - */ - token: string; - /** - * The authentication time formatted as a UTC string. This is the time the user authenticated - * (signed in) and not the time the token was refreshed. - */ - authTime: string; - /** - * The ID token issued at time formatted as a UTC string. - */ - issuedAtTime: string; - /** - * The ID token expiration time formatted as a UTC string. - */ - expirationTime: string; - /** - * The sign-in provider through which the ID token was obtained (anonymous, custom, - * phone, password, etc). Note, this does not map to provider IDs. - */ - signInProvider: null | string; - /** - * The entire payload claims of the ID token including the standard reserved claims as well as - * the custom claims. - */ - claims: { - [key: string]: any; - }; - } - - /** - * Request used to update user profile information. - * - * #### Example - * - * ```js - * const update = { - * displayName: 'Alias', - * photoURL: 'https://my-cdn.com/assets/user/123.png', - * }; - * - * await firebase.auth().currentUser.updateProfile(update); - * ``` - */ - export interface UpdateProfile { - /** - * An optional display name for the user. Explicitly pass null to clear the displayName. - */ - displayName?: string | null; - /** - * An optional photo URL for the user. Explicitly pass null to clear the photoURL. - */ - photoURL?: string | null; - } - - /** - * A result from a {@link signInWithPhoneNumber} call. - * - * #### Example - * - * ```js - * // Force a new message to be sent - * const result = await firebase.auth().signInWithPhoneNumber('#4423456789'); - * const user = await result.confirm('12345'); - * ``` - */ - export interface ConfirmationResult { - /** - * The phone number authentication operation's verification ID. This can be used along with - * the verification code to initialize a phone auth credential. - */ - verificationId: string | null; - /** - * Finishes the sign in flow. Validates a code that was sent to the users device. - * - * @param verificationCode The code sent to the users device from Firebase. - */ - confirm(verificationCode: string): Promise; - } - - /** - * Android specific options which can be attached to the {@link ActionCodeSettings} object - * to be sent with requests such as {@link User#sendEmailVerification}. - * - * #### Example - * - * ```js - * await firebase.auth().currentUser.sendEmailVerification({ - * android: { - * installApp: true, - * packageName: 'com.awesome.app', - * }, - * }); - * ``` - */ - export interface ActionCodeSettingsAndroid { - /** - * Sets the Android package name. This will try to open the link in an android app if it is installed. - */ - packageName: string; - /** - * 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. - */ - installApp?: boolean; - /** - * 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. The Android app needs to be registered in the Console. - */ - minimumVersion?: string; - } - - /** - * Additional data returned from a {@link checkActionCode} call. - * For the PASSWORD_RESET, VERIFY_EMAIL, and RECOVER_EMAIL actions, this object contains an email field with the address the email was sent to. - * For the RECOVER_EMAIL action, which allows a user to undo an email address change, this object also contains a fromEmail field with the user account's new email address. After the action completes, the user's email address will revert to the value in the email field from the value in fromEmail field. - * - * #### Example - * - * ```js - * const actionCodeInfo = await firebase.auth().checkActionCode('ABCD'); - *Data - * console.log('Action code email: ', actionCodeInfo.data.email); - * console.log('Action code from email: ', actionCodeInfo.data.fromEmail); - * ``` - */ - export interface ActionCodeInfoData { - /** - * This signifies the email before the call was made. - */ - email?: string; - /** - * This signifies the current email associated with the account, which may have changed as a result of the {@link checkActionCode} call performed. - */ - fromEmail?: string; - } - - /** - * The interface returned from a {@link checkActionCode} call. - * - * #### Example - * - * ```js - * const actionCodeInfo = await firebase.auth().checkActionCode('ABCD'); - * console.log('Action code operation: ', actionCodeInfo.operation); - * ``` - */ - export interface ActionCodeInfo { - /** - * The data associated with the action code. - */ - data: ActionCodeInfoData; - /** - * The operation from where the action originated. - */ - operation: 'PASSWORD_RESET' | 'VERIFY_EMAIL' | 'RECOVER_EMAIL' | 'EMAIL_SIGNIN' | 'ERROR'; - } - - /** - * iOS specific options which can be attached to the {@link ActionCodeSettings} object - * to be sent with requests such as {@link User#sendEmailVerification}. - * - * #### Example - * - * ```js - * await firebase.auth().currentUser.sendEmailVerification({ - * iOS: { - * bundleId: '123456', - * }, - * }); - * ``` - */ - export interface ActionCodeSettingsIos { - /** - * Sets the iOS bundle ID. This will try to open the link in an iOS app if it is installed. The iOS app needs to be registered in the Console. - */ - bundleId?: string; - } - - /** - * Options to be sent with requests such as {@link User#sendEmailVerification}. - * - * #### Example - * - * ```js - * await firebase.auth().currentUser.sendEmailVerification({ - * handleCodeInApp: true, - * url: 'app/email-verification', - * }); - * ``` - */ - export interface ActionCodeSettings { - /** - * Android specific settings. - */ - android?: ActionCodeSettingsAndroid; - - /** - * Whether the email action link will be opened in a mobile app or a web link first. The default is false. When set to true, the action code link will be be sent as a Universal Link or Android App Link and will be opened by the app if installed. In the false case, the code will be sent to the web widget first and then on continue will redirect to the app if installed. - */ - handleCodeInApp?: boolean; - - /** - * iOS specific settings. - */ - iOS?: ActionCodeSettingsIos; - - /** - * Sets the dynamic link domain (or subdomain) 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 one. If none is provided, the first domain is used by default. - * Deprecated - use {@link ActionCodeSettings.linkDomain} instead. - */ - dynamicLinkDomain?: string; - - /** - * This URL represents the state/Continue URL in the form of a universal link. This URL can should be constructed as a universal link that would either directly open the app where the action code would be handled or continue to the app after the action code is handled by Firebase. - */ - url: string; - /** - * Firebase Dynamic Links is deprecated and will be shut down as early as August * 2025. - * Instead, use ActionCodeSettings.linkDomain to set a a custom domain. Learn more at: https://firebase.google.com/support/dynamic-links-faq - */ - linkDomain?: string; - } - - /** - * An auth listener callback function for {@link onAuthStateChanged}. - * - * #### Example - * - * ```js - * function listener(user) { - * if (user) { - * // Signed in - * } else { - * // Signed out - * } - * } - * - * firebase.auth().onAuthStateChanged(listener); - * ``` - */ - export type AuthListenerCallback = (user: User | null) => void; - - /** - * A snapshot interface of the current phone auth state. - * - * #### Example - * - * ```js - * firebase.auth().verifyPhoneNumber('+4423456789') - * .on('state_changed', (phoneAuthSnapshot) => { - * console.log('Snapshot state: ', phoneAuthSnapshot.state); - * }); - * ``` - */ - export interface PhoneAuthSnapshot { - /** - * The current phone auth verification state. - * - * - `sent`: On iOS, this is the final event received. Once sent, show a visible input box asking the user to enter the verification code. - * - `timeout`: Auto verification has timed out. Show a visible input box asking the user to enter the verification code. - * - `verified`: The verification code has automatically been verified by the Android device. The snapshot contains the verification ID & code to create a credential. - * - `error`: An error occurred. Handle or allow the promise to reject. - */ - state: 'sent' | 'timeout' | 'verified' | 'error'; - /** - * The verification ID to build a `PhoneAuthProvider` credential. - */ - verificationId: string; - /** - * The verification code. Will only be available if auto verification has taken place. - */ - code: string | null; - /** - * A native JavaScript error if an error occurs. - */ - error: NativeFirebaseError | null; - } - - /** - * A custom error in the event verifying a phone number failed. - * - * #### Example - * - * ```js - * firebase.auth().verifyPhoneNumber('+4423456789') - * .on('state_changed', (phoneAuthSnapshot) => { - * console.log('Snapshot state: ', phoneAuthSnapshot.state); - * }, (phoneAuthError) => { - * console.error('Error: ', phoneAuthError.message); - * }); - * ``` - */ - export interface PhoneAuthError { - /** - * The code the verification failed with. - */ - code: string | null; - /** - * The verification ID which failed. - */ - verificationId: string; - /** - * JavaScript error message. - */ - message: string | null; - /** - * JavaScript error stack trace. - */ - stack: string | null; - } - - /** - * The listener function returned from a {@link verifyPhoneNumber} call. - */ - export interface PhoneAuthListener { - /** - * The phone auth state listener. See {@link PhoneAuthState} for different event state types. - * - * #### Example - * - * ```js - * firebase.auth().verifyPhoneNumber('+4423456789') - * .on('state_changed', (phoneAuthSnapshot) => { - * console.log('State: ', phoneAuthSnapshot.state); - * }, (error) => { - * console.error(error); - * }, (phoneAuthSnapshot) => { - * console.log('Success'); - * }); - * ``` - * - * @param event The event to subscribe to. Currently only `state_changed` is available. - * @param observer The required observer function. Returns a new phone auth snapshot on each event. - * @param errorCb An optional error handler function. This is not required if the `error` snapshot state is being handled in the `observer`. - * @param successCb An optional success handler function. This is not required if the `sent` or `verified` snapshot state is being handled in the `observer`. - */ - on( - event: string, - observer: (snapshot: PhoneAuthSnapshot) => void, - errorCb?: (error: PhoneAuthError) => void, - successCb?: (snapshot: PhoneAuthSnapshot) => void, - ): PhoneAuthListener; - - /** - * A promise handler called once the `on` listener flow has succeeded or rejected. - * - * #### Example - * - * ```js - * firebase.auth().verifyPhoneNumber('+4423456789') - * .on('state_changed', (phoneAuthSnapshot) => { - * if (phoneAuthSnapshot.state === firebase.auth.PhoneAuthState.CODE_SENT) { - * return Promise.resolve(); - * } else { - * return Promise.reject( - * new Error('Code not sent!') - * ); - * } - * }) - * .then((phoneAuthSnapshot) => { - * console.log(phoneAuthSnapshot.state); - * }, (error) => { - * console.error(error.message); - * }); - * ``` - * - * @param onFulfilled Resolved promise handler. - * @param onRejected Rejected promise handler. - */ - then( - onFulfilled?: ((a: PhoneAuthSnapshot) => any) | null, - onRejected?: ((a: NativeFirebaseError) => any) | null, - ): Promise; - - /** - * A promise handler called once the `on` listener flow has rejected. - * - * #### Example - * - * ```js - * firebase.auth().verifyPhoneNumber('+4423456789') - * .on('state_changed', (phoneAuthSnapshot) => { - * return Promise.reject( - * new Error('Code not sent!') - * ); - * }) - * .catch((error) => { - * console.error(error.message); - * }); - * ``` - * - * > Used when no `onRejected` handler is passed to {@link PhoneAuthListener#then}. - * - * @param onRejected Rejected promise handler. - */ - catch(onRejected: (a: NativeFirebaseError) => any): Promise; - } - - /** - * Interface for module auth settings. - * - * #### Example - * - * ```js - * const settings = firebase.auth().settings; - * console.log(settings.appVerificationDisabledForTesting); - * ``` - */ - export interface AuthSettings { - /** - * Forces application verification to use the web reCAPTCHA flow for Phone Authentication. - * - * Once this has been called, every call to PhoneAuthProvider#verifyPhoneNumber() will skip the Play Integrity API verification flow and use the reCAPTCHA flow instead. - * - * > Calling this method a second time will overwrite the previously passed parameter. - * - * @android - * @param appName - * @param forceRecaptchaFlow - * @param promise - */ - forceRecaptchaFlowForTesting: boolean; - - /** - * Flag to disable app verification for the purpose of testing phone authentication. For this property to take effect, it needs to be set before rendering a reCAPTCHA app verifier. When this is disabled, a mock reCAPTCHA is rendered instead. This is useful for manual testing during development or for automated integration tests. - * - * > In order to use this feature, you will need to [whitelist your phone number](https://firebase.google.com/docs/auth/web/phone-auth#test-with-whitelisted-phone-numbers) via the Firebase Console. - * - * @param disabled Boolean value representing whether app verification should be disabled for testing. - */ - appVerificationDisabledForTesting: boolean; - - /** - * Calling this method a second time will overwrite the previously passed parameters. - * Only one number can be configured at a given time. - * - * > The phone number and SMS code here must have been configured in the Firebase Console (Authentication > Sign In Method > Phone). - * - * #### Example - * - * ```js - * await firebase.auth().settings.setAutoRetrievedSmsCodeForPhoneNumber('+4423456789', 'ABCDE'); - * ``` - * - * @android - * @param phoneNumber The users phone number. - * @param smsCode The pre-set SMS code. - */ - setAutoRetrievedSmsCodeForPhoneNumber(phoneNumber: string, smsCode: string): Promise; - } - - /** - * Represents a user's profile information in your Firebase project's user database. It also - * contains helper methods to change or retrieve profile information, as well as to manage that user's authentication state. - * - * #### Example 1 - * - * Subscribing to the users authentication state. - * - * ```js - * firebase.auth().onAuthStateChanged((user) => { - * if (user) { - * console.log('User email: ', user.email); - * } - * }); - * ``` - * - * #### Example 2 - * - * ```js - * const user = firebase.auth().currentUser; - * - * if (user) { - * console.log('User email: ', user.email); - * } - * ``` - */ - export interface User { - /** - * The user's display name (if available). - */ - displayName: string | null; - /** - * - The user's email address (if available). - */ - email: string | null; - /** - * - True if the user's email address has been verified. - */ - emailVerified: boolean; - /** - * Returns true if the user is anonymous; that is, the user account was created with - * {@link signInAnonymously} and has not been linked to another account - * with {@link linkWithCredential}. - */ - isAnonymous: boolean; - - /** - * Returns the {@link UserMetadata} associated with this user. - */ - metadata: UserMetadata; - - /** - * Returns the {@link MultiFactor} associated with this user. - */ - multiFactor: MultiFactor | null; - - /** - * Returns the phone number of the user, as stored in the Firebase project's user database, - * or null if none exists. This can be updated at any time by calling {@link User#updatePhoneNumber}. - */ - phoneNumber: string | null; - - /** - * The URL of the user's profile picture (if available). - */ - photoURL: string | null; - - /** - * Additional provider-specific information about the user. - */ - providerData: UserInfo[]; - - /** - * The authentication provider ID for the current user. - * For example, 'facebook.com', or 'google.com'. - */ - providerId: string; - - /** - * - The user's unique ID. - */ - uid: string; - - /** - * Delete the current user. - * - * #### Example - * - * ```js - * await firebase.auth().currentUser.delete(); - * ``` - * - * @error auth/requires-recent-login Thrown if the user's last sign-in time does not meet the security threshold. Use `auth.User#reauthenticateWithCredential` to resolve. This does not apply if the user is anonymous. - */ - delete(): Promise; - - /** - * Returns the users authentication token. - * - * #### Example - * - * ```js - * // Force a token refresh - * const idToken = await firebase.auth().currentUser.getIdToken(true); - * ``` - * - * @param forceRefresh A boolean value which forces Firebase to refresh the token. - */ - getIdToken(forceRefresh?: boolean): Promise; - - /** - * Returns a firebase.auth.IdTokenResult object which contains the ID token JWT string and - * other helper properties for getting different data associated with the token as well as - * all the decoded payload claims. - * - * #### Example - * - * ```js - * // Force a token refresh - * const idTokenResult = await firebase.auth().currentUser.getIdTokenResult(true); - * ``` - * - * @param forceRefresh boolean Force refresh regardless of token expiration. - */ - getIdTokenResult(forceRefresh?: boolean): Promise; - - /** - * Link the user with a 3rd party credential provider. - * - * #### Example - * - * ```js - * const facebookCredential = firebase.auth.FacebookAuthProvider.credential('access token from Facebook'); - * const userCredential = await firebase.auth().currentUser.linkWithCredential(facebookCredential); - * ``` - * - * @error auth/provider-already-linked Thrown if the provider has already been linked to the user. This error is thrown even if this is not the same provider's account that is currently linked to the user. - * @error auth/invalid-credential Thrown if the provider's credential is not valid. This can happen if it has already expired when calling link, or if it used invalid token(s). See the Firebase documentation for your provider, and make sure you pass in the correct parameters to the credential method. - * @error auth/credential-already-in-use Thrown if the account corresponding to the credential already exists among your users, or is already linked to a Firebase User. - * @error auth/email-already-in-use Thrown if the email corresponding to the credential already exists among your users. - * @error auth/operation-not-allowed Thrown if you have not enabled the provider in the Firebase Console. Go to the Firebase Console for your project, in the Auth section and the Sign in Method tab and configure the provider. - * @error auth/invalid-email Thrown if the email used in a auth.EmailAuthProvider.credential is invalid. - * @error auth/wrong-password Thrown if the password used in a auth.EmailAuthProvider.credential is not correct or when the user associated with the email does not have a password. - * @error auth/invalid-verification-code Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. - * @error auth/invalid-verification-id Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. - * @throws on iOS {@link NativeFirebaseAuthError}, on Android {@link NativeFirebaseError} - * @param credential A created {@link AuthCredential}. - */ - linkWithCredential(credential: AuthCredential): Promise; - - /** - * Link the user with a federated 3rd party credential provider (Microsoft, Yahoo). - * The APIs here are the web-compatible linkWithPopup and linkWithRedirect but both - * share the same underlying native SDK behavior and may be used interchangably. - * - * #### Example - * - * ```js - * const provider = new firebase.auth.OAuthProvider('microsoft.com'); - * const userCredential = await firebase.auth().currentUser.linkWithPopup(provider); - * ``` - * - * @error auth/provider-already-linked Thrown if the provider has already been linked to the user. This error is thrown even if this is not the same provider's account that is currently linked to the user. - * @error auth/invalid-credential Thrown if the provider's credential is not valid. This can happen if it has already expired when calling link, or if it used invalid token(s). See the Firebase documentation for your provider, and make sure you pass in the correct parameters to the credential method. - * @error auth/credential-already-in-use Thrown if the account corresponding to the credential already exists among your users, or is already linked to a Firebase User. - * @error auth/email-already-in-use Thrown if the email corresponding to the credential already exists among your users. - * @error auth/operation-not-allowed Thrown if you have not enabled the provider in the Firebase Console. Go to the Firebase Console for your project, in the Auth section and the Sign in Method tab and configure the provider. - * @error auth/invalid-email Thrown if the email used in a auth.EmailAuthProvider.credential is invalid. - * @error auth/wrong-password Thrown if the password used in a auth.EmailAuthProvider.credential is not correct or when the user associated with the email does not have a password. - * @error auth/invalid-verification-code Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. - * @error auth/invalid-verification-id Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. - * @throws on iOS {@link NativeFirebaseAuthError}, on Android {@link NativeFirebaseError} - * @param provider A created {@link AuthProvider}. - */ - linkWithPopup(provider: AuthProvider): Promise; - - /** - * Link the user with a federated 3rd party credential provider (Microsoft, Yahoo). - * The APIs here are the web-compatible linkWithPopup and linkWithRedirect but both - * share the same underlying native SDK behavior and may be used interchangably. - * - * #### Example - * - * ```js - * const provider = new firebase.auth.OAuthProvider('microsoft.com'); - * const userCredential = await firebase.auth().currentUser.linkWithRedirect(provider); - * ``` - * - * @error auth/provider-already-linked Thrown if the provider has already been linked to the user. This error is thrown even if this is not the same provider's account that is currently linked to the user. - * @error auth/invalid-credential Thrown if the provider's credential is not valid. This can happen if it has already expired when calling link, or if it used invalid token(s). See the Firebase documentation for your provider, and make sure you pass in the correct parameters to the credential method. - * @error auth/credential-already-in-use Thrown if the account corresponding to the credential already exists among your users, or is already linked to a Firebase User. - * @error auth/email-already-in-use Thrown if the email corresponding to the credential already exists among your users. - * @error auth/operation-not-allowed Thrown if you have not enabled the provider in the Firebase Console. Go to the Firebase Console for your project, in the Auth section and the Sign in Method tab and configure the provider. - * @error auth/invalid-email Thrown if the email used in a auth.EmailAuthProvider.credential is invalid. - * @error auth/wrong-password Thrown if the password used in a auth.EmailAuthProvider.credential is not correct or when the user associated with the email does not have a password. - * @error auth/invalid-verification-code Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. - * @error auth/invalid-verification-id Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. - * @throws on iOS {@link NativeFirebaseAuthError}, on Android {@link NativeFirebaseError} - * @param provider A created {@link AuthProvider}. - */ - linkWithRedirect(provider: AuthProvider): Promise; - - /** - * Re-authenticate a user with a third-party authentication provider. - * - * #### Example - * - * ```js - * const facebookCredential = firebase.auth.FacebookAuthProvider.credential('access token from Facebook'); - * const userCredential = await firebase.auth().currentUser.reauthenticateWithCredential(facebookCredential); - * ``` - * - * @error auth/user-mismatch Thrown if the credential given does not correspond to the user. - * @error auth/user-not-found Thrown if the credential given does not correspond to any existing user. - * @error auth/invalid-credential Thrown if the provider's credential is not valid. This can happen if it has already expired when calling link, or if it used invalid token(s). See the Firebase documentation for your provider, and make sure you pass in the correct parameters to the credential method. - * @error auth/invalid-email Thrown if the email used in a auth.EmailAuthProvider.credential is invalid. - * @error auth/wrong-password Thrown if the password used in a auth.EmailAuthProvider.credential is not correct or when the user associated with the email does not have a password. - * @error auth/invalid-verification-code Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. - * @error auth/invalid-verification-id Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. - * @param credential A created {@link AuthCredential}. - */ - reauthenticateWithCredential(credential: AuthCredential): Promise; - - /** - * Re-authenticate a user with a federated authentication provider (Microsoft, Yahoo). For native platforms, this will open a browser window. - * #### Example - * - * ```js - * const provider = new firebase.auth.OAuthProvider('microsoft.com'); - * const userCredential = await firebase.auth().currentUser.reauthenticateWithProvider(provider); - * ``` - * - * @error auth/user-mismatch Thrown if the credential given does not correspond to the user. - * @error auth/user-not-found Thrown if the credential given does not correspond to any existing user. - * @error auth/invalid-credential Thrown if the provider's credential is not valid. This can happen if it has already expired when calling link, or if it used invalid token(s). See the Firebase documentation for your provider, and make sure you pass in the correct parameters to the credential method. - * @error auth/invalid-email Thrown if the email used in a auth.EmailAuthProvider.credential is invalid. - * @error auth/wrong-password Thrown if the password used in a auth.EmailAuthProvider.credential is not correct or when the user associated with the email does not have a password. - * @error auth/invalid-verification-code Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. - * @error auth/invalid-verification-id Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. - * @param provider A created {@link AuthProvider}. - * @returns A promise that resolves with no value. - */ - reauthenticateWithRedirect(provider: AuthProvider): Promise; - /** - * Re-authenticate a user with a federated authentication provider (Microsoft, Yahoo). For native platforms, this will open a browser window. - * pop-up equivalent on native platforms. - * - * @param provider - The auth provider. - * @returns A promise that resolves with the user credentials. - */ - reauthenticateWithPopup(provider: AuthProvider): Promise; - /** - * Refreshes the current user. - * - * #### Example - * - * ```js - * await firebase.auth().currentUser.reload(); - * ``` - */ - reload(): Promise; - - /** - * Sends a verification email to a user. - * - * #### Example - * - * ```js - * await firebase.auth().currentUser.sendEmailVerification({ - * handleCodeInApp: true, - * }); - * ``` - * - * > This will Promise reject if the user is anonymous. - * - * @error auth/missing-android-pkg-name An Android package name must be provided if the Android app is required to be installed. - * @error auth/missing-continue-uri A continue URL must be provided in the request. - * @error auth/missing-ios-bundle-id An iOS bundle ID must be provided if an App Store ID is provided. - * @error auth/invalid-continue-uri The continue URL provided in the request is invalid. - * @error auth/unauthorized-continue-uri The domain of the continue URL is not whitelisted. Whitelist the domain in the Firebase console. - * @param actionCodeSettings Any optional additional settings to be set before sending the verification email. - */ - sendEmailVerification(actionCodeSettings?: ActionCodeSettings): Promise; - /** - * Sends a link to the user's email address, when clicked, the user's Authentication email address will be updated to whatever - * was passed as the first argument. - * - * #### Example - * - * ```js - * await firebase.auth().currentUser.verifyBeforeUpdateEmail( - * 'foo@emailaddress.com', - * { - * handleCodeInApp: true, - * }); - * ``` - * - * > This will Promise reject if the user is anonymous. - * - * @error auth/missing-android-pkg-name An Android package name must be provided if the Android app is required to be installed. - * @error auth/missing-continue-uri A continue URL must be provided in the request. - * @error auth/missing-ios-bundle-id An iOS bundle ID must be provided if an App Store ID is provided. - * @error auth/invalid-continue-uri The continue URL provided in the request is invalid. - * @error auth/unauthorized-continue-uri The domain of the continue URL is not whitelisted. Whitelist the domain in the Firebase console. - * @param actionCodeSettings Any optional additional settings to be set before sending the verification email. - */ - verifyBeforeUpdateEmail(email: string, actionCodeSettings?: ActionCodeSettings): Promise; - - /** - * Returns a JSON-serializable representation of this object. - * - * #### Example - * - * ```js - * const user = firebase.auth().currentUser.toJSON(); - * ``` - */ - toJSON(): object; - - /** - * Unlinks a provider from a user account. - * - * #### Example - * - * ```js - * const user = await firebase.auth().currentUser.unlink('facebook.com'); - * ``` - * - * @error auth/no-such-provider Thrown if the user does not have this provider linked or when the provider ID given does not exist. - * @param providerId - */ - unlink(providerId: string): Promise; - - /** - * Updates the user's email address. - * - * See Firebase docs for more information on security & email validation. - * - * #### Example - * - * ```js - * await firebase.auth().currentUser.updateEmail('joe.bloggs@new-email.com'); - * ``` - * - * > This will Promise reject if the user is anonymous. - * - * @error auth/invalid-email Thrown if the email used is invalid. - * @error auth/email-already-in-use Thrown if the email is already used by another user. - * @error auth/requires-recent-login Thrown if the user's last sign-in time does not meet the security threshold. - * @param email The users new email address. - */ - updateEmail(email: string): Promise; - - /** - * Updates the users password. - * - * Important: this is a security sensitive operation that requires the user to have recently signed in. - * If this requirement isn't met, ask the user to authenticate again and then call firebase.User#reauthenticate. - * - * #### Example - * - * ```js - * await firebase.auth().currentUser.updatePassword('654321'); - * ``` - * - * > This will Promise reject is the user is anonymous. - * - * @error auth/weak-password Thrown if the password is not strong enough. - * @error auth/requires-recent-login Thrown if the user's last sign-in time does not meet the security threshold. - * @param password The users new password. - */ - updatePassword(password: string): Promise; - - /** - * Updates the user's phone number. - * - * See Firebase docs for more information on security & email validation. - * - * #### Example - * - * ```js - * const snapshot = await firebase.auth().verifyPhoneNumber('+4423456789') - * .on(...); // See PhoneAuthListener - wait for successful verification - * - * const credential = firebase.auth.PhoneAuthProvider.credential(snapshot.verificationId, snapshot.code); - * - * // Update user with new verified phone number - * await firebase.auth().currentUser.updatePhoneNumber(credential); - * ``` - * - * > This will Promise reject is the user is anonymous. - * - * @error auth/invalid-verification-code Thrown if the verification code of the credential is not valid. - * @error auth/invalid-verification-id Thrown if the verification ID of the credential is not valid. - * @param credential A created `PhoneAuthCredential`. - */ - updatePhoneNumber(credential: AuthCredential): Promise; - - /** - * Updates a user's profile data. - * - * #### Example - * - * ```js - * await firebase.auth().currentUser.updateProfile({ - * displayName: 'Alias', - * }); - * ``` - */ - updateProfile(updates: UpdateProfile): Promise; - } - - /** - * The Firebase Authentication service is available for the default app or a given app. - * - * #### Example 1 - * - * Get the auth instance for the **default app**: - * - * ```js - * const authForDefaultApp = firebase.auth(); - * ``` - * - * #### Example 2 - * - * Get the auth instance for a **secondary app**: - * - * ```js - * const otherApp = firebase.app('otherApp'); - * const authForOtherApp = firebase.auth(otherApp); - * ``` - * - * TODO @salakar missing updateCurrentUser - */ - export class Module extends FirebaseModule { - /** - * The current `FirebaseApp` instance for this Firebase service. - */ - app: ReactNativeFirebase.FirebaseApp; - - /** - * Returns the current tenant Id or null if it has never been set - * - * #### Example - * - * ```js - * const tenantId = firebase.auth().tenantId; - * ``` - */ - tenantId: string | null; - /** - * Returns the current language code. - * - * #### Example - * - * ```js - * const language = firebase.auth().languageCode; - * ``` - */ - languageCode: string; - /** - * Returns the current `AuthSettings`. - */ - settings: AuthSettings; - - /** - * Returns the currently signed-in user (or null if no user signed in). See the User interface documentation for detailed usage. - * - * #### Example - * - * ```js - * const user = firebase.auth().currentUser; - * ``` - * - * > It is recommended to use {@link onAuthStateChanged} to track whether the user is currently signed in. - */ - currentUser: User | null; - /** - * Sets the tenant id. - * - * #### Example - * - * ```js - * await firebase.auth().setTenantId('tenant-123'); - * ``` - * - * @error auth/invalid-tenant-id if the tenant id is invalid for some reason - * @param tenantId the tenantID current app bind to. - */ - setTenantId(tenantId: string): Promise; - /** - * Sets the language code. - * - * #### Example - * - * ```js - * // Set language to French - * await firebase.auth().setLanguageCode('fr'); - * ``` - * - * @param code An ISO language code. - * 'null' value will set the language code to the app's current language. - */ - setLanguageCode(languageCode: string | null): Promise; - /** - * Listen for changes in the users auth state (logging in and out). - * This method returns a unsubscribe function to stop listening to events. - * Always ensure you unsubscribe from the listener when no longer needed to prevent updates to components no longer in use. - * - * #### Example - * - * ```js - * const unsubscribe = firebase.auth().onAuthStateChanged((user) => { - * if (user) { - * // Signed in - * } else { - * // Signed out - * } - * }); - * - * // Unsubscribe from further state changes - * unsubscribe(); - * ``` - * - * @param listener A listener function which triggers when auth state changed (for example signing out). - */ - onAuthStateChanged(listener: CallbackOrObserver): () => void; - - /** - * Listen for changes in ID token. - * ID token can be verified (if desired) using the [admin SDK or a 3rd party JWT library](https://firebase.google.com/docs/auth/admin/verify-id-tokens) - * This method returns a unsubscribe function to stop listening to events. - * Always ensure you unsubscribe from the listener when no longer needed to prevent updates to components no longer in use. - * - * #### Example - * - * ```js - * const unsubscribe = firebase.auth().onIdTokenChanged((user) => { - * if (user) { - * // User is signed in or token was refreshed. - * } - * }); - * - * // Unsubscribe from further state changes - * unsubscribe(); - * ``` - * - * @param listener A listener function which triggers when the users ID token changes. - */ - onIdTokenChanged(listener: CallbackOrObserver): () => void; - - /** - * Adds a listener to observe changes to the User object. This is a superset of everything from - * {@link onAuthStateChanged}, {@link onIdTokenChanged} and user changes. The goal of this - * method is to provide easier listening to all user changes, such as when credentials are - * linked and unlinked, without manually having to call {@link User#reload}. - * - * #### Example - * - * ```js - * const unsubscribe = firebase.auth().onUserChanged((user) => { - * if (user) { - * // User is signed in or token was refreshed. - * } - * }); - * - * // Unsubscribe from further state changes - * unsubscribe(); - * ``` - * - * > This is an experimental feature and is only part of React Native Firebase. - * - * @react-native-firebase - * @param listener A listener function which triggers when the users data changes. - */ - onUserChanged(listener: CallbackOrObserver): () => void; - - /** - * Signs the user out. - * - * Triggers the {@link onAuthStateChanged} listener. - * - * #### Example - * - * ```js - * await firebase.auth().signOut(); - * ``` - * - */ - signOut(): Promise; - - /** - * Sign in a user anonymously. If the user has already signed in, that user will be returned. - * - * #### Example - * - * ```js - * const userCredential = await firebase.auth().signInAnonymously(); - * ``` - * - * @error auth/operation-not-allowed Thrown if anonymous accounts are not enabled. Enable anonymous accounts in the Firebase Console, under the Auth tab. - */ - signInAnonymously(): Promise; - - /** - * Signs in the user using their phone number. - * - * #### Example - * - * ```js - * // Force a new message to be sent - * const result = await firebase.auth().signInWithPhoneNumber('#4423456789', true); - * ``` - * - * @error auth/invalid-phone-number Thrown if the phone number has an invalid format. - * @error auth/missing-phone-number Thrown if the phone number is missing. - * @error auth/quota-exceeded Thrown if the SMS quota for the Firebase project has been exceeded. - * @error auth/user-disabled Thrown if the user corresponding to the given phone number has been disabled. - * @error auth/operation-not-allowed Thrown if you have not enabled the provider in the Firebase Console. Go to the Firebase Console for your project, in the Auth section and the Sign in Method tab and configure the provider. - * @param phoneNumber The devices phone number. - * @param forceResend Forces a new message to be sent if it was already recently sent. - */ - signInWithPhoneNumber(phoneNumber: string, forceResend?: boolean): Promise; - - /** - * Returns a PhoneAuthListener to listen to phone verification events, - * on the final completion event a PhoneAuthCredential can be generated for - * authentication purposes. - * - * #### Example - * - * ```js - * firebase.auth().verifyPhoneNumber('+4423456789', ) - * .on('state_changed', (phoneAuthSnapshot) => { - * console.log('Snapshot state: ', phoneAuthSnapshot.state); - * }); - * ``` - * - * @param phoneNumber The phone number identifier supplied by the user. Its format is normalized on the server, so it can be in any format here. (e.g. +16505550101). - * @param autoVerifyTimeoutOrForceResend If a number, sets in seconds how to to wait until auto verification times out. If boolean, sets the `forceResend` parameter. - * @param forceResend If true, resend the verification message even if it was recently sent. - */ - verifyPhoneNumber( - phoneNumber: string, - autoVerifyTimeoutOrForceResend?: number | boolean, - forceResend?: boolean, - ): PhoneAuthListener; - - /** - * Obtain a verification id to complete the multi-factor sign-in flow. - */ - verifyPhoneNumberWithMultiFactorInfo( - hint: MultiFactorInfo, - session: MultiFactorSession, - ): Promise; - - /** - * Send an SMS to the user for verification of second factor - * @param phoneInfoOptions the phone number and session to use during enrollment - */ - verifyPhoneNumberForMultiFactor( - phoneInfoOptions: PhoneMultiFactorEnrollInfoOptions, - ): Promise; - - /** - * Creates a new user with an email and password. - * - * This method also signs the user in once the account has been created. - * - * #### Example - * - * ```js - * const userCredential = await firebase.auth().createUserWithEmailAndPassword('joe.bloggs@example.com', '123456'); - * ``` - * - * @error auth/email-already-in-use Thrown if there already exists an account with the given email address. - * @error auth/invalid-email Thrown if the email address is not valid. - * @error auth/operation-not-allowed Thrown if email/password accounts are not enabled. Enable email/password accounts in the Firebase Console, under the Auth tab. - * @error auth/weak-password Thrown if the password is not strong enough. - * @param email The users email address. - * @param password The users password. - */ - createUserWithEmailAndPassword(email: string, password: string): Promise; - - /** - * Signs a user in with an email and password. - * - * ⚠️ Note: - * If "Email Enumeration Protection" is enabled in your Firebase Authentication settings (enabled by default), - * Firebase may return a generic `auth/invalid-login-credentials` error instead of more specific ones like - * `auth/user-not-found` or `auth/wrong-password`. This behavior is intended to prevent leaking information - * about whether an account with the given email exists. - * - * To receive detailed error codes, you must disable "Email Enumeration Protection", which may increase - * security risks if not properly handled on the frontend. - * - * #### Example - * - * ```js - * const userCredential = await firebase.auth().signInWithEmailAndPassword('joe.bloggs@example.com', '123456'); - * ``` - * - * @error auth/invalid-email Thrown if the email address is not valid. - * @error auth/user-disabled Thrown if the user corresponding to the given email has been disabled. - * @error auth/user-not-found Thrown if there is no user corresponding to the given email. (May be suppressed if email enumeration protection is enabled.) - * @error auth/wrong-password Thrown if the password is invalid or missing. (May be suppressed if email enumeration protection is enabled.) - * @param email The user's email address. - * @param password The user's password. - */ - signInWithEmailAndPassword(email: string, password: string): Promise; - - /** - * Signs a user in with a custom token. - * - * #### Example - * - * ```js - * // Create a custom token via the Firebase Admin SDK. - * const token = await firebase.auth().createCustomToken(uid, customClaims); - * ... - * // Use the token on the device to sign in. - * const userCredential = await firebase.auth().signInWithCustomToken(token); - * ``` - * - * @error auth/custom-token-mismatch Thrown if the custom token is for a different Firebase App. - * @error auth/invalid-custom-token Thrown if the custom token format is incorrect. - * @param customToken A custom token generated from the Firebase Admin SDK. - */ - signInWithCustomToken(customToken: string): Promise; - - /** - * Signs the user in with a generated credential. - * - * #### Example - * - * ```js - * // Generate a Firebase credential - * const credential = firebase.auth.FacebookAuthProvider.credential('access token from Facebook'); - * // Sign the user in with the credential - * const userCredential = await firebase.auth().signInWithCredential(credential); - * ``` - * - * @error auth/account-exists-with-different-credential Thrown if there already exists an account with the email address asserted by the credential. - * @error auth/invalid-credential Thrown if the credential is malformed or has expired. - * @error auth/operation-not-allowed Thrown if the type of account corresponding to the credential is not enabled. Enable the account type in the Firebase Console, under the Auth tab. - * @error auth/user-disabled Thrown if the user corresponding to the given credential has been disabled. - * @error auth/user-not-found Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and there is no user corresponding to the given email. - * @error auth/wrong-password Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and the password is invalid for the given email, or if the account corresponding to the email does not have a password set. - * @error auth/invalid-verification-code Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. - * @error auth/invalid-verification-id Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. - * @param credential A generated `AuthCredential`, for example from social auth. - */ - signInWithCredential(credential: AuthCredential): Promise; - - /** - * Signs the user in with a specified provider. This is a web-compatible API along with signInWithRedirect. - * They both share the same call to the underlying native SDK signInWithProvider method. - * - * #### Example - * - * ```js - * // create a new OAuthProvider - * const provider = firebase.auth.OAuthProvider('microsoft.com'); - * // Sign the user in with the provider - * const userCredential = await firebase.auth().signInWithPopup(provider); - * ``` - * - * @error auth/account-exists-with-different-credential Thrown if there already exists an account with the email address asserted by the credential. - * @error auth/invalid-credential Thrown if the credential is malformed or has expired. - * @error auth/operation-not-allowed Thrown if the type of account corresponding to the credential is not enabled. Enable the account type in the Firebase Console, under the Auth tab. - * @error auth/user-disabled Thrown if the user corresponding to the given credential has been disabled. - * @error auth/user-not-found Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and there is no user corresponding to the given email. - * @error auth/wrong-password Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and the password is invalid for the given email, or if the account corresponding to the email does not have a password set. - * @error auth/invalid-verification-code Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. - * @error auth/invalid-verification-id Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. - * @param provider An `AuthProvider` configured for your desired provider, e.g. "microsoft.com" - */ - signInWithPopup(provider: AuthProvider): Promise; - - /** - * Signs the user in with a specified provider. This is a web-compatible API along with signInWithPopup. - * They both share the same call to the underlying native SDK signInWithProvider method. - * - * #### Example - * - * ```js - * // create a new OAuthProvider - * const provider = firebase.auth.OAuthProvider('microsoft.com'); - * // Sign the user in with the provider - * const userCredential = await firebase.auth().signInWithRedirect(provider); - * ``` - * - * @error auth/account-exists-with-different-credential Thrown if there already exists an account with the email address asserted by the credential. - * @error auth/invalid-credential Thrown if the credential is malformed or has expired. - * @error auth/operation-not-allowed Thrown if the type of account corresponding to the credential is not enabled. Enable the account type in the Firebase Console, under the Auth tab. - * @error auth/user-disabled Thrown if the user corresponding to the given credential has been disabled. - * @error auth/user-not-found Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and there is no user corresponding to the given email. - * @error auth/wrong-password Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and the password is invalid for the given email, or if the account corresponding to the email does not have a password set. - * @error auth/invalid-verification-code Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. - * @error auth/invalid-verification-id Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. - * @param provider An `AuthProvider` configured for your desired provider, e.g. "microsoft.com" - */ - signInWithRedirect(provider: AuthProvider): Promise; - - /** - * Revokes a user's Sign in with Apple token. - * - * #### Example - * - * ```js - * // Generate an Apple ID authorizationCode for the currently logged in user (ie, with @invertase/react-native-apple-authentication) - * const { authorizationCode } = await appleAuth.performRequest({ requestedOperation: appleAuth.Operation.REFRESH }); - * // Revoke the token - * await firebase.auth().revokeToken(authorizationCode); - * ``` - * - * @param authorizationCode A generated authorization code from Sign in with Apple. - */ - revokeToken(authorizationCode: string): Promise; - - /** - * Signs the user in with a federated OAuth provider supported by Firebase (Microsoft, Yahoo). - * - * From Firebase Docs: - * Unlike other OAuth providers supported by Firebase such as Google, Facebook, and Twitter, where - * sign-in can directly be achieved with OAuth access token based credentials, Firebase Auth does not - * support the same capability for providers such as Microsoft due to the inability of the Firebase Auth - * server to verify the audience of Microsoft OAuth access tokens. - * - * #### Example - * ```js - * // Generate an OAuth instance - * const provider = new firebase.auth.OAuthProvider('microsoft.com'); - * // Optionally add scopes to the OAuth instance - * provider.addScope('mail.read'); - * // Optionally add custom parameters to the OAuth instance - * provider.setCustomParameters({ - * prompt: 'consent', - * }); - * // Sign in using the OAuth provider - * const userCredential = await firebase.auth().signInWithProvider(provider); - * ``` - * - * @error auth/account-exists-with-different-credential Thrown if there already exists an account with the email address asserted by the credential. - * @error auth/invalid-credential Thrown if the credential is malformed or has expired. - * @error auth/operation-not-allowed Thrown if the type of account corresponding to the credential is not enabled. Enable the account type in the Firebase Console, under the Auth tab. - * @error auth/user-disabled Thrown if the user corresponding to the given credential has been disabled. - * @error auth/user-not-found Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and there is no user corresponding to the given email. - * @error auth/wrong-password Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and the password is invalid for the given email, or if the account corresponding to the email does not have a password set. - * @error auth/invalid-verification-code Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. - * @error auth/invalid-verification-id Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. - * @param provider A generated `AuthProvider`, for example from social auth. - */ - signInWithProvider(provider: AuthProvider): Promise; - - /** - * Sends a password reset email to the given email address. - * Unlike the web SDK, the email will contain a password reset link rather than a code. - * - * #### Example - * - * ```js - * await firebase.auth().sendPasswordResetEmail('joe.bloggs@example.com'); - * ``` - * - * @error auth/invalid-email Thrown if the email address is not valid. - * @error auth/missing-android-pkg-name An Android package name must be provided if the Android app is required to be installed. - * @error auth/missing-continue-uri A continue URL must be provided in the request. - * @error auth/missing-ios-bundle-id An iOS Bundle ID must be provided if an App Store ID is provided. - * @error auth/invalid-continue-uri The continue URL provided in the request is invalid. - * @error auth/unauthorized-continue-uri The domain of the continue URL is not whitelisted. Whitelist the domain in the Firebase console. - * @error auth/user-not-found Thrown if there is no user corresponding to the email address. - * @param email The users email address. - * @param actionCodeSettings Additional settings to be set before sending the reset email. - */ - sendPasswordResetEmail(email: string, actionCodeSettings?: ActionCodeSettings): Promise; - - /** - * Sends a sign in link to the user. - * - * #### Example - * - * ```js - * await firebase.auth().sendSignInLinkToEmail('joe.bloggs@example.com'); - * ``` - * - * @error auth/argument-error Thrown if handleCodeInApp is false. - * @error auth/invalid-email Thrown if the email address is not valid. - * @error auth/missing-android-pkg-name An Android package name must be provided if the Android app is required to be installed. - * @error auth/missing-continue-uri A continue URL must be provided in the request. - * @error auth/missing-ios-bundle-id An iOS Bundle ID must be provided if an App Store ID is provided. - * @error auth/invalid-continue-uri The continue URL provided in the request is invalid. - * @error auth/unauthorized-continue-uri The domain of the continue URL is not whitelisted. Whitelist the domain in the Firebase console. - * @param email The users email address. - * @param actionCodeSettings The action code settings. The action code settings which provides Firebase with instructions on how to construct the email link. This includes the sign in completion URL or the deep link for mobile redirects, the mobile apps to use when the sign-in link is opened on an Android or iOS device. Mobile app redirects will only be applicable if the developer configures and accepts the Firebase Dynamic Links terms of condition. The Android package name and iOS bundle ID will be respected only if they are configured in the same Firebase Auth project used. - */ - sendSignInLinkToEmail(email: string, actionCodeSettings?: ActionCodeSettings): Promise; - - /** - * Checks if an incoming link is a sign-in with email link suitable for signInWithEmailLink. - * Note that android and other platforms require `apiKey` link parameter for signInWithEmailLink - * - * #### Example - * - * ```js - * const valid = await firebase.auth().isSignInWithEmailLink(link); - * ``` - * - * @param emailLink The email link to verify prior to using signInWithEmailLink - */ - isSignInWithEmailLink(emailLink: string): Promise; - - /** - * Signs the user in with an email link. - * - * #### Example - * - * ```js - * const userCredential = await firebase.auth().signInWithEmailLink('joe.bloggs@example.com', link); - * ``` - * - * @error auth/expired-action-code Thrown if OTP in email link expires. - * @error auth/invalid-email Thrown if the email address is not valid. - * @error auth/user-disabled Thrown if the user corresponding to the given email has been disabled. - * @param email The users email to sign in with. - * @param emailLink An email link. - */ - signInWithEmailLink(email: string, emailLink: string): Promise; - - /** - * Completes the password reset process with the confirmation code and new password, via - * {@link sendPasswordResetEmail}. - * - * #### Example - * - * ```js - * await firebase.auth().confirmPasswordReset('ABCD', '1234567'); - * ``` - * - * @error auth/expired-action-code Thrown if the password reset code has expired. - * @error auth/invalid-action-code Thrown if the password reset code is invalid. This can happen if the code is malformed or has already been used. - * @error auth/user-disabled Thrown if the user corresponding to the given password reset code has been disabled. - * @error auth/user-not-found Thrown if there is no user corresponding to the password reset code. This may have happened if the user was deleted between when the code was issued and when this method was called. - * @error auth/weak-password Thrown if the new password is not strong enough. - * @param code The code from the password reset email. - * @param newPassword The new password. - */ - confirmPasswordReset(code: string, newPassword: string): Promise; - - /** - * Applies a verification code sent to the user by email or other out-of-band mechanism. - * - * #### Example - * - * ```js - * await firebase.auth().applyActionCode('ABCD'); - * ``` - * - * @error auth/expired-action-code Thrown if the action code has expired. - * @error auth/invalid-action-code Thrown if the action code is invalid. This can happen if the code is malformed or has already been used. - * @error auth/user-disabled Thrown if the user corresponding to the given action code has been disabled. - * @error auth/user-not-found Thrown if there is no user corresponding to the action code. This may have happened if the user was deleted between when the action code was issued and when this method was called. - * @param code A verification code sent to the user. - */ - applyActionCode(code: string): Promise; - - /** - * Checks a verification code sent to the user by email or other out-of-band mechanism. - * - * #### Example - * - * ```js - * const actionCodeInfo = await firebase.auth().checkActionCode('ABCD'); - * console.log('Action code operation: ', actionCodeInfo.operation); - * ``` - * - * @error auth/expired-action-code Thrown if the action code has expired. - * @error auth/invalid-action-code Thrown if the action code is invalid. This can happen if the code is malformed or has already been used. - * @error auth/user-disabled Thrown if the user corresponding to the given action code has been disabled. - * @error auth/user-not-found Thrown if there is no user corresponding to the action code. This may have happened if the user was deleted between when the action code was issued and when this method was called. - * @param code A verification code sent to the user. - */ - checkActionCode(code: string): Promise; - - /** - * Returns a list of authentication methods that can be used to sign in a given user (identified by its main email address). - * - * ⚠️ Note: - * If "Email Enumeration Protection" is enabled in your Firebase Authentication settings (which is the default), - * this method may return an empty array even if the email is registered, especially when called from an unauthenticated context. - * - * This is a security measure to prevent leaking account existence via email enumeration attacks. - * Do not use the result of this method to directly inform the user whether an email is registered. - * - * #### Example - * - * ```js - * const methods = await firebase.auth().fetchSignInMethodsForEmail('joe.bloggs@example.com'); - * - * if (methods.length > 0) { - * // Likely a registered user — offer sign-in - * } else { - * // Could be unregistered OR email enumeration protection is active — offer registration - * } - * ``` - * - * @error auth/invalid-email Thrown if the email address is not valid. - * @param email The user's email address. - */ - fetchSignInMethodsForEmail(email: string): Promise; - - /** - * Checks a password reset code sent to the user by email or other out-of-band mechanism. - * TODO salakar: confirm return behavior (Returns the user's email address if valid.) - * - * #### Example - * - * ```js - * const verifiedEmail = await firebase.auth().verifyPasswordResetCode('ABCD'); - * ``` - * - * @error auth/expired-action-code Thrown if the password reset code has expired. - * @error auth/invalid-action-code Thrown if the password reset code is invalid. This can happen if the code is malformed or has already been used. - * @error auth/user-disabled Thrown if the user corresponding to the given password reset code has been disabled. - * @error auth/user-not-found Thrown if there is no user corresponding to the password reset code. This may have happened if the user was deleted between when the code was issued and when this method was called. - * @param code A password reset code. - * @returns {string} The user's email address if valid - */ - verifyPasswordResetCode(code: string): Promise; - /** - * Switch userAccessGroup and current user to the given accessGroup and the user stored in it. - * Sign in a user with any sign in method, and the same current user is available in all - * apps in the access group. - * - * Set the `useAccessGroup` argument to `null` to stop sharing the auth state (default behaviour), the user state will no longer be - * available to any other apps. - * - * @platform ios - * - * @error auth/keychain-error Thrown if you attempt to access an inaccessible keychain - * @param userAccessGroup A string of the keychain id i.e. "TEAMID.com.example.group1" - */ - useUserAccessGroup(userAccessGroup: string): Promise; - /** - * Modify this Auth instance to communicate with the Firebase Auth emulator. - * This must be called synchronously immediately following the first call to firebase.auth(). - * Do not use with production credentials as emulator traffic is not encrypted. - * - * Note: on android, hosts 'localhost' and '127.0.0.1' are automatically remapped to '10.0.2.2' (the - * "host" computer IP address for android emulators) to make the standard development experience easy. - * If you want to use the emulator on a real android device, you will need to specify the actual host - * computer IP address. - * - * @param url: emulator URL, must have host and port (eg, 'http://localhost:9099') - */ - useEmulator(url: string): void; - /** - * Provides a MultiFactorResolver suitable for completion of a multi-factor flow. - * - * @param error: The MultiFactorError raised during a sign-in, or reauthentication operation. - */ - getMultiFactorResolver(error: MultiFactorError): MultiFactorResolver; - /** - * The MultiFactorUser corresponding to the user. - * - * This is used to access all multi-factor properties and operations related to the user. - * @param user The user. - */ - multiFactor(user: User): MultiFactorUser; - /** - * Returns the custom auth domain for the auth instance. - */ - getCustomAuthDomain(): Promise; - /** - * Sets the language code on the auth instance. This is to match Firebase JS SDK behavior. - * Please use the `setLanguageCode` method for setting the language code. - */ - set languageCode(code: string | null); - /** - * Gets the config used to initialize this auth instance. This is to match Firebase JS SDK behavior. - * It returns an empty map as the config is not available in the native SDK. - */ - get config(): Map; - } -} - -export type CallbackOrObserver any> = T | { next: T }; - -type AuthNamespace = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp< - FirebaseAuthTypes.Module, - FirebaseAuthTypes.Statics -> & { - auth: ReactNativeFirebase.FirebaseModuleWithStaticsAndApp< - FirebaseAuthTypes.Module, - FirebaseAuthTypes.Statics - >; - firebase: ReactNativeFirebase.Module; - app(name?: string): ReactNativeFirebase.FirebaseApp; -}; - -declare const defaultExport: AuthNamespace; - -export const firebase: ReactNativeFirebase.Module & { - auth: typeof defaultExport; - app(name?: string): ReactNativeFirebase.FirebaseApp & { auth(): FirebaseAuthTypes.Module }; -}; - -export default defaultExport; - -/** - * Attach namespace to `firebase.` and `FirebaseApp.`. - */ -declare module '@react-native-firebase/app' { - namespace ReactNativeFirebase { - import FirebaseModuleWithStaticsAndApp = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp; - interface Module { - auth: FirebaseModuleWithStaticsAndApp; - } - interface FirebaseApp { - auth(): FirebaseAuthTypes.Module; - } - } -} - -export * from './modular'; diff --git a/packages/auth/lib/index.js b/packages/auth/lib/index.ts similarity index 99% rename from packages/auth/lib/index.js rename to packages/auth/lib/index.ts index 3ddb6dc9f9..e1d88163cf 100644 --- a/packages/auth/lib/index.js +++ b/packages/auth/lib/index.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -49,7 +50,7 @@ import OIDCAuthProvider from './providers/OIDCAuthProvider'; import PhoneAuthProvider from './providers/PhoneAuthProvider'; import TwitterAuthProvider from './providers/TwitterAuthProvider'; import { TotpSecret } from './TotpSecret'; -import version from './version'; +import { version } from './version'; import fallBackModule from './web/RNFBAuthModule'; import { PasswordPolicyMixin } from './password-policy/PasswordPolicyMixin'; diff --git a/packages/auth/lib/modular/index.d.ts b/packages/auth/lib/modular/index.d.ts deleted file mode 100644 index edaec52bb2..0000000000 --- a/packages/auth/lib/modular/index.d.ts +++ /dev/null @@ -1,801 +0,0 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library 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 { ReactNativeFirebase } from '@react-native-firebase/app'; -import { FirebaseAuthTypes, CallbackOrObserver } from '../index'; -import { firebase } from '..'; - -import Auth = FirebaseAuthTypes.Module; -import FirebaseApp = ReactNativeFirebase.FirebaseApp; - -/** - * Returns the Auth instance associated with the provided FirebaseApp. - * @param app - The Firebase app instance. - * @returns The Auth instance. - */ -export function getAuth(app?: FirebaseApp): Auth; - -/** - * This function allows more control over the Auth instance than getAuth(). - * - * @param app - The Firebase app instance. - * @param deps - Optional. Dependencies for the Auth instance. - * @returns The Auth instance. - * - * getAuth uses platform-specific defaults to supply the Dependencies. - * In general, getAuth is the easiest way to initialize Auth and works for most use cases. - * Use initializeAuth if you need control over which persistence layer is used, or to minimize bundle size - * if you're not using either signInWithPopup or signInWithRedirect. - */ -export function initializeAuth(app: FirebaseApp, deps?: any): Auth; - -/** - * Applies a verification code sent to the user by email or other out-of-band mechanism. - * - * @param auth - The Auth instance. - * @param oobCode - The out-of-band code sent to the user. - * @returns A promise that resolves when the code is applied successfully. - */ -export function applyActionCode(auth: Auth, oobCode: string): Promise; - -/** - * Adds a blocking callback that runs before an auth state change sets a new user. - * - * @param auth - The Auth instance. - * @param callback - A callback function to run before the auth state changes. - * @param onAbort - Optional. A callback function to run if the operation is aborted. - * - */ -export function beforeAuthStateChanged( - auth: Auth, - callback: (user: FirebaseAuthTypes.User | null) => void, - onAbort?: () => void, -): void; - -/** - * Checks a verification code sent to the user by email or other out-of-band mechanism. - * - * @param auth - The Auth instance. - * @param oobCode - The out-of-band code sent to the user. - * @returns A promise that resolves with the action code information. - */ -export function checkActionCode( - auth: Auth, - oobCode: string, -): Promise; - -/** - * Completes the password reset process, given a confirmation code and new password. - * - * @param auth - The Auth instance. - * @param oobCode - The out-of-band code sent to the user. - * @param newPassword - The new password. - * @returns A promise that resolves when the password is reset. - */ -export function confirmPasswordReset( - auth: Auth, - oobCode: string, - newPassword: string, -): Promise; - -/** - * Changes the Auth instance to communicate with the Firebase Auth Emulator, instead of production Firebase Auth services. - * - * @param auth - The Auth instance. - * @param url - The URL of the Firebase Auth Emulator. - * @param options - Optional. Options for the emulator connection. - * - * This must be called synchronously immediately following the first call to initializeAuth(). Do not use with production credentials as emulator traffic is not encrypted. - */ -export function connectAuthEmulator( - auth: Auth, - url: string, - options?: { disableWarnings: boolean }, -): void; - -/** - * Creates a new user account associated with the specified email address and password. - * - * @param auth - The Auth instance. - * @param email - The user's email address. - * @param password - The user's password. - * @returns A promise that resolves with the user credentials. - */ -export function createUserWithEmailAndPassword( - auth: Auth, - email: string, - password: string, -): Promise; - -/** - * Gets the list of possible sign in methods for the given email address. - * - * @param auth - The Auth instance. - * @param email - The user's email address. - * @returns A promise that resolves with the list of sign-in methods. - */ -export function fetchSignInMethodsForEmail(auth: Auth, email: string): Promise; - -/** - * Provides a MultiFactorResolver suitable for completion of a multi-factor flow. - * - * @param auth - The Auth instance. - * @param error - The multi-factor error. - * @returns The MultiFactorResolver instance. - */ -export function getMultiFactorResolver( - auth: Auth, - error: FirebaseAuthTypes.MultiFactorError, -): FirebaseAuthTypes.MultiFactorResolver; - -/** - * Returns a UserCredential from the redirect-based sign-in flow. - * - * @param auth - The Auth instance. - * @param resolver - Optional. The popup redirect resolver. - * @returns A promise that resolves with the user credentials or null. - */ -export function getRedirectResult( - auth: Auth, - resolver?: PopupRedirectResolver, -): Promise; - -export interface PopupRedirectResolver {} - -/** - * Loads the reCAPTCHA configuration into the Auth instance. - * Does not work in a Node.js environment - * @param auth - The Auth instance. - */ -export function initializeRecaptchaConfig(auth: Auth): Promise; - -/** - * Checks if an incoming link is a sign-in with email link suitable for signInWithEmailLink. - * Note that android and other platforms require `apiKey` link parameter for signInWithEmailLink - * - * @param auth - The Auth instance. - * @param emailLink - The email link to check. - * @returns A promise that resolves if the link is a sign-in with email link. - */ -export function isSignInWithEmailLink(auth: Auth, emailLink: string): Promise; - -/** - * Adds an observer for changes to the user's sign-in state. - * - * @param auth - The Auth instance. - * @param nextOrObserver - A callback function or observer for auth state changes. - * @returns A function to unsubscribe from the auth state changes. - */ -export function onAuthStateChanged( - auth: Auth, - nextOrObserver: CallbackOrObserver, -): () => void; - -/** - * Adds an observer for changes to the signed-in user's ID token. - * - * @param auth - The Auth instance. - * @param nextOrObserver - A callback function or observer for ID token changes. - * @returns A function to unsubscribe from the ID token changes. - */ -export function onIdTokenChanged( - auth: Auth, - nextOrObserver: CallbackOrObserver, -): () => void; - -/** - * Revoke the given access token, Currently only supports Apple OAuth access tokens. - * @param auth - * @param token - */ -export declare function revokeAccessToken(auth: Auth, token: string): Promise; - -/** - * Sends a password reset email to the given email address. - * - * @param auth - The Auth instance. - * @param email - The user's email address. - * @param actionCodeSettings - Optional. Action code settings. - * @returns A promise that resolves when the email is sent. - */ -export function sendPasswordResetEmail( - auth: Auth, - email: string, - actionCodeSettings?: FirebaseAuthTypes.ActionCodeSettings, -): Promise; - -/** - * Sends a sign-in email link to the user with the specified email. - * - * @param auth - The Auth instance. - * @param email - The user's email address. - * @param actionCodeSettings - Optional, Action code settings. - * @returns A promise that resolves when the email is sent. - */ -export function sendSignInLinkToEmail( - auth: Auth, - email: string, - actionCodeSettings?: FirebaseAuthTypes.ActionCodeSettings, -): Promise; - -/** - * Type of Persistence. - * - 'SESSION' is used for temporary persistence such as `sessionStorage`. - * - 'LOCAL' is used for long term persistence such as `localStorage` or `IndexedDB`. - * - 'NONE' is used for in-memory, or no persistence. - */ -export type Persistence = { - readonly type: 'SESSION' | 'LOCAL' | 'NONE'; -}; - -/** - * Changes the type of persistence on the Auth instance for the currently saved Auth session and applies this type of persistence for future sign-in requests, including sign-in with redirect requests. - * - * @param auth - The Auth instance. - * @param persistence - The persistence type. - * @returns A promise that resolves when the persistence is set. - */ -export function setPersistence(auth: Auth, persistence: Persistence): Promise; - -/** - * Asynchronously signs in as an anonymous user. - * - * @param auth - The Auth instance. - * @returns A promise that resolves with the user credentials. - */ -export function signInAnonymously(auth: Auth): Promise; - -/** - * Asynchronously signs in with the given credentials. - * - * @param auth - The Auth instance. - * @param credential - The auth credentials. - * @returns A promise that resolves with the user credentials. - */ -export function signInWithCredential( - auth: Auth, - credential: FirebaseAuthTypes.AuthCredential, -): Promise; - -/** - * Asynchronously signs in using a custom token. - * - * @param auth - The Auth instance. - * @param customToken - The custom token. - * @returns A promise that resolves with the user credentials. - */ -export function signInWithCustomToken( - auth: Auth, - customToken: string, -): Promise; - -/** - * Asynchronously signs in using an email and password. - * - * @param auth - The Auth instance. - * @param email - The user's email address. - * @param password - The user's password. - * @returns A promise that resolves with the user credentials. - */ -export function signInWithEmailAndPassword( - auth: Auth, - email: string, - password: string, -): Promise; - -/** - * Asynchronously signs in using an email and sign-in email link. - * - * @param auth - The Auth instance. - * @param email - The user's email address. - * @param emailLink - The email link. - * @returns A promise that resolves with the user credentials. - */ -export function signInWithEmailLink( - auth: Auth, - email: string, - emailLink: string, -): Promise; - -/** - * Interface representing an application verifier. - */ -export interface ApplicationVerifier { - readonly type: string; - verify(): Promise; -} - -/** - * Asynchronously signs in using a phone number. - * - * @param auth - The Auth instance. - * @param phoneNumber - The user's phone number. - * @param appVerifier - Optional. The application verifier. - * @param forceResend - Optional. (Native only) Forces a new message to be sent if it was already recently sent. - * @returns A promise that resolves with the confirmation result. - */ -export function signInWithPhoneNumber( - auth: Auth, - phoneNumber: string, - appVerifier?: ApplicationVerifier, - forceResend?: boolean, -): Promise; - -/** - * Asynchronously signs in using a phone number. - * - * @param auth - The Auth instance. - * @param phoneNumber - The user's phone number. - * @param autoVerifyTimeoutOrForceResend - The auto verify timeout or force resend flag. - * @param forceResend - Optional. Whether to force resend. - * @returns A promise that resolves with the phone auth listener. - */ -export function verifyPhoneNumber( - auth: Auth, - phoneNumber: string, - autoVerifyTimeoutOrForceResend: number | boolean, - forceResend?: boolean, -): FirebaseAuthTypes.PhoneAuthListener; - -/** - * Authenticates a Firebase client using a popup-based OAuth authentication flow. - * - * @param auth - The Auth instance. - * @param provider - The auth provider. - * @param resolver - Optional. The popup redirect resolver. - * @returns A promise that resolves with the user credentials. - */ -export function signInWithPopup( - auth: Auth, - provider: FirebaseAuthTypes.AuthProvider, - resolver?: PopupRedirectResolver, -): Promise; - -/** - * Authenticates a Firebase client using a full-page redirect flow. - * - * @param auth - The Auth instance. - * @param provider - The auth provider. - * @param resolver - Optional. The popup redirect resolver. - * @returns A promise that resolves when the redirect is complete. - */ -export function signInWithRedirect( - auth: Auth, - provider: FirebaseAuthTypes.AuthProvider, - resolver?: PopupRedirectResolver, -): Promise; - -/** - * Signs out the current user. - * - * @param auth - The Auth instance. - * @returns A promise that resolves when the user is signed out. - */ -export function signOut(auth: Auth): Promise; - -/** - * Asynchronously sets the provided user as Auth.currentUser on the Auth instance. - * - * @param auth - The Auth instance. - * @param user - The user to set as the current user. - * @returns A promise that resolves when the user is set. - */ -export function updateCurrentUser(auth: Auth, user: FirebaseAuthTypes.User | null): Promise; - -/** - * Sets the current language to the default device/browser preference. - * - * @param auth - The Auth instance. - */ -export function useDeviceLanguage(auth: Auth): void; - -/** - * Sets the language code. - * - * #### Example - * - * ```js - * // Set language to French - * await firebase.auth().setLanguageCode('fr'); - * ``` - * @param auth - The Auth instance. - * @param languageCode An ISO language code. - * 'null' value will set the language code to the app's current language. - */ -export function setLanguageCode(auth: Auth, languageCode: string | null): Promise; - -/** - * Validates the password against the password policy configured for the project or tenant. - * - * @param auth - The Auth instance. - * @param password - The password to validate. - * - */ -export function validatePassword(auth: Auth, password: string): Promise; - -/** - * Configures a shared user access group to sync auth state across multiple apps via the Keychain. - * - * @param auth - The Auth instance. - * @param userAccessGroup - The user access group. - * @returns A promise that resolves when the user access group is set. - */ -export function useUserAccessGroup(auth: Auth, userAccessGroup: string): Promise; - -/** - * Verifies the password reset code sent to the user by email or other out-of-band mechanism. - * - * @param auth - The Auth instance. - * @param code - The password reset code. - * @returns A promise that resolves with the user's email address. - */ -export function verifyPasswordResetCode(auth: Auth, code: string): Promise; - -/** - * Parses the email action link string and returns an ActionCodeURL if the link is valid, otherwise returns null. - * - * @param link - The email action link string. - * @returns The ActionCodeURL if the link is valid, otherwise null. - */ -export function parseActionCodeURL(link: string): FirebaseAuthTypes.ActionCodeURL | null; - -/** - * Deletes and signs out the user. - * - * @param user - The user to delete. - * @returns A promise that resolves when the user is deleted. - */ -export function deleteUser(user: FirebaseAuthTypes.User): Promise; - -/** - * Returns a JSON Web Token (JWT) used to identify the user to a Firebase service. - * - * @param user - The user to get the token for. - * @param forceRefresh - Optional. Whether to force refresh the token. - * @returns A promise that resolves with the token. - */ -export function getIdToken(user: FirebaseAuthTypes.User, forceRefresh?: boolean): Promise; - -/** - * Returns a deserialized JSON Web Token (JWT) used to identify the user to a Firebase service. - * - * @param user - The user to get the token result for. - * @param forceRefresh - Optional. Whether to force refresh the token. - * @returns A promise that resolves with the token result. - */ -export function getIdTokenResult( - user: FirebaseAuthTypes.User, - forceRefresh?: boolean, -): Promise; - -/** - * Links the user account with the given credentials. - * - * @param user - The user to link the credentials with. - * @param credential - The auth credentials. - * @returns A promise that resolves with the user credentials. - */ -export function linkWithCredential( - user: FirebaseAuthTypes.User, - credential: FirebaseAuthTypes.AuthCredential, -): Promise; - -/** - * Links the user account with the given phone number. - * - * @param user - The user to link the phone number with. - * @param phoneNumber - The phone number. - * @param appVerifier - The application verifier. - * @returns A promise that resolves with the confirmation result. - */ -export function linkWithPhoneNumber( - user: FirebaseAuthTypes.User, - phoneNumber: string, - appVerifier?: ApplicationVerifier, -): Promise; - -/** - * Links the authenticated provider to the user account using a pop-up based OAuth flow. - * - * @param user - The user to link the provider with. - * @param provider - The auth provider. - * @param resolver - Optional. The popup redirect resolver. - * @returns A promise that resolves with the user credentials. - */ -export function linkWithPopup( - user: FirebaseAuthTypes.User, - provider: FirebaseAuthTypes.AuthProvider, - resolver?: PopupRedirectResolver, -): Promise; - -/** - * Links the OAuthProvider to the user account using a full-page redirect flow. - * - * @param user - The user to link the provider with. - * @param provider - The auth provider. - * @param resolver - Optional. The popup redirect resolver. - * @returns A promise that resolves when the redirect is complete. - */ -export function linkWithRedirect( - user: FirebaseAuthTypes.User, - provider: FirebaseAuthTypes.AuthProvider, - resolver?: PopupRedirectResolver, -): Promise; - -/** - * The MultiFactorUser corresponding to the user. - * - * @param user - The user to get the multi-factor user for. - * @returns The MultiFactorUser instance. - */ -export function multiFactor(user: FirebaseAuthTypes.User): FirebaseAuthTypes.MultiFactorUser; - -/** - * Re-authenticates a user using a fresh credential. - * - * @param user - The user to re-authenticate. - * @param credential - The auth credentials. - * @returns A promise that resolves with the user credentials. - */ -export function reauthenticateWithCredential( - user: FirebaseAuthTypes.User, - credential: FirebaseAuthTypes.AuthCredential, -): Promise; - -/** - * Re-authenticates a user using a fresh phone credential. - * - * @param user - The user to re-authenticate. - * @param phoneNumber - The phone number. - * @param appVerifier - The application verifier. - * @returns A promise that resolves with the confirmation result. - */ -export function reauthenticateWithPhoneNumber( - user: FirebaseAuthTypes.User, - phoneNumber: string, - appVerifier?: ApplicationVerifier, -): Promise; - -/** - * Re-authenticate a user with a federated authentication provider (Microsoft, Yahoo). For native platforms, this will open a browser window. - * - * @param user - The user to re-authenticate. - * @param provider - The auth provider. - * @param resolver - Optional. The popup redirect resolver. Web only. - * @returns A promise that resolves with the user credentials. - */ -export function reauthenticateWithPopup( - user: FirebaseAuthTypes.User, - provider: FirebaseAuthTypes.AuthProvider, - resolver?: PopupRedirectResolver, -): Promise; - -/** - * Re-authenticate a user with a federated authentication provider (Microsoft, Yahoo). For native platforms, this will open a browser window. - * - * @param user - The user to re-authenticate. - * @param provider - The auth provider. - * @param resolver - Optional. The popup redirect resolver. Web only. - * @returns A promise that resolves with no value. - */ -export function reauthenticateWithRedirect( - user: FirebaseAuthTypes.User, - provider: FirebaseAuthTypes.AuthProvider, - resolver?: PopupRedirectResolver, -): Promise; - -/** - * Reloads user account data, if signed in. - * - * @param user - The user to reload data for. - * @returns A promise that resolves when the data is reloaded. - */ -export function reload(user: FirebaseAuthTypes.User): Promise; - -/** - * Sends a verification email to a user. - * - * @param user - The user to send the email to. - * @param actionCodeSettings - Optional. Action code settings. - * @returns A promise that resolves when the email is sent. - */ -export function sendEmailVerification( - user: FirebaseAuthTypes.User, - actionCodeSettings?: FirebaseAuthTypes.ActionCodeSettings, -): Promise; - -/** - * Unlinks a provider from a user account. - * - * @param user - The user to unlink the provider from. - * @param providerId - The provider ID. - * @returns A promise that resolves with the user. - */ -export function unlink( - user: FirebaseAuthTypes.User, - providerId: string, -): Promise; - -/** - * Updates the user's email address. - * - * @param user - The user to update the email for. - * @param newEmail - The new email address. - * @returns A promise that resolves when the email is updated. - */ -export function updateEmail(user: FirebaseAuthTypes.User, newEmail: string): Promise; - -/** - * Updates the user's password. - * - * @param user - The user to update the password for. - * @param newPassword - The new password. - * @returns A promise that resolves when the password is updated. - */ -export function updatePassword(user: FirebaseAuthTypes.User, newPassword: string): Promise; - -/** - * Updates the user's phone number. - * - * @param user - The user to update the phone number for. - * @param credential - The auth credentials. - * @returns A promise that resolves when the phone number is updated. - */ -export function updatePhoneNumber( - user: FirebaseAuthTypes.User, - credential: FirebaseAuthTypes.AuthCredential, -): Promise; - -/** - * Updates a user's profile data. - * - * @param user - The user to update the profile for. - * @param profile - An object containing the profile data to update. - * @returns A promise that resolves when the profile is updated. - */ -export function updateProfile( - user: FirebaseAuthTypes.User, - { displayName, photoURL: photoUrl }: { displayName?: string | null; photoURL?: string | null }, -): Promise; - -/** - * Sends a verification email to a new email address. - * - * @param user - The user to send the email to. - * @param newEmail - The new email address. - * @param actionCodeSettings - Optional. Action code settings. - * @returns A promise that resolves when the email is sent. - */ -export function verifyBeforeUpdateEmail( - user: FirebaseAuthTypes.User, - newEmail: string, - actionCodeSettings?: FirebaseAuthTypes.ActionCodeSettings | null, -): Promise; - -/** - * Extracts provider specific AdditionalUserInfo for the given credential. - * - * @param userCredential - The user credential. - * @returns The additional user information, or null if none is available. - */ -export function getAdditionalUserInfo( - userCredential: FirebaseAuthTypes.UserCredential, -): FirebaseAuthTypes.AdditionalUserInfo | null; - -/** - * Returns the custom auth domain for the auth instance. - * - * @param auth - The Auth instance. - * @returns {Promise} A promise that resolves with the custom auth domain. - */ -export function getCustomAuthDomain(auth: Auth): Promise; - -/** - * Validates the password against the password policy configured for the project or tenant. - * - * @remarks - * If no tenant ID is set on the `Auth` instance, then this method will use the password - * policy configured for the project. Otherwise, this method will use the policy configured - * for the tenant. If a password policy has not been configured, then the default policy - * configured for all projects will be used. - * - * If an auth flow fails because a submitted password does not meet the password policy - * requirements and this method has previously been called, then this method will use the - * most recent policy available when called again. - * - * When using this method, ensure you have the Identity Toolkit enabled on the - * Google Cloud Platform with the API Key for your application permitted to use it. - * - * @example - * ``` js - * import { getAuth, validatePassword } from "firebase/auth"; - * - * const status = await validatePassword(getAuth(), passwordFromUser); - * if (!status.isValid) { - * // Password could not be validated. Use the status to show what - * // requirements are met and which are missing. - * - * // If a criterion is undefined, it is not required by policy. If the - * // criterion is defined but false, it is required but not fulfilled by - * // the given password. For example: - * const needsLowerCase = status.containsLowercaseLetter !== true; - * } - * ``` - * - * @param auth The {@link Auth} instance. - * @param password The password to validate. - * - * @public - */ -export function validatePassword(auth: Auth, password: string): Promise; - -/** - * A structure indicating which password policy requirements were met or violated and what the - * requirements are. - * - * @public - */ -export interface PasswordValidationStatus { - /** - * Whether the password meets all requirements. - */ - readonly isValid: boolean; - /** - * Whether the password meets the minimum password length, or undefined if not required. - */ - readonly meetsMinPasswordLength?: boolean; - /** - * Whether the password meets the maximum password length, or undefined if not required. - */ - readonly meetsMaxPasswordLength?: boolean; - /** - * Whether the password contains a lowercase letter, or undefined if not required. - */ - readonly containsLowercaseLetter?: boolean; - /** - * Whether the password contains an uppercase letter, or undefined if not required. - */ - readonly containsUppercaseLetter?: boolean; - /** - * Whether the password contains a numeric character, or undefined if not required. - */ - readonly containsNumericCharacter?: boolean; - /** - * Whether the password contains a non-alphanumeric character, or undefined if not required. - */ - readonly containsNonAlphanumericCharacter?: boolean; - /** - * The policy used to validate the password. - */ - readonly passwordPolicy: PasswordPolicy; -} - -export { - AppleAuthProvider, - EmailAuthProvider, - FacebookAuthProvider, - GithubAuthProvider, - GoogleAuthProvider, - OAuthProvider, - OIDCAuthProvider, - PhoneAuthProvider, - PhoneMultiFactorGenerator, - TotpMultiFactorGenerator, - TotpSecret, - TwitterAuthProvider, - PhoneAuthState, -} from '../index'; diff --git a/packages/auth/lib/modular/index.js b/packages/auth/lib/modular/index.ts similarity index 99% rename from packages/auth/lib/modular/index.js rename to packages/auth/lib/modular/index.ts index ff408213d0..e19413b044 100644 --- a/packages/auth/lib/modular/index.js +++ b/packages/auth/lib/modular/index.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* eslint-disable @typescript-eslint/no-unused-vars */ /* * Copyright (c) 2016-present Invertase Limited & Contributors diff --git a/packages/auth/lib/multiFactor.js b/packages/auth/lib/multiFactor.ts similarity index 99% rename from packages/auth/lib/multiFactor.js rename to packages/auth/lib/multiFactor.ts index bfaca1278f..9729959eb6 100644 --- a/packages/auth/lib/multiFactor.js +++ b/packages/auth/lib/multiFactor.ts @@ -1,3 +1,4 @@ +// @ts-nocheck import { reload } from './modular'; /** * Return a MultiFactorUser instance the gateway to multi-factor operations. diff --git a/packages/auth/lib/password-policy/PasswordPolicyImpl.js b/packages/auth/lib/password-policy/PasswordPolicyImpl.ts similarity index 98% rename from packages/auth/lib/password-policy/PasswordPolicyImpl.js rename to packages/auth/lib/password-policy/PasswordPolicyImpl.ts index cdfb99a118..6613758106 100644 --- a/packages/auth/lib/password-policy/PasswordPolicyImpl.js +++ b/packages/auth/lib/password-policy/PasswordPolicyImpl.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -63,7 +64,7 @@ export class PasswordPolicyImpl { this.schemaVersion = response.schemaVersion; } - validatePassword(password) { + validatePassword(password): any { const status = { isValid: true, passwordPolicy: this, diff --git a/packages/auth/lib/password-policy/PasswordPolicyMixin.js b/packages/auth/lib/password-policy/PasswordPolicyMixin.ts similarity index 99% rename from packages/auth/lib/password-policy/PasswordPolicyMixin.js rename to packages/auth/lib/password-policy/PasswordPolicyMixin.ts index e8c916dd3a..db6eeb091d 100644 --- a/packages/auth/lib/password-policy/PasswordPolicyMixin.js +++ b/packages/auth/lib/password-policy/PasswordPolicyMixin.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * diff --git a/packages/auth/lib/password-policy/passwordPolicyApi.js b/packages/auth/lib/password-policy/passwordPolicyApi.ts similarity index 99% rename from packages/auth/lib/password-policy/passwordPolicyApi.js rename to packages/auth/lib/password-policy/passwordPolicyApi.ts index 7d375deae8..77cd2341c5 100644 --- a/packages/auth/lib/password-policy/passwordPolicyApi.js +++ b/packages/auth/lib/password-policy/passwordPolicyApi.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * diff --git a/packages/auth/lib/providers/AppleAuthProvider.js b/packages/auth/lib/providers/AppleAuthProvider.ts similarity index 98% rename from packages/auth/lib/providers/AppleAuthProvider.js rename to packages/auth/lib/providers/AppleAuthProvider.ts index 172cc1d12e..d0d1fc5fa2 100644 --- a/packages/auth/lib/providers/AppleAuthProvider.js +++ b/packages/auth/lib/providers/AppleAuthProvider.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * diff --git a/packages/auth/lib/providers/EmailAuthProvider.js b/packages/auth/lib/providers/EmailAuthProvider.ts similarity index 98% rename from packages/auth/lib/providers/EmailAuthProvider.js rename to packages/auth/lib/providers/EmailAuthProvider.ts index b722a7d29b..e69dd0ff2b 100644 --- a/packages/auth/lib/providers/EmailAuthProvider.js +++ b/packages/auth/lib/providers/EmailAuthProvider.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * diff --git a/packages/auth/lib/providers/FacebookAuthProvider.js b/packages/auth/lib/providers/FacebookAuthProvider.ts similarity index 98% rename from packages/auth/lib/providers/FacebookAuthProvider.js rename to packages/auth/lib/providers/FacebookAuthProvider.ts index 50ae4d9bd5..ab73c1c5c7 100644 --- a/packages/auth/lib/providers/FacebookAuthProvider.js +++ b/packages/auth/lib/providers/FacebookAuthProvider.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * diff --git a/packages/auth/lib/providers/GithubAuthProvider.js b/packages/auth/lib/providers/GithubAuthProvider.ts similarity index 98% rename from packages/auth/lib/providers/GithubAuthProvider.js rename to packages/auth/lib/providers/GithubAuthProvider.ts index c0c9c6a253..39e7348655 100644 --- a/packages/auth/lib/providers/GithubAuthProvider.js +++ b/packages/auth/lib/providers/GithubAuthProvider.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * diff --git a/packages/auth/lib/providers/GoogleAuthProvider.js b/packages/auth/lib/providers/GoogleAuthProvider.ts similarity index 98% rename from packages/auth/lib/providers/GoogleAuthProvider.js rename to packages/auth/lib/providers/GoogleAuthProvider.ts index 03cb7b55f0..eb695afc36 100644 --- a/packages/auth/lib/providers/GoogleAuthProvider.js +++ b/packages/auth/lib/providers/GoogleAuthProvider.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * diff --git a/packages/auth/lib/providers/OAuthProvider.js b/packages/auth/lib/providers/OAuthProvider.ts similarity index 99% rename from packages/auth/lib/providers/OAuthProvider.js rename to packages/auth/lib/providers/OAuthProvider.ts index feab7e004f..ce20fd3ccf 100644 --- a/packages/auth/lib/providers/OAuthProvider.js +++ b/packages/auth/lib/providers/OAuthProvider.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * diff --git a/packages/auth/lib/providers/OIDCAuthProvider.js b/packages/auth/lib/providers/OIDCAuthProvider.ts similarity index 98% rename from packages/auth/lib/providers/OIDCAuthProvider.js rename to packages/auth/lib/providers/OIDCAuthProvider.ts index d262a29548..ce1a7eb2aa 100644 --- a/packages/auth/lib/providers/OIDCAuthProvider.js +++ b/packages/auth/lib/providers/OIDCAuthProvider.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * diff --git a/packages/auth/lib/providers/PhoneAuthProvider.js b/packages/auth/lib/providers/PhoneAuthProvider.ts similarity index 99% rename from packages/auth/lib/providers/PhoneAuthProvider.js rename to packages/auth/lib/providers/PhoneAuthProvider.ts index 2fb238049c..2c4963a1aa 100644 --- a/packages/auth/lib/providers/PhoneAuthProvider.js +++ b/packages/auth/lib/providers/PhoneAuthProvider.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* eslint-disable @typescript-eslint/no-unused-vars */ /* * Copyright (c) 2016-present Invertase Limited & Contributors diff --git a/packages/auth/lib/providers/TwitterAuthProvider.js b/packages/auth/lib/providers/TwitterAuthProvider.ts similarity index 98% rename from packages/auth/lib/providers/TwitterAuthProvider.js rename to packages/auth/lib/providers/TwitterAuthProvider.ts index 62150cc2a7..a1b80de931 100644 --- a/packages/auth/lib/providers/TwitterAuthProvider.js +++ b/packages/auth/lib/providers/TwitterAuthProvider.ts @@ -1,3 +1,4 @@ +// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * diff --git a/packages/auth/lib/web/RNFBAuthModule.android.js b/packages/auth/lib/web/RNFBAuthModule.android.ts similarity index 73% rename from packages/auth/lib/web/RNFBAuthModule.android.js rename to packages/auth/lib/web/RNFBAuthModule.android.ts index af77c859b1..56a9885699 100644 --- a/packages/auth/lib/web/RNFBAuthModule.android.js +++ b/packages/auth/lib/web/RNFBAuthModule.android.ts @@ -1,2 +1,3 @@ +// @ts-nocheck // No-op for android. export default {}; diff --git a/packages/auth/lib/web/RNFBAuthModule.ios.js b/packages/auth/lib/web/RNFBAuthModule.ios.ts similarity index 71% rename from packages/auth/lib/web/RNFBAuthModule.ios.js rename to packages/auth/lib/web/RNFBAuthModule.ios.ts index a3429ada0e..93d22181a4 100644 --- a/packages/auth/lib/web/RNFBAuthModule.ios.js +++ b/packages/auth/lib/web/RNFBAuthModule.ios.ts @@ -1,2 +1,3 @@ +// @ts-nocheck // No-op for ios. export default {}; diff --git a/packages/auth/lib/web/RNFBAuthModule.js b/packages/auth/lib/web/RNFBAuthModule.ts similarity index 99% rename from packages/auth/lib/web/RNFBAuthModule.js rename to packages/auth/lib/web/RNFBAuthModule.ts index f5b02d9c48..2774b3976e 100644 --- a/packages/auth/lib/web/RNFBAuthModule.js +++ b/packages/auth/lib/web/RNFBAuthModule.ts @@ -1,3 +1,4 @@ +// @ts-nocheck import { Platform } from 'react-native'; import { getApp, diff --git a/packages/auth/package.json b/packages/auth/package.json index bbbdd7883d..8cd03a7c8a 100644 --- a/packages/auth/package.json +++ b/packages/auth/package.json @@ -3,14 +3,15 @@ "version": "24.0.0", "author": "Invertase (http://invertase.io)", "description": "React Native Firebase - The authentication module provides an easy-to-use API to integrate an authentication workflow into new and existing applications. React Native Firebase provides access to all Firebase authentication methods and identity providers.", - "main": "lib/index.js", - "types": "lib/index.d.ts", + "main": "./dist/module/index.js", + "types": "./dist/typescript/lib/index.d.ts", "scripts": { - "build": "genversion --semi lib/version.js", + "build": "genversion --esm --semi lib/version.ts", "build:clean": "rimraf android/build && rimraf ios/build", "build:plugin": "rimraf plugin/build && tsc --build plugin", + "compile": "bob build", "lint:plugin": "eslint plugin/src/*", - "prepare": "yarn run build && yarn run build:plugin" + "prepare": "yarn run build && yarn compile && yarn run build:plugin" }, "repository": { "type": "git", @@ -32,7 +33,8 @@ }, "devDependencies": { "@types/plist": "^3.0.5", - "expo": "^55.0.5" + "expo": "^55.0.5", + "react-native-builder-bob": "^0.40.13" }, "peerDependenciesMeta": { "expo": { @@ -42,5 +44,35 @@ "publishConfig": { "access": "public", "provenance": true - } + }, + "exports": { + ".": { + "source": "./lib/index.ts", + "types": "./dist/typescript/lib/index.d.ts", + "default": "./dist/module/index.js" + }, + "./package.json": "./package.json" + }, + "react-native-builder-bob": { + "source": "lib", + "output": "dist", + "targets": [ + [ + "module", + { + "esm": true + } + ], + [ + "typescript", + { + "tsc": "../../node_modules/.bin/tsc" + } + ] + ] + }, + "eslintIgnore": [ + "node_modules/", + "dist/" + ] } diff --git a/packages/auth/tsconfig.json b/packages/auth/tsconfig.json new file mode 100644 index 0000000000..e74ce68d3a --- /dev/null +++ b/packages/auth/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "../../tsconfig.packages.base.json", + "compilerOptions": { + "baseUrl": ".", + "rootDir": ".", + "paths": { + "@react-native-firebase/app/dist/module/common/*": ["../app/dist/typescript/lib/common/*"], + "@react-native-firebase/app/dist/module/common": ["../app/dist/typescript/lib/common"], + "@react-native-firebase/app/dist/module/internal/*": [ + "../app/dist/typescript/lib/internal/*" + ], + "@react-native-firebase/app/dist/module/internal": ["../app/dist/typescript/lib/internal"], + "@react-native-firebase/app": ["../app/dist/typescript/lib"] + } + }, + "include": ["lib/**/*"], + "exclude": ["node_modules", "dist", "__tests__", "**/*.test.ts"] +} diff --git a/yarn.lock b/yarn.lock index 68e0650b90..71385899d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6210,6 +6210,7 @@ __metadata: "@types/plist": "npm:^3.0.5" expo: "npm:^55.0.5" plist: "npm:^3.1.0" + react-native-builder-bob: "npm:^0.40.13" peerDependencies: "@react-native-firebase/app": 24.0.0 expo: ">=47.0.0" From f7e3edbb7705471fbeeb278d90793e757567959a Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Tue, 21 Apr 2026 10:21:38 +0100 Subject: [PATCH 02/45] refactor(auth): split modular and namespaced TypeScript surfaces --- packages/auth/lib/User.ts | 2 +- packages/auth/lib/index.ts | 605 +------ packages/auth/lib/modular.ts | 652 +++++++ packages/auth/lib/modular/index.ts | 653 +------ packages/auth/lib/namespaced.ts | 571 ++++++ packages/auth/lib/types/auth.ts | 89 + packages/auth/lib/types/internal.ts | 23 + packages/auth/lib/types/namespaced.ts | 2351 +++++++++++++++++++++++++ 8 files changed, 3737 insertions(+), 1209 deletions(-) create mode 100644 packages/auth/lib/modular.ts create mode 100644 packages/auth/lib/namespaced.ts create mode 100644 packages/auth/lib/types/auth.ts create mode 100644 packages/auth/lib/types/internal.ts create mode 100644 packages/auth/lib/types/namespaced.ts diff --git a/packages/auth/lib/User.ts b/packages/auth/lib/User.ts index 7bfdfc4ca5..fc3604d2d9 100644 --- a/packages/auth/lib/User.ts +++ b/packages/auth/lib/User.ts @@ -84,7 +84,7 @@ export default class User { delete() { return this._auth.native.delete().then(() => { - this._auth._setUser(); + this._auth._setUser(null); }); } diff --git a/packages/auth/lib/index.ts b/packages/auth/lib/index.ts index e1d88163cf..a7a0a0006f 100644 --- a/packages/auth/lib/index.ts +++ b/packages/auth/lib/index.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -16,558 +15,52 @@ * */ -import { - createDeprecationProxy, - isAndroid, - isBoolean, - isNull, - isOther, - isString, - isValidUrl, - parseListenerOrObserver, -} from '@react-native-firebase/app/dist/module/common'; -import { setReactNativeModule } from '@react-native-firebase/app/dist/module/internal/nativeModule'; -import { - FirebaseModule, - createModuleNamespace, - getFirebaseRoot, -} from '@react-native-firebase/app/dist/module/internal'; -import ConfirmationResult from './ConfirmationResult'; -import PhoneAuthListener from './PhoneAuthListener'; -import PhoneMultiFactorGenerator from './PhoneMultiFactorGenerator'; -import TotpMultiFactorGenerator from './TotpMultiFactorGenerator'; -import Settings from './Settings'; -import User from './User'; -import { getMultiFactorResolver } from './getMultiFactorResolver'; -import { MultiFactorUser, multiFactor } from './multiFactor'; -import AppleAuthProvider from './providers/AppleAuthProvider'; -import EmailAuthProvider from './providers/EmailAuthProvider'; -import FacebookAuthProvider from './providers/FacebookAuthProvider'; -import GithubAuthProvider from './providers/GithubAuthProvider'; -import GoogleAuthProvider from './providers/GoogleAuthProvider'; -import OAuthProvider from './providers/OAuthProvider'; -import OIDCAuthProvider from './providers/OIDCAuthProvider'; -import PhoneAuthProvider from './providers/PhoneAuthProvider'; -import TwitterAuthProvider from './providers/TwitterAuthProvider'; -import { TotpSecret } from './TotpSecret'; -import { version } from './version'; -import fallBackModule from './web/RNFBAuthModule'; -import { PasswordPolicyMixin } from './password-policy/PasswordPolicyMixin'; - -const PhoneAuthState = { - CODE_SENT: 'sent', - AUTO_VERIFY_TIMEOUT: 'timeout', - AUTO_VERIFIED: 'verified', - ERROR: 'error', -}; - -export { - AppleAuthProvider, - EmailAuthProvider, - PhoneAuthProvider, - GoogleAuthProvider, - GithubAuthProvider, - TwitterAuthProvider, - FacebookAuthProvider, - PhoneMultiFactorGenerator, - TotpMultiFactorGenerator, - TotpSecret, - OAuthProvider, - OIDCAuthProvider, - PhoneAuthState, -}; - -const statics = { - AppleAuthProvider, - EmailAuthProvider, - PhoneAuthProvider, - GoogleAuthProvider, - GithubAuthProvider, - TwitterAuthProvider, - FacebookAuthProvider, - PhoneMultiFactorGenerator, - TotpMultiFactorGenerator, - OAuthProvider, - OIDCAuthProvider, - PhoneAuthState, - getMultiFactorResolver, - multiFactor, -}; - -const namespace = 'auth'; -const nativeModuleName = 'RNFBAuthModule'; - -class FirebaseAuthModule extends FirebaseModule { - constructor(...args) { - super(...args); - this._user = null; - this._settings = null; - this._authResult = false; - this._languageCode = this.native.APP_LANGUAGE[this.app._name]; - this._tenantId = null; - this._projectPasswordPolicy = null; - this._tenantPasswordPolicies = {}; - - if (!this.languageCode) { - this._languageCode = this.native.APP_LANGUAGE['[DEFAULT]']; - } - - if (this.native.APP_USER[this.app._name]) { - this._setUser(this.native.APP_USER[this.app._name]); - } - - this.emitter.addListener(this.eventNameForApp('auth_state_changed'), event => { - this._setUser(event.user); - this.emitter.emit(this.eventNameForApp('onAuthStateChanged'), this._user); - }); - - this.emitter.addListener(this.eventNameForApp('phone_auth_state_changed'), event => { - const eventKey = `phone:auth:${event.requestKey}:${event.type}`; - this.emitter.emit(eventKey, event.state); - }); - - this.emitter.addListener(this.eventNameForApp('auth_id_token_changed'), auth => { - this._setUser(auth.user); - this.emitter.emit(this.eventNameForApp('onIdTokenChanged'), this._user); - }); - - this.native.addAuthStateListener(); - this.native.addIdTokenListener(); - - // custom authDomain in only available from App's FirebaseOptions, - // but we need it in Auth if it exists. During app configuration we store - // mappings from app name to authDomain, this auth constructor - // is a reasonable time to use the mapping and set it into auth natively - if (!isOther) { - // Only supported on native platforms - this.native.configureAuthDomain(); - } - } - - get languageCode() { - return this._languageCode; - } - - set languageCode(code) { - // For modular API, not recommended to set languageCode directly as it should be set in the native SDKs first - if (!isString(code) && !isNull(code)) { - throw new Error( - "firebase.auth().languageCode = (*) expected 'languageCode' to be a string or null value", - ); - } - // as this is a setter, we can't use async/await. So we set it first so it is available immediately - if (code === null) { - this._languageCode = this.native.APP_LANGUAGE[this.app._name]; - - if (!this.languageCode) { - this._languageCode = this.native.APP_LANGUAGE['[DEFAULT]']; - } - } else { - this._languageCode = code; - } - // This sets it natively - this.setLanguageCode(code); - } - - get config() { - // for modular API, firebase JS SDK has a config object which is not available in native SDKs - return {}; - } - - get tenantId() { - return this._tenantId; - } - - get settings() { - if (!this._settings) { - this._settings = new Settings(this); - } - return this._settings; - } - - get currentUser() { - return this._user; - } - - _setUser(user) { - this._user = user ? createDeprecationProxy(new User(this, user)) : null; - this._authResult = true; - this.emitter.emit(this.eventNameForApp('onUserChanged'), this._user); - return this._user; - } - - _setUserCredential(userCredential) { - const user = createDeprecationProxy(new User(this, userCredential.user)); - this._user = user; - this._authResult = true; - this.emitter.emit(this.eventNameForApp('onUserChanged'), this._user); - return { - additionalUserInfo: userCredential.additionalUserInfo, - user, - }; - } - - async setLanguageCode(code) { - if (!isString(code) && !isNull(code)) { - throw new Error( - "firebase.auth().setLanguageCode(*) expected 'languageCode' to be a string or null value", - ); - } - - await this.native.setLanguageCode(code); - - if (code === null) { - this._languageCode = this.native.APP_LANGUAGE[this.app._name]; - - if (!this.languageCode) { - this._languageCode = this.native.APP_LANGUAGE['[DEFAULT]']; - } - } else { - this._languageCode = code; - } - } - - async setTenantId(tenantId) { - if (!isString(tenantId)) { - throw new Error("firebase.auth().setTenantId(*) expected 'tenantId' to be a string"); - } - this._tenantId = tenantId; - await this.native.setTenantId(tenantId); - } - - onAuthStateChanged(listenerOrObserver) { - const listener = parseListenerOrObserver(listenerOrObserver); - const subscription = this.emitter.addListener( - this.eventNameForApp('onAuthStateChanged'), - listener, - ); - - if (this._authResult) { - Promise.resolve().then(() => { - listener(this._user || null); - }); - } - return () => subscription.remove(); - } - - onIdTokenChanged(listenerOrObserver) { - const listener = parseListenerOrObserver(listenerOrObserver); - const subscription = this.emitter.addListener( - this.eventNameForApp('onIdTokenChanged'), - listener, - ); - - if (this._authResult) { - Promise.resolve().then(() => { - listener(this._user || null); - }); - } - return () => subscription.remove(); - } - - onUserChanged(listenerOrObserver) { - const listener = parseListenerOrObserver(listenerOrObserver); - const subscription = this.emitter.addListener(this.eventNameForApp('onUserChanged'), listener); - if (this._authResult) { - Promise.resolve().then(() => { - listener(this._user || null); - }); - } - - return () => { - subscription.remove(); - }; - } - - signOut() { - return this.native.signOut().then(() => { - this._setUser(); - }); - } - - signInAnonymously() { - return this.native - .signInAnonymously() - .then(userCredential => this._setUserCredential(userCredential)); - } - - signInWithPhoneNumber(phoneNumber, forceResend) { - if (isAndroid) { - return this.native - .signInWithPhoneNumber(phoneNumber, forceResend || false) - .then(result => new ConfirmationResult(this, result.verificationId)); - } - - return this.native - .signInWithPhoneNumber(phoneNumber) - .then(result => new ConfirmationResult(this, result.verificationId)); - } - - verifyPhoneNumber(phoneNumber, autoVerifyTimeoutOrForceResend, forceResend) { - let _forceResend = forceResend; - let _autoVerifyTimeout = 60; - - if (isBoolean(autoVerifyTimeoutOrForceResend)) { - _forceResend = autoVerifyTimeoutOrForceResend; - } else { - _autoVerifyTimeout = autoVerifyTimeoutOrForceResend; - } - - return new PhoneAuthListener(this, phoneNumber, _autoVerifyTimeout, _forceResend); - } - - verifyPhoneNumberWithMultiFactorInfo(multiFactorHint, session) { - return this.native.verifyPhoneNumberWithMultiFactorInfo(multiFactorHint.uid, session); - } - - verifyPhoneNumberForMultiFactor(phoneInfoOptions) { - const { phoneNumber, session } = phoneInfoOptions; - return this.native.verifyPhoneNumberForMultiFactor(phoneNumber, session); - } - - resolveMultiFactorSignIn(session, verificationId, verificationCode) { - return this.native - .resolveMultiFactorSignIn(session, verificationId, verificationCode) - .then(userCredential => { - return this._setUserCredential(userCredential); - }); - } - - resolveTotpSignIn(session, uid, totpSecret) { - return this.native.resolveTotpSignIn(session, uid, totpSecret).then(userCredential => { - return this._setUserCredential(userCredential); - }); - } - - createUserWithEmailAndPassword(email, password) { - return ( - this.native - .createUserWithEmailAndPassword(email, password) - .then(userCredential => this._setUserCredential(userCredential)) - /* istanbul ignore next - native error handling cannot be unit tested */ - .catch(error => { - if (error.code === 'auth/password-does-not-meet-requirements') { - return this._recachePasswordPolicy() - .catch(() => { - // Silently ignore recache failures - the original error matters more - }) - .then(() => { - throw error; - }); - } - throw error; - }) - ); - } - - signInWithEmailAndPassword(email, password) { - return ( - this.native - .signInWithEmailAndPassword(email, password) - .then(userCredential => this._setUserCredential(userCredential)) - /* istanbul ignore next - native error handling cannot be unit tested */ - .catch(error => { - if (error.code === 'auth/password-does-not-meet-requirements') { - return this._recachePasswordPolicy() - .catch(() => { - // Silently ignore recache failures - the original error matters more - }) - .then(() => { - throw error; - }); - } - throw error; - }) - ); - } - - signInWithCustomToken(customToken) { - return this.native - .signInWithCustomToken(customToken) - .then(userCredential => this._setUserCredential(userCredential)); - } - - signInWithCredential(credential) { - return this.native - .signInWithCredential(credential.providerId, credential.token, credential.secret) - .then(userCredential => this._setUserCredential(userCredential)); - } - - revokeToken(authorizationCode) { - return this.native.revokeToken(authorizationCode); - } - - sendPasswordResetEmail(email, actionCodeSettings = null) { - return this.native.sendPasswordResetEmail(email, actionCodeSettings); - } - - sendSignInLinkToEmail(email, actionCodeSettings = {}) { - return this.native.sendSignInLinkToEmail(email, actionCodeSettings); - } - - isSignInWithEmailLink(emailLink) { - return this.native.isSignInWithEmailLink(emailLink); - } - - signInWithEmailLink(email, emailLink) { - return this.native - .signInWithEmailLink(email, emailLink) - .then(userCredential => this._setUserCredential(userCredential)); - } - - confirmPasswordReset(code, newPassword) { - return ( - this.native - .confirmPasswordReset(code, newPassword) - /* istanbul ignore next - native error handling cannot be unit tested */ - .catch(error => { - if (error.code === 'auth/password-does-not-meet-requirements') { - return this._recachePasswordPolicy() - .catch(() => { - // Silently ignore recache failures - the original error matters more - }) - .then(() => { - throw error; - }); - } - throw error; - }) - ); - } - - applyActionCode(code) { - return this.native.applyActionCode(code).then(user => { - this._setUser(user); - }); - } - - checkActionCode(code) { - return this.native.checkActionCode(code); - } - - fetchSignInMethodsForEmail(email) { - return this.native.fetchSignInMethodsForEmail(email); - } - - verifyPasswordResetCode(code) { - return this.native.verifyPasswordResetCode(code); - } - - useUserAccessGroup(userAccessGroup) { - if (isAndroid) { - return Promise.resolve(); - } - return this.native.useUserAccessGroup(userAccessGroup); - } - - getRedirectResult() { - throw new Error( - 'firebase.auth().getRedirectResult() is unsupported by the native Firebase SDKs.', - ); - } - - setPersistence() { - throw new Error('firebase.auth().setPersistence() is unsupported by the native Firebase SDKs.'); - } - - signInWithPopup(provider) { - return this.native - .signInWithProvider(provider.toObject()) - .then(userCredential => this._setUserCredential(userCredential)); - } - - signInWithRedirect(provider) { - return this.native - .signInWithProvider(provider.toObject()) - .then(userCredential => this._setUserCredential(userCredential)); - } - - // firebase issue - https://github.com/invertase/react-native-firebase/pull/655#issuecomment-349904680 - useDeviceLanguage() { - throw new Error( - 'firebase.auth().useDeviceLanguage() is unsupported by the native Firebase SDKs.', - ); - } - - useEmulator(url) { - if (!url || !isString(url) || !isValidUrl(url)) { - throw new Error('firebase.auth().useEmulator() takes a non-empty string URL'); - } - - let _url = url; - const androidBypassEmulatorUrlRemap = - typeof this.firebaseJson.android_bypass_emulator_url_remap === 'boolean' && - this.firebaseJson.android_bypass_emulator_url_remap; - if (!androidBypassEmulatorUrlRemap && isAndroid && _url) { - if (_url.startsWith('http://localhost')) { - _url = _url.replace('http://localhost', 'http://10.0.2.2'); - // eslint-disable-next-line no-console - console.log( - 'Mapping auth host "localhost" to "10.0.2.2" for android emulators. Use real IP on real devices. You can bypass this behaviour with "android_bypass_emulator_url_remap" flag.', - ); - } - if (_url.startsWith('http://127.0.0.1')) { - _url = _url.replace('http://127.0.0.1', 'http://10.0.2.2'); - // eslint-disable-next-line no-console - console.log( - 'Mapping auth host "127.0.0.1" to "10.0.2.2" for android emulators. Use real IP on real devices. You can bypass this behaviour with "android_bypass_emulator_url_remap" flag.', - ); - } - } - - // Native calls take the host and port split out - const hostPortRegex = /^http:\/\/([\w\d-.]+):(\d+)$/; - const urlMatches = _url.match(hostPortRegex); - if (!urlMatches) { - throw new Error('firebase.auth().useEmulator() unable to parse host and port from URL'); - } - const host = urlMatches[1]; - const port = parseInt(urlMatches[2], 10); - this.native.useEmulator(host, port); - return [host, port]; // undocumented return, useful for unit testing - } - - getMultiFactorResolver(error) { - return getMultiFactorResolver(this, error); - } - - multiFactor(user) { - if (user.userId !== this.currentUser.userId) { - throw new Error('firebase.auth().multiFactor() only operates on currentUser'); - } - return new MultiFactorUser(this, user); - } - - getCustomAuthDomain() { - return this.native.getCustomAuthDomain(); - } -} - -// Apply password policy mixin to FirebaseAuthModule -Object.assign(FirebaseAuthModule.prototype, PasswordPolicyMixin); - -// import { SDK_VERSION } from '@react-native-firebase/auth'; -export const SDK_VERSION = version; - -// import auth from '@react-native-firebase/auth'; -// auth().X(...); -export default createModuleNamespace({ - statics, - version, - namespace, - nativeModuleName, - nativeEvents: ['auth_state_changed', 'auth_id_token_changed', 'phone_auth_state_changed'], - hasMultiAppSupport: true, - hasCustomUrlOrRegionSupport: false, - ModuleClass: FirebaseAuthModule, -}); - -export * from './modular/index'; - -// import auth, { firebase } from '@react-native-firebase/auth'; -// auth().X(...); -// firebase.auth().X(...); -export const firebase = getFirebaseRoot(); - -// Register the interop module for non-native platforms. -setReactNativeModule(nativeModuleName, fallBackModule); +export type { + ActionCodeInfo, + ActionCodeInfoData, + ActionCodeSettings, + ActionCodeSettingsAndroid, + ActionCodeSettingsIos, + ActionCodeURL, + AdditionalUserInfo, + ApplicationVerifier, + Auth, + AuthCredential, + AuthListenerCallback, + AuthProvider, + AuthSettings, + ConfirmationResult, + FactorId, + FirebaseApp, + IdTokenResult, + MultiFactor, + MultiFactorAssertion, + MultiFactorError, + MultiFactorInfo, + MultiFactorInfoCommon, + MultiFactorResolver, + MultiFactorSession, + MultiFactorUser, + NativeFirebaseAuthError, + OIDCProvider, + PasswordPolicy, + PasswordValidationStatus, + Persistence, + PhoneAuthError, + PhoneAuthListener, + PhoneAuthSnapshot, + PhoneMultiFactorEnrollInfoOptions, + PhoneMultiFactorInfo, + PhoneMultiFactorSignInInfoOptions, + PopupRedirectResolver, + TotpMultiFactorInfo, + UpdateProfile, + User, + UserCredential, + UserInfo, + UserMetadata, +} from './types/auth'; +export * from './types/namespaced'; +export * from './modular'; +export * from './namespaced'; +export { default } from './namespaced'; diff --git a/packages/auth/lib/modular.ts b/packages/auth/lib/modular.ts new file mode 100644 index 0000000000..acd09c1cd6 --- /dev/null +++ b/packages/auth/lib/modular.ts @@ -0,0 +1,652 @@ +// @ts-nocheck +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library 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 { getApp } from '@react-native-firebase/app'; +import { MultiFactorUser } from './multiFactor'; +import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/dist/module/common'; + +/** + * @typedef {import('@firebase/app-types').FirebaseApp} FirebaseApp + * @typedef {import('..').FirebaseAuthTypes} FirebaseAuthTypes + * @typedef {import('..').FirebaseAuthTypes.Module} Auth + * @typedef {import('..').FirebaseAuthTypes.CallbackOrObserver} CallbackOrObserver + * @typedef {import('..').FirebaseAuthTypes.AuthListenerCallback} AuthListenerCallback + * @typedef {import('..').FirebaseAuthTypes.ActionCodeInfo} ActionCodeInfo + * @typedef {import('..').FirebaseAuthTypes.UserCredential} UserCredential + * @typedef {import('..').FirebaseAuthTypes.MultiFactorError} MultiFactorError + * @typedef {import('..').FirebaseAuthTypes.MultiFactorUser} MultiFactorUser + * @typedef {import('..').FirebaseAuthTypes.MultiFactorResolver} MultiFactorResolver + * @typedef {import('..').FirebaseAuthTypes.ConfirmationResult} ConfirmationResult + * @typedef {import('..').FirebaseAuthTypes.AuthCredential} AuthCredential + * @typedef {import('..').FirebaseAuthTypes.AuthProvider} AuthProvider + * @typedef {import('..').FirebaseAuthTypes.PhoneAuthListener} PhoneAuthListener + * @typedef {import('..').FirebaseAuthTypes.ActionCodeSettings} ActionCodeSettings + * @typedef {import('..').FirebaseAuthTypes.User} User + * @typedef {import('..').FirebaseAuthTypes.IdTokenResult} IdTokenResult + * @typedef {import('..').FirebaseAuthTypes.AdditionalUserInfo} AdditionalUserInfo + * @typedef {import('..').FirebaseAuthTypes.ActionCodeURL} ActionCodeURL + * @typedef {import('..').FirebaseAuthTypes.ApplicationVerifier} ApplicationVerifier + */ + +/** + * Returns the Auth instance associated with the provided FirebaseApp. + * @param {FirebaseApp} [app] - The Firebase app instance. + * @returns {Auth} + */ +export function getAuth(app) { + if (app) { + return getApp(app.name).auth(); + } + return getApp().auth(); +} + +/** + * This function allows more control over the Auth instance than getAuth(). + * @param {FirebaseApp} app - The Firebase app instance. + * @param {any} [deps] - Optional. Dependencies for the Auth instance. + * @returns {Auth} + */ +export function initializeAuth(app, deps) { + if (app) { + return getApp(app.name).auth(); + } + return getApp().auth(); +} + +/** + * Applies a verification code sent to the user by email or other out-of-band mechanism. + * @param {Auth} auth - The Auth instance. + * @param {string} oobCode - The out-of-band code sent to the user. + * @returns {Promise} + */ +export async function applyActionCode(auth, oobCode) { + return auth.applyActionCode.call(auth, oobCode, MODULAR_DEPRECATION_ARG); +} + +/** + * Adds a blocking callback that runs before an auth state change sets a new user. + * @param {Auth} auth - The Auth instance. + * @param {(user: User | null) => void} callback - A callback function to run before the auth state changes. + * @param {() => void} [onAbort] - Optional. A callback function to run if the operation is aborted. + */ +export function beforeAuthStateChanged(auth, callback, onAbort) { + throw new Error('beforeAuthStateChanged is unsupported by the native Firebase SDKs'); +} + +/** + * Checks a verification code sent to the user by email or other out-of-band mechanism. + * @param {Auth} auth - The Auth instance. + * @param {string} oobCode - The out-of-band code sent to the user. + * @returns {Promise} + */ +export async function checkActionCode(auth, oobCode) { + return auth.checkActionCode.call(auth, oobCode, MODULAR_DEPRECATION_ARG); +} + +/** + * Completes the password reset process, given a confirmation code and new password. + * @param {Auth} auth - The Auth instance. + * @param {string} oobCode - The out-of-band code sent to the user. + * @param {string} newPassword - The new password. + * @returns {Promise} + */ +export async function confirmPasswordReset(auth, oobCode, newPassword) { + return auth.confirmPasswordReset.call(auth, oobCode, newPassword, MODULAR_DEPRECATION_ARG); +} + +/** + * Changes the Auth instance to communicate with the Firebase Auth Emulator, instead of production Firebase Auth services. + * @param {Auth} auth - The Auth instance. + * @param {string} url - The URL of the Firebase Auth Emulator. + * @param {{ disableWarnings: boolean }} [options] - Optional. Options for the emulator connection. + */ +export function connectAuthEmulator(auth, url, options) { + auth.useEmulator.call(auth, url, options, MODULAR_DEPRECATION_ARG); +} + +/** + * Creates a new user account associated with the specified email address and password. + * @param {Auth} auth - The Auth instance. + * @param {string} email - The user's email address. + * @param {string} password - The user's password. + * @returns {Promise} + */ +export async function createUserWithEmailAndPassword(auth, email, password) { + return auth.createUserWithEmailAndPassword.call(auth, email, password, MODULAR_DEPRECATION_ARG); +} + +/** + * Gets the list of possible sign in methods for the given email address. + * @param {Auth} auth - The Auth instance. + * @param {string} email - The user's email address. + * @returns {Promise} + */ +export async function fetchSignInMethodsForEmail(auth, email) { + return auth.fetchSignInMethodsForEmail.call(auth, email, MODULAR_DEPRECATION_ARG); +} + +/** + * Provides a MultiFactorResolver suitable for completion of a multi-factor flow. + * @param {Auth} auth - The Auth instance. + * @param {MultiFactorError} error - The multi-factor error. + * @returns {MultiFactorResolver} + */ +export function getMultiFactorResolver(auth, error) { + return auth.getMultiFactorResolver.call(auth, error, MODULAR_DEPRECATION_ARG); +} + +/** + * Returns a UserCredential from the redirect-based sign-in flow. + * @param {Auth} auth - The Auth instance. + * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. + * @returns {Promise} + */ +export async function getRedirectResult(auth, resolver) { + throw new Error('getRedirectResult is unsupported by the native Firebase SDKs'); +} + +/** + * Checks if an incoming link is a sign-in with email link suitable for signInWithEmailLink(). + * @param {Auth} auth - The Auth instance. + * @param {string} emailLink - The email link to check. + * @returns {Promise} + */ +export function isSignInWithEmailLink(auth, emailLink) { + return auth.isSignInWithEmailLink.call(auth, emailLink, MODULAR_DEPRECATION_ARG); +} + +/** + * Adds an observer for changes to the user's sign-in state. + * @param {Auth} auth - The Auth instance. + * @param {CallbackOrObserver} nextOrObserver - A callback function or observer for auth state changes. + * @returns {() => void} + */ +export function onAuthStateChanged(auth, nextOrObserver) { + return auth.onAuthStateChanged.call(auth, nextOrObserver, MODULAR_DEPRECATION_ARG); +} + +/** + * Adds an observer for changes to the signed-in user's ID token. + * @param {Auth} auth - The Auth instance. + * @param {CallbackOrObserver} nextOrObserver - A callback function or observer for ID token changes. + * @returns {() => void} + */ +export function onIdTokenChanged(auth, nextOrObserver) { + return auth.onIdTokenChanged.call(auth, nextOrObserver, MODULAR_DEPRECATION_ARG); +} + +/** + * Revoke the given access token, Currently only supports Apple OAuth access tokens. + * @param auth - The Auth Instance. + * @param token - The Access Token + */ +export async function revokeAccessToken(auth, token) { + throw new Error('revokeAccessToken() is only supported on Web'); +} //TO DO: Add Support + +/** + * Sends a password reset email to the given email address. + * @param {Auth} auth - The Auth instance. + * @param {string} email - The user's email address. + * @param {ActionCodeSettings} [actionCodeSettings] - Optional. Action code settings. + * @returns {Promise} + */ +export async function sendPasswordResetEmail(auth, email, actionCodeSettings) { + return auth.sendPasswordResetEmail.call(auth, email, actionCodeSettings, MODULAR_DEPRECATION_ARG); +} + +/** + * Sends a sign-in email link to the user with the specified email. + * @param {Auth} auth - The Auth instance. + * @param {string} email - The user's email address. + * @param {ActionCodeSettings} [actionCodeSettings] - Optional. Action code settings. + * @returns {Promise} + */ +export async function sendSignInLinkToEmail(auth, email, actionCodeSettings) { + return auth.sendSignInLinkToEmail.call(auth, email, actionCodeSettings, MODULAR_DEPRECATION_ARG); +} + +/** + * Changes the type of persistence on the Auth instance for the currently saved Auth session and applies this type of persistence for future sign-in requests, including sign-in with redirect requests. + * @param {Auth} auth - The Auth instance. + * @param {Persistence} persistence - The persistence type. + * @returns {Promise} + */ +export async function setPersistence(auth, persistence) { + throw new Error('setPersistence is unsupported by the native Firebase SDKs'); +} + +/** + * Asynchronously signs in as an anonymous user. + * @param {Auth} auth - The Auth instance. + * @returns {Promise} + */ +export async function signInAnonymously(auth) { + return auth.signInAnonymously.call(auth, MODULAR_DEPRECATION_ARG); +} + +/** + * Asynchronously signs in with the given credentials. + * @param {Auth} auth - The Auth instance. + * @param {AuthCredential} credential - The auth credentials. + * @returns {Promise} + */ +export async function signInWithCredential(auth, credential) { + return auth.signInWithCredential.call(auth, credential, MODULAR_DEPRECATION_ARG); +} + +/** + * Asynchronously signs in using a custom token. + * @param {Auth} auth - The Auth instance. + * @param {string} customToken - The custom token. + * @returns {Promise} + */ +export async function signInWithCustomToken(auth, customToken) { + return auth.signInWithCustomToken.call(auth, customToken, MODULAR_DEPRECATION_ARG); +} + +/** + * Asynchronously signs in using an email and password. + * @param {Auth} auth - The Auth instance. + * @param {string} email - The user's email address. + * @param {string} password - The user's password. + * @returns {Promise} + */ +export async function signInWithEmailAndPassword(auth, email, password) { + return auth.signInWithEmailAndPassword.call(auth, email, password, MODULAR_DEPRECATION_ARG); +} + +/** + * Asynchronously signs in using an email and sign-in email link. + * @param {Auth} auth - The Auth instance. + * @param {string} email - The user's email address. + * @param {string} emailLink - The email link. + * @returns {Promise} + */ +export async function signInWithEmailLink(auth, email, emailLink) { + return auth.signInWithEmailLink.call(auth, email, emailLink, MODULAR_DEPRECATION_ARG); +} + +/** + * Asynchronously signs in using a phone number. + * @param {Auth} auth - The Auth instance. + * @param {string} phoneNumber - The user's phone number. + * @param {ApplicationVerifier} appVerifier - The application verifier. + * @returns {Promise} + */ +export async function signInWithPhoneNumber(auth, phoneNumber, appVerifier) { + return auth.signInWithPhoneNumber.call(auth, phoneNumber, appVerifier, MODULAR_DEPRECATION_ARG); +} + +/** + * Asynchronously verifies a phone number. + * @param {Auth} auth - The Auth instance. + * @param {string} phoneNumber - The user's phone number. + * @param {number | boolean} autoVerifyTimeoutOrForceResend - The auto verify timeout or force resend flag. + * @param {boolean} [forceResend] - Optional. Whether to force resend. + * @returns {PhoneAuthListener} + */ +export function verifyPhoneNumber(auth, phoneNumber, autoVerifyTimeoutOrForceResend, forceResend) { + return auth.verifyPhoneNumber.call( + auth, + phoneNumber, + autoVerifyTimeoutOrForceResend, + forceResend, + MODULAR_DEPRECATION_ARG, + ); +} + +/** + * Authenticates a Firebase client using a popup-based OAuth authentication flow. + * @param {Auth} auth - The Auth instance. + * @param {AuthProvider} provider - The auth provider. + * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. + * @returns {Promise} + */ +export async function signInWithPopup(auth, provider, resolver) { + return auth.signInWithPopup.call(auth, provider, resolver, MODULAR_DEPRECATION_ARG); +} + +/** + * Authenticates a Firebase client using a full-page redirect flow. + * @param {Auth} auth - The Auth instance. + * @param {AuthProvider} provider - The auth provider. + * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. + * @returns {Promise} + */ +export async function signInWithRedirect(auth, provider, resolver) { + return auth.signInWithRedirect.call(auth, provider, resolver, MODULAR_DEPRECATION_ARG); +} + +/** + * Signs out the current user. + * @param {Auth} auth - The Auth instance. + * @returns {Promise} + */ +export async function signOut(auth) { + return auth.signOut.call(auth, MODULAR_DEPRECATION_ARG); +} + +/** + * Asynchronously sets the provided user as Auth.currentUser on the Auth instance. + * @param {Auth} auth - The Auth instance. + * @param {User} user - The user to set as the current user. + * @returns {Promise} + */ +export async function updateCurrentUser(auth, user) { + throw new Error('updateCurrentUser is unsupported by the native Firebase SDKs'); +} + +/** + * Sets the current language to the default device/browser preference. + * @param {Auth} auth - The Auth instance. + */ +export function useDeviceLanguage(auth) { + throw new Error('useDeviceLanguage is unsupported by the native Firebase SDKs'); +} + +/** + * Sets the language code. + * @param {Auth} auth - The Auth instance. + * @param {string} languageCode - The language code. + */ +export function setLanguageCode(auth, languageCode) { + return auth.setLanguageCode.call(auth, languageCode, MODULAR_DEPRECATION_ARG); +} + +/** + * Configures a shared user access group to sync auth state across multiple apps via the Keychain. + * @param {Auth} auth - The Auth instance. + * @param {string} userAccessGroup - The user access group. + * @returns {Promise} + */ +export function useUserAccessGroup(auth, userAccessGroup) { + return auth.useUserAccessGroup.call(auth, userAccessGroup, MODULAR_DEPRECATION_ARG); +} + +/** + * Verifies the password reset code sent to the user by email or other out-of-band mechanism. + * @param {Auth} auth - The Auth instance. + * @param {string} code - The password reset code. + * @returns {Promise} + */ +export async function verifyPasswordResetCode(auth, code) { + return auth.verifyPasswordResetCode.call(auth, code, MODULAR_DEPRECATION_ARG); +} + +/** + * Parses the email action link string and returns an ActionCodeURL if the link is valid, otherwise returns null. + * @param {string} link - The email action link string. + * @returns {ActionCodeURL | null} + */ +export function parseActionCodeURL(link) { + throw new Error('parseActionCodeURL is unsupported by the native Firebase SDKs'); +} + +/** + * Deletes and signs out the user. + * @param {User} user - The user to delete. + * @returns {Promise} + */ +export async function deleteUser(user) { + return user.delete.call(user, MODULAR_DEPRECATION_ARG); +} + +/** + * Returns a JSON Web Token (JWT) used to identify the user to a Firebase service. + * @param {User} user - The user to get the token for. + * @param {boolean} [forceRefresh] - Optional. Whether to force refresh the token. + * @returns {Promise} + */ +export async function getIdToken(user, forceRefresh) { + return user.getIdToken.call(user, forceRefresh, MODULAR_DEPRECATION_ARG); +} + +/** + * Returns a deserialized JSON Web Token (JWT) used to identify the user to a Firebase service. + * @param {User} user - The user to get the token result for. + * @param {boolean} [forceRefresh] - Optional. Whether to force refresh the token. + * @returns {Promise} + */ +export async function getIdTokenResult(user, forceRefresh) { + return user.getIdTokenResult.call(user, forceRefresh, MODULAR_DEPRECATION_ARG); +} + +/** + * Links the user account with the given credentials. + * @param {User} user - The user to link the credentials with. + * @param {AuthCredential} credential - The auth credentials. + * @returns {Promise} + */ +export async function linkWithCredential(user, credential) { + return user.linkWithCredential.call(user, credential, MODULAR_DEPRECATION_ARG); +} + +/** + * Links the user account with the given phone number. + * @param {User} user - The user to link the phone number with. + * @param {string} phoneNumber - The phone number. + * @param {ApplicationVerifier} appVerifier - The application verifier. + * @returns {Promise} + */ +export async function linkWithPhoneNumber(user, phoneNumber, appVerifier) { + throw new Error('linkWithPhoneNumber is unsupported by the native Firebase SDKs'); +} + +/** + * Links the authenticated provider to the user account using a pop-up based OAuth flow. + * @param {User} user - The user to link the provider with. + * @param {AuthProvider} provider - The auth provider. + * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. + * @returns {Promise} + */ +export async function linkWithPopup(user, provider, resolver) { + return user.linkWithPopup.call(user, provider, resolver, MODULAR_DEPRECATION_ARG); +} + +/** + * Links the OAuthProvider to the user account using a full-page redirect flow. + * @param {User} user - The user to link the provider with. + * @param {AuthProvider} provider - The auth provider. + * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. + * @returns {Promise} + */ +export async function linkWithRedirect(user, provider, resolver) { + return user.linkWithRedirect.call(user, provider, resolver, MODULAR_DEPRECATION_ARG); +} + +/** + * The MultiFactorUser corresponding to the user. + * @param {User} user - The user to get the multi-factor user for. + * @returns {MultiFactorUser} + */ +export function multiFactor(user) { + return new MultiFactorUser(user._auth || getAuth(), user); +} + +/** + * Re-authenticates a user using a fresh credential. + * @param {User} user - The user to re-authenticate. + * @param {AuthCredential} credential - The auth credentials. + * @returns {Promise} + */ +export async function reauthenticateWithCredential(user, credential) { + return user.reauthenticateWithCredential.call(user, credential, MODULAR_DEPRECATION_ARG); +} + +/** + * Re-authenticates a user using a fresh phone credential. + * @param {User} user - The user to re-authenticate. + * @param {string} phoneNumber - The phone number. + * @param {ApplicationVerifier} appVerifier - The application verifier. + * @returns {Promise} + */ +export async function reauthenticateWithPhoneNumber(user, phoneNumber, appVerifier) { + throw new Error('reauthenticateWithPhoneNumber is unsupported by the native Firebase SDKs'); +} + +/** + * Re-authenticate a user with a federated authentication provider (Microsoft, Yahoo). For native platforms, this will open a browser window. + * @param {User} user - The user to re-authenticate. + * @param {AuthProvider} provider - The auth provider. + * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. Web only. + * @returns {Promise} + */ +export async function reauthenticateWithPopup(user, provider, resolver) { + return user.reauthenticateWithPopup.call(user, provider, resolver, MODULAR_DEPRECATION_ARG); +} + +/** + * Re-authenticate a user with a federated authentication provider (Microsoft, Yahoo). For native platforms, this will open a browser window. + * @param {User} user - The user to re-authenticate. + * @param {AuthProvider} provider - The auth provider. + * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. Web only. + * @returns {Promise} + */ +export async function reauthenticateWithRedirect(user, provider, resolver) { + return user.reauthenticateWithRedirect.call(user, provider, resolver, MODULAR_DEPRECATION_ARG); +} + +/** + * Reloads user account data, if signed in. + * @param {User} user - The user to reload data for. + * @returns {Promise} + */ +export async function reload(user) { + return user.reload.call(user, MODULAR_DEPRECATION_ARG); +} + +/** + * Sends a verification email to a user. + * @param {User} user - The user to send the email to. + * @param {ActionCodeSettings} [actionCodeSettings] - Optional. Action code settings. + * @returns {Promise} + */ +export async function sendEmailVerification(user, actionCodeSettings) { + return user.sendEmailVerification.call(user, actionCodeSettings, MODULAR_DEPRECATION_ARG); +} + +/** + * Unlinks a provider from a user account. + * @param {User} user - The user to unlink the provider from. + * @param {string} providerId - The provider ID. + * @returns {Promise} + */ +export async function unlink(user, providerId) { + return user.unlink.call(user, providerId, MODULAR_DEPRECATION_ARG); +} + +/** + * Updates the user's email address. + * @param {User} user - The user to update the email for. + * @param {string} newEmail - The new email address. + * @returns {Promise} + */ +export async function updateEmail(user, newEmail) { + return user.updateEmail.call(user, newEmail, MODULAR_DEPRECATION_ARG); +} + +/** + * Updates the user's password. + * @param {User} user - The user to update the password for. + * @param {string} newPassword - The new password. + * @returns {Promise} + */ +export async function updatePassword(user, newPassword) { + return user.updatePassword.call(user, newPassword, MODULAR_DEPRECATION_ARG); +} + +/** + * Updates the user's phone number. + * @param {User} user - The user to update the phone number for. + * @param {AuthCredential} credential - The auth credentials. + * @returns {Promise} + */ +export async function updatePhoneNumber(user, credential) { + return user.updatePhoneNumber.call(user, credential, MODULAR_DEPRECATION_ARG); +} + +/** + * Updates a user's profile data. + * @param {User} user - The user to update the profile for. + * @param {{ displayName?: string | null, photoURL?: string | null }} profile - An object containing the profile data to update. + * @returns {Promise} + */ +export async function updateProfile(user, { displayName, photoURL: photoUrl }) { + return user.updateProfile.call( + user, + { displayName, photoURL: photoUrl }, + MODULAR_DEPRECATION_ARG, + ); +} + +/** + * Sends a verification email to a new email address. + * @param {User} user - The user to send the email to. + * @param {string} newEmail - The new email address. + * @param {ActionCodeSettings} [actionCodeSettings] - Optional. Action code settings. + * @returns {Promise} + */ +export async function verifyBeforeUpdateEmail(user, newEmail, actionCodeSettings) { + return user.verifyBeforeUpdateEmail.call( + user, + newEmail, + actionCodeSettings, + MODULAR_DEPRECATION_ARG, + ); +} + +/** + * Extracts provider specific AdditionalUserInfo for the given credential. + * @param {UserCredential} userCredential - The user credential. + * @returns {AdditionalUserInfo | null} + */ +export function getAdditionalUserInfo(userCredential) { + return userCredential.additionalUserInfo; +} + +/** + * Returns the custom auth domain for the auth instance. + * @param {Auth} auth - The Auth instance. + * @returns {Promise} + */ +export function getCustomAuthDomain(auth) { + return auth.getCustomAuthDomain.call(auth, MODULAR_DEPRECATION_ARG); +} + +/** + * Returns a password validation status + * @param {Auth} auth - The Auth instance. + * @param {string} password - The password to validate. + * @returns {Promise} + */ +export async function validatePassword(auth, password) { + if (!auth || !auth.app) { + throw new Error( + "firebase.auth().validatePassword(*) 'auth' must be a valid Auth instance with an 'app' property. Received: undefined", + ); + } + + if (password === null || password === undefined) { + throw new Error( + "firebase.auth().validatePassword(*) expected 'password' to be a non-null or a defined value.", + ); + } + + return auth.validatePassword.call(auth, password, MODULAR_DEPRECATION_ARG); +} diff --git a/packages/auth/lib/modular/index.ts b/packages/auth/lib/modular/index.ts index e19413b044..a5749ac7cf 100644 --- a/packages/auth/lib/modular/index.ts +++ b/packages/auth/lib/modular/index.ts @@ -1,652 +1 @@ -// @ts-nocheck -/* eslint-disable @typescript-eslint/no-unused-vars */ -/* - * Copyright (c) 2016-present Invertase Limited & Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this library 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 { getApp } from '@react-native-firebase/app'; -import { MultiFactorUser } from '../multiFactor'; -import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/dist/module/common'; - -/** - * @typedef {import('@firebase/app-types').FirebaseApp} FirebaseApp - * @typedef {import('..').FirebaseAuthTypes} FirebaseAuthTypes - * @typedef {import('..').FirebaseAuthTypes.Module} Auth - * @typedef {import('..').FirebaseAuthTypes.CallbackOrObserver} CallbackOrObserver - * @typedef {import('..').FirebaseAuthTypes.AuthListenerCallback} AuthListenerCallback - * @typedef {import('..').FirebaseAuthTypes.ActionCodeInfo} ActionCodeInfo - * @typedef {import('..').FirebaseAuthTypes.UserCredential} UserCredential - * @typedef {import('..').FirebaseAuthTypes.MultiFactorError} MultiFactorError - * @typedef {import('..').FirebaseAuthTypes.MultiFactorUser} MultiFactorUser - * @typedef {import('..').FirebaseAuthTypes.MultiFactorResolver} MultiFactorResolver - * @typedef {import('..').FirebaseAuthTypes.ConfirmationResult} ConfirmationResult - * @typedef {import('..').FirebaseAuthTypes.AuthCredential} AuthCredential - * @typedef {import('..').FirebaseAuthTypes.AuthProvider} AuthProvider - * @typedef {import('..').FirebaseAuthTypes.PhoneAuthListener} PhoneAuthListener - * @typedef {import('..').FirebaseAuthTypes.ActionCodeSettings} ActionCodeSettings - * @typedef {import('..').FirebaseAuthTypes.User} User - * @typedef {import('..').FirebaseAuthTypes.IdTokenResult} IdTokenResult - * @typedef {import('..').FirebaseAuthTypes.AdditionalUserInfo} AdditionalUserInfo - * @typedef {import('..').FirebaseAuthTypes.ActionCodeURL} ActionCodeURL - * @typedef {import('..').FirebaseAuthTypes.ApplicationVerifier} ApplicationVerifier - */ - -/** - * Returns the Auth instance associated with the provided FirebaseApp. - * @param {FirebaseApp} [app] - The Firebase app instance. - * @returns {Auth} - */ -export function getAuth(app) { - if (app) { - return getApp(app.name).auth(); - } - return getApp().auth(); -} - -/** - * This function allows more control over the Auth instance than getAuth(). - * @param {FirebaseApp} app - The Firebase app instance. - * @param {any} [deps] - Optional. Dependencies for the Auth instance. - * @returns {Auth} - */ -export function initializeAuth(app, deps) { - if (app) { - return getApp(app.name).auth(); - } - return getApp().auth(); -} - -/** - * Applies a verification code sent to the user by email or other out-of-band mechanism. - * @param {Auth} auth - The Auth instance. - * @param {string} oobCode - The out-of-band code sent to the user. - * @returns {Promise} - */ -export async function applyActionCode(auth, oobCode) { - return auth.applyActionCode.call(auth, oobCode, MODULAR_DEPRECATION_ARG); -} - -/** - * Adds a blocking callback that runs before an auth state change sets a new user. - * @param {Auth} auth - The Auth instance. - * @param {(user: User | null) => void} callback - A callback function to run before the auth state changes. - * @param {() => void} [onAbort] - Optional. A callback function to run if the operation is aborted. - */ -export function beforeAuthStateChanged(auth, callback, onAbort) { - throw new Error('beforeAuthStateChanged is unsupported by the native Firebase SDKs'); -} - -/** - * Checks a verification code sent to the user by email or other out-of-band mechanism. - * @param {Auth} auth - The Auth instance. - * @param {string} oobCode - The out-of-band code sent to the user. - * @returns {Promise} - */ -export async function checkActionCode(auth, oobCode) { - return auth.checkActionCode.call(auth, oobCode, MODULAR_DEPRECATION_ARG); -} - -/** - * Completes the password reset process, given a confirmation code and new password. - * @param {Auth} auth - The Auth instance. - * @param {string} oobCode - The out-of-band code sent to the user. - * @param {string} newPassword - The new password. - * @returns {Promise} - */ -export async function confirmPasswordReset(auth, oobCode, newPassword) { - return auth.confirmPasswordReset.call(auth, oobCode, newPassword, MODULAR_DEPRECATION_ARG); -} - -/** - * Changes the Auth instance to communicate with the Firebase Auth Emulator, instead of production Firebase Auth services. - * @param {Auth} auth - The Auth instance. - * @param {string} url - The URL of the Firebase Auth Emulator. - * @param {{ disableWarnings: boolean }} [options] - Optional. Options for the emulator connection. - */ -export function connectAuthEmulator(auth, url, options) { - auth.useEmulator.call(auth, url, options, MODULAR_DEPRECATION_ARG); -} - -/** - * Creates a new user account associated with the specified email address and password. - * @param {Auth} auth - The Auth instance. - * @param {string} email - The user's email address. - * @param {string} password - The user's password. - * @returns {Promise} - */ -export async function createUserWithEmailAndPassword(auth, email, password) { - return auth.createUserWithEmailAndPassword.call(auth, email, password, MODULAR_DEPRECATION_ARG); -} - -/** - * Gets the list of possible sign in methods for the given email address. - * @param {Auth} auth - The Auth instance. - * @param {string} email - The user's email address. - * @returns {Promise} - */ -export async function fetchSignInMethodsForEmail(auth, email) { - return auth.fetchSignInMethodsForEmail.call(auth, email, MODULAR_DEPRECATION_ARG); -} - -/** - * Provides a MultiFactorResolver suitable for completion of a multi-factor flow. - * @param {Auth} auth - The Auth instance. - * @param {MultiFactorError} error - The multi-factor error. - * @returns {MultiFactorResolver} - */ -export function getMultiFactorResolver(auth, error) { - return auth.getMultiFactorResolver.call(auth, error, MODULAR_DEPRECATION_ARG); -} - -/** - * Returns a UserCredential from the redirect-based sign-in flow. - * @param {Auth} auth - The Auth instance. - * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. - * @returns {Promise} - */ -export async function getRedirectResult(auth, resolver) { - throw new Error('getRedirectResult is unsupported by the native Firebase SDKs'); -} - -/** - * Checks if an incoming link is a sign-in with email link suitable for signInWithEmailLink(). - * @param {Auth} auth - The Auth instance. - * @param {string} emailLink - The email link to check. - * @returns {Promise} - */ -export function isSignInWithEmailLink(auth, emailLink) { - return auth.isSignInWithEmailLink.call(auth, emailLink, MODULAR_DEPRECATION_ARG); -} - -/** - * Adds an observer for changes to the user's sign-in state. - * @param {Auth} auth - The Auth instance. - * @param {CallbackOrObserver} nextOrObserver - A callback function or observer for auth state changes. - * @returns {() => void} - */ -export function onAuthStateChanged(auth, nextOrObserver) { - return auth.onAuthStateChanged.call(auth, nextOrObserver, MODULAR_DEPRECATION_ARG); -} - -/** - * Adds an observer for changes to the signed-in user's ID token. - * @param {Auth} auth - The Auth instance. - * @param {CallbackOrObserver} nextOrObserver - A callback function or observer for ID token changes. - * @returns {() => void} - */ -export function onIdTokenChanged(auth, nextOrObserver) { - return auth.onIdTokenChanged.call(auth, nextOrObserver, MODULAR_DEPRECATION_ARG); -} - -/** - * Revoke the given access token, Currently only supports Apple OAuth access tokens. - * @param auth - The Auth Instance. - * @param token - The Access Token - */ -export async function revokeAccessToken(auth, token) { - throw new Error('revokeAccessToken() is only supported on Web'); -} //TO DO: Add Support - -/** - * Sends a password reset email to the given email address. - * @param {Auth} auth - The Auth instance. - * @param {string} email - The user's email address. - * @param {ActionCodeSettings} [actionCodeSettings] - Optional. Action code settings. - * @returns {Promise} - */ -export async function sendPasswordResetEmail(auth, email, actionCodeSettings) { - return auth.sendPasswordResetEmail.call(auth, email, actionCodeSettings, MODULAR_DEPRECATION_ARG); -} - -/** - * Sends a sign-in email link to the user with the specified email. - * @param {Auth} auth - The Auth instance. - * @param {string} email - The user's email address. - * @param {ActionCodeSettings} [actionCodeSettings] - Optional. Action code settings. - * @returns {Promise} - */ -export async function sendSignInLinkToEmail(auth, email, actionCodeSettings) { - return auth.sendSignInLinkToEmail.call(auth, email, actionCodeSettings, MODULAR_DEPRECATION_ARG); -} - -/** - * Changes the type of persistence on the Auth instance for the currently saved Auth session and applies this type of persistence for future sign-in requests, including sign-in with redirect requests. - * @param {Auth} auth - The Auth instance. - * @param {Persistence} persistence - The persistence type. - * @returns {Promise} - */ -export async function setPersistence(auth, persistence) { - throw new Error('setPersistence is unsupported by the native Firebase SDKs'); -} - -/** - * Asynchronously signs in as an anonymous user. - * @param {Auth} auth - The Auth instance. - * @returns {Promise} - */ -export async function signInAnonymously(auth) { - return auth.signInAnonymously.call(auth, MODULAR_DEPRECATION_ARG); -} - -/** - * Asynchronously signs in with the given credentials. - * @param {Auth} auth - The Auth instance. - * @param {AuthCredential} credential - The auth credentials. - * @returns {Promise} - */ -export async function signInWithCredential(auth, credential) { - return auth.signInWithCredential.call(auth, credential, MODULAR_DEPRECATION_ARG); -} - -/** - * Asynchronously signs in using a custom token. - * @param {Auth} auth - The Auth instance. - * @param {string} customToken - The custom token. - * @returns {Promise} - */ -export async function signInWithCustomToken(auth, customToken) { - return auth.signInWithCustomToken.call(auth, customToken, MODULAR_DEPRECATION_ARG); -} - -/** - * Asynchronously signs in using an email and password. - * @param {Auth} auth - The Auth instance. - * @param {string} email - The user's email address. - * @param {string} password - The user's password. - * @returns {Promise} - */ -export async function signInWithEmailAndPassword(auth, email, password) { - return auth.signInWithEmailAndPassword.call(auth, email, password, MODULAR_DEPRECATION_ARG); -} - -/** - * Asynchronously signs in using an email and sign-in email link. - * @param {Auth} auth - The Auth instance. - * @param {string} email - The user's email address. - * @param {string} emailLink - The email link. - * @returns {Promise} - */ -export async function signInWithEmailLink(auth, email, emailLink) { - return auth.signInWithEmailLink.call(auth, email, emailLink, MODULAR_DEPRECATION_ARG); -} - -/** - * Asynchronously signs in using a phone number. - * @param {Auth} auth - The Auth instance. - * @param {string} phoneNumber - The user's phone number. - * @param {ApplicationVerifier} appVerifier - The application verifier. - * @returns {Promise} - */ -export async function signInWithPhoneNumber(auth, phoneNumber, appVerifier) { - return auth.signInWithPhoneNumber.call(auth, phoneNumber, appVerifier, MODULAR_DEPRECATION_ARG); -} - -/** - * Asynchronously verifies a phone number. - * @param {Auth} auth - The Auth instance. - * @param {string} phoneNumber - The user's phone number. - * @param {number | boolean} autoVerifyTimeoutOrForceResend - The auto verify timeout or force resend flag. - * @param {boolean} [forceResend] - Optional. Whether to force resend. - * @returns {PhoneAuthListener} - */ -export function verifyPhoneNumber(auth, phoneNumber, autoVerifyTimeoutOrForceResend, forceResend) { - return auth.verifyPhoneNumber.call( - auth, - phoneNumber, - autoVerifyTimeoutOrForceResend, - forceResend, - MODULAR_DEPRECATION_ARG, - ); -} - -/** - * Authenticates a Firebase client using a popup-based OAuth authentication flow. - * @param {Auth} auth - The Auth instance. - * @param {AuthProvider} provider - The auth provider. - * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. - * @returns {Promise} - */ -export async function signInWithPopup(auth, provider, resolver) { - return auth.signInWithPopup.call(auth, provider, resolver, MODULAR_DEPRECATION_ARG); -} - -/** - * Authenticates a Firebase client using a full-page redirect flow. - * @param {Auth} auth - The Auth instance. - * @param {AuthProvider} provider - The auth provider. - * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. - * @returns {Promise} - */ -export async function signInWithRedirect(auth, provider, resolver) { - return auth.signInWithRedirect.call(auth, provider, resolver, MODULAR_DEPRECATION_ARG); -} - -/** - * Signs out the current user. - * @param {Auth} auth - The Auth instance. - * @returns {Promise} - */ -export async function signOut(auth) { - return auth.signOut.call(auth, MODULAR_DEPRECATION_ARG); -} - -/** - * Asynchronously sets the provided user as Auth.currentUser on the Auth instance. - * @param {Auth} auth - The Auth instance. - * @param {User} user - The user to set as the current user. - * @returns {Promise} - */ -export async function updateCurrentUser(auth, user) { - throw new Error('updateCurrentUser is unsupported by the native Firebase SDKs'); -} - -/** - * Sets the current language to the default device/browser preference. - * @param {Auth} auth - The Auth instance. - */ -export function useDeviceLanguage(auth) { - throw new Error('useDeviceLanguage is unsupported by the native Firebase SDKs'); -} - -/** - * Sets the language code. - * @param {Auth} auth - The Auth instance. - * @param {string} languageCode - The language code. - */ -export function setLanguageCode(auth, languageCode) { - return auth.setLanguageCode.call(auth, languageCode, MODULAR_DEPRECATION_ARG); -} - -/** - * Configures a shared user access group to sync auth state across multiple apps via the Keychain. - * @param {Auth} auth - The Auth instance. - * @param {string} userAccessGroup - The user access group. - * @returns {Promise} - */ -export function useUserAccessGroup(auth, userAccessGroup) { - return auth.useUserAccessGroup.call(auth, userAccessGroup, MODULAR_DEPRECATION_ARG); -} - -/** - * Verifies the password reset code sent to the user by email or other out-of-band mechanism. - * @param {Auth} auth - The Auth instance. - * @param {string} code - The password reset code. - * @returns {Promise} - */ -export async function verifyPasswordResetCode(auth, code) { - return auth.verifyPasswordResetCode.call(auth, code, MODULAR_DEPRECATION_ARG); -} - -/** - * Parses the email action link string and returns an ActionCodeURL if the link is valid, otherwise returns null. - * @param {string} link - The email action link string. - * @returns {ActionCodeURL | null} - */ -export function parseActionCodeURL(link) { - throw new Error('parseActionCodeURL is unsupported by the native Firebase SDKs'); -} - -/** - * Deletes and signs out the user. - * @param {User} user - The user to delete. - * @returns {Promise} - */ -export async function deleteUser(user) { - return user.delete.call(user, MODULAR_DEPRECATION_ARG); -} - -/** - * Returns a JSON Web Token (JWT) used to identify the user to a Firebase service. - * @param {User} user - The user to get the token for. - * @param {boolean} [forceRefresh] - Optional. Whether to force refresh the token. - * @returns {Promise} - */ -export async function getIdToken(user, forceRefresh) { - return user.getIdToken.call(user, forceRefresh, MODULAR_DEPRECATION_ARG); -} - -/** - * Returns a deserialized JSON Web Token (JWT) used to identify the user to a Firebase service. - * @param {User} user - The user to get the token result for. - * @param {boolean} [forceRefresh] - Optional. Whether to force refresh the token. - * @returns {Promise} - */ -export async function getIdTokenResult(user, forceRefresh) { - return user.getIdTokenResult.call(user, forceRefresh, MODULAR_DEPRECATION_ARG); -} - -/** - * Links the user account with the given credentials. - * @param {User} user - The user to link the credentials with. - * @param {AuthCredential} credential - The auth credentials. - * @returns {Promise} - */ -export async function linkWithCredential(user, credential) { - return user.linkWithCredential.call(user, credential, MODULAR_DEPRECATION_ARG); -} - -/** - * Links the user account with the given phone number. - * @param {User} user - The user to link the phone number with. - * @param {string} phoneNumber - The phone number. - * @param {ApplicationVerifier} appVerifier - The application verifier. - * @returns {Promise} - */ -export async function linkWithPhoneNumber(user, phoneNumber, appVerifier) { - throw new Error('linkWithPhoneNumber is unsupported by the native Firebase SDKs'); -} - -/** - * Links the authenticated provider to the user account using a pop-up based OAuth flow. - * @param {User} user - The user to link the provider with. - * @param {AuthProvider} provider - The auth provider. - * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. - * @returns {Promise} - */ -export async function linkWithPopup(user, provider, resolver) { - return user.linkWithPopup.call(user, provider, resolver, MODULAR_DEPRECATION_ARG); -} - -/** - * Links the OAuthProvider to the user account using a full-page redirect flow. - * @param {User} user - The user to link the provider with. - * @param {AuthProvider} provider - The auth provider. - * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. - * @returns {Promise} - */ -export async function linkWithRedirect(user, provider, resolver) { - return user.linkWithRedirect.call(user, provider, resolver, MODULAR_DEPRECATION_ARG); -} - -/** - * The MultiFactorUser corresponding to the user. - * @param {User} user - The user to get the multi-factor user for. - * @returns {MultiFactorUser} - */ -export function multiFactor(user) { - return new MultiFactorUser(getAuth(), user); -} - -/** - * Re-authenticates a user using a fresh credential. - * @param {User} user - The user to re-authenticate. - * @param {AuthCredential} credential - The auth credentials. - * @returns {Promise} - */ -export async function reauthenticateWithCredential(user, credential) { - return user.reauthenticateWithCredential.call(user, credential, MODULAR_DEPRECATION_ARG); -} - -/** - * Re-authenticates a user using a fresh phone credential. - * @param {User} user - The user to re-authenticate. - * @param {string} phoneNumber - The phone number. - * @param {ApplicationVerifier} appVerifier - The application verifier. - * @returns {Promise} - */ -export async function reauthenticateWithPhoneNumber(user, phoneNumber, appVerifier) { - throw new Error('reauthenticateWithPhoneNumber is unsupported by the native Firebase SDKs'); -} - -/** - * Re-authenticate a user with a federated authentication provider (Microsoft, Yahoo). For native platforms, this will open a browser window. - * @param {User} user - The user to re-authenticate. - * @param {AuthProvider} provider - The auth provider. - * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. Web only. - * @returns {Promise} - */ -export async function reauthenticateWithPopup(user, provider, resolver) { - return user.reauthenticateWithPopup.call(user, provider, resolver, MODULAR_DEPRECATION_ARG); -} - -/** - * Re-authenticate a user with a federated authentication provider (Microsoft, Yahoo). For native platforms, this will open a browser window. - * @param {User} user - The user to re-authenticate. - * @param {AuthProvider} provider - The auth provider. - * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. Web only. - * @returns {Promise} - */ -export async function reauthenticateWithRedirect(user, provider, resolver) { - return user.reauthenticateWithRedirect.call(user, provider, resolver, MODULAR_DEPRECATION_ARG); -} - -/** - * Reloads user account data, if signed in. - * @param {User} user - The user to reload data for. - * @returns {Promise} - */ -export async function reload(user) { - return user.reload.call(user, MODULAR_DEPRECATION_ARG); -} - -/** - * Sends a verification email to a user. - * @param {User} user - The user to send the email to. - * @param {ActionCodeSettings} [actionCodeSettings] - Optional. Action code settings. - * @returns {Promise} - */ -export async function sendEmailVerification(user, actionCodeSettings) { - return user.sendEmailVerification.call(user, actionCodeSettings, MODULAR_DEPRECATION_ARG); -} - -/** - * Unlinks a provider from a user account. - * @param {User} user - The user to unlink the provider from. - * @param {string} providerId - The provider ID. - * @returns {Promise} - */ -export async function unlink(user, providerId) { - return user.unlink.call(user, providerId, MODULAR_DEPRECATION_ARG); -} - -/** - * Updates the user's email address. - * @param {User} user - The user to update the email for. - * @param {string} newEmail - The new email address. - * @returns {Promise} - */ -export async function updateEmail(user, newEmail) { - return user.updateEmail.call(user, newEmail, MODULAR_DEPRECATION_ARG); -} - -/** - * Updates the user's password. - * @param {User} user - The user to update the password for. - * @param {string} newPassword - The new password. - * @returns {Promise} - */ -export async function updatePassword(user, newPassword) { - return user.updatePassword.call(user, newPassword, MODULAR_DEPRECATION_ARG); -} - -/** - * Updates the user's phone number. - * @param {User} user - The user to update the phone number for. - * @param {AuthCredential} credential - The auth credentials. - * @returns {Promise} - */ -export async function updatePhoneNumber(user, credential) { - return user.updatePhoneNumber.call(user, credential, MODULAR_DEPRECATION_ARG); -} - -/** - * Updates a user's profile data. - * @param {User} user - The user to update the profile for. - * @param {{ displayName?: string | null, photoURL?: string | null }} profile - An object containing the profile data to update. - * @returns {Promise} - */ -export async function updateProfile(user, { displayName, photoURL: photoUrl }) { - return user.updateProfile.call( - user, - { displayName, photoURL: photoUrl }, - MODULAR_DEPRECATION_ARG, - ); -} - -/** - * Sends a verification email to a new email address. - * @param {User} user - The user to send the email to. - * @param {string} newEmail - The new email address. - * @param {ActionCodeSettings} [actionCodeSettings] - Optional. Action code settings. - * @returns {Promise} - */ -export async function verifyBeforeUpdateEmail(user, newEmail, actionCodeSettings) { - return user.verifyBeforeUpdateEmail.call( - user, - newEmail, - actionCodeSettings, - MODULAR_DEPRECATION_ARG, - ); -} - -/** - * Extracts provider specific AdditionalUserInfo for the given credential. - * @param {UserCredential} userCredential - The user credential. - * @returns {AdditionalUserInfo | null} - */ -export function getAdditionalUserInfo(userCredential) { - return userCredential.additionalUserInfo; -} - -/** - * Returns the custom auth domain for the auth instance. - * @param {Auth} auth - The Auth instance. - * @returns {Promise} - */ -export function getCustomAuthDomain(auth) { - return auth.getCustomAuthDomain.call(auth, MODULAR_DEPRECATION_ARG); -} - -/** - * Returns a password validation status - * @param {Auth} auth - The Auth instance. - * @param {string} password - The password to validate. - * @returns {Promise} - */ -export async function validatePassword(auth, password) { - if (!auth || !auth.app) { - throw new Error( - "firebase.auth().validatePassword(*) 'auth' must be a valid Auth instance with an 'app' property. Received: undefined", - ); - } - - if (password === null || password === undefined) { - throw new Error( - "firebase.auth().validatePassword(*) expected 'password' to be a non-null or a defined value.", - ); - } - - return auth.validatePassword.call(auth, password, MODULAR_DEPRECATION_ARG); -} +export * from '../modular'; diff --git a/packages/auth/lib/namespaced.ts b/packages/auth/lib/namespaced.ts new file mode 100644 index 0000000000..a86a4de6c2 --- /dev/null +++ b/packages/auth/lib/namespaced.ts @@ -0,0 +1,571 @@ +// @ts-nocheck +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library 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 { + createDeprecationProxy, + isAndroid, + isBoolean, + isNull, + isOther, + isString, + isValidUrl, + parseListenerOrObserver, +} from '@react-native-firebase/app/dist/module/common'; +import { setReactNativeModule } from '@react-native-firebase/app/dist/module/internal/nativeModule'; +import { + FirebaseModule, + createModuleNamespace, + getFirebaseRoot, +} from '@react-native-firebase/app/dist/module/internal'; +import ConfirmationResult from './ConfirmationResult'; +import PhoneAuthListener from './PhoneAuthListener'; +import PhoneMultiFactorGenerator from './PhoneMultiFactorGenerator'; +import TotpMultiFactorGenerator from './TotpMultiFactorGenerator'; +import Settings from './Settings'; +import User from './User'; +import { getMultiFactorResolver } from './getMultiFactorResolver'; +import { MultiFactorUser, multiFactor } from './multiFactor'; +import AppleAuthProvider from './providers/AppleAuthProvider'; +import EmailAuthProvider from './providers/EmailAuthProvider'; +import FacebookAuthProvider from './providers/FacebookAuthProvider'; +import GithubAuthProvider from './providers/GithubAuthProvider'; +import GoogleAuthProvider from './providers/GoogleAuthProvider'; +import OAuthProvider from './providers/OAuthProvider'; +import OIDCAuthProvider from './providers/OIDCAuthProvider'; +import PhoneAuthProvider from './providers/PhoneAuthProvider'; +import TwitterAuthProvider from './providers/TwitterAuthProvider'; +import { TotpSecret } from './TotpSecret'; +import { version } from './version'; +import fallBackModule from './web/RNFBAuthModule'; +import { PasswordPolicyMixin } from './password-policy/PasswordPolicyMixin'; + +const PhoneAuthState = { + CODE_SENT: 'sent', + AUTO_VERIFY_TIMEOUT: 'timeout', + AUTO_VERIFIED: 'verified', + ERROR: 'error', +}; + +export { + AppleAuthProvider, + EmailAuthProvider, + PhoneAuthProvider, + GoogleAuthProvider, + GithubAuthProvider, + TwitterAuthProvider, + FacebookAuthProvider, + PhoneMultiFactorGenerator, + TotpMultiFactorGenerator, + TotpSecret, + OAuthProvider, + OIDCAuthProvider, + PhoneAuthState, +}; + +const statics = { + AppleAuthProvider, + EmailAuthProvider, + PhoneAuthProvider, + GoogleAuthProvider, + GithubAuthProvider, + TwitterAuthProvider, + FacebookAuthProvider, + PhoneMultiFactorGenerator, + TotpMultiFactorGenerator, + OAuthProvider, + OIDCAuthProvider, + PhoneAuthState, + getMultiFactorResolver, + multiFactor, +}; + +const namespace = 'auth'; +const nativeModuleName = 'RNFBAuthModule'; + +class FirebaseAuthModule extends FirebaseModule { + constructor(...args) { + super(...args); + this._user = null; + this._settings = null; + this._authResult = false; + this._languageCode = this.native.APP_LANGUAGE[this.app._name]; + this._tenantId = null; + this._projectPasswordPolicy = null; + this._tenantPasswordPolicies = {}; + + if (!this.languageCode) { + this._languageCode = this.native.APP_LANGUAGE['[DEFAULT]']; + } + + if (this.native.APP_USER[this.app._name]) { + this._setUser(this.native.APP_USER[this.app._name]); + } + + this.emitter.addListener(this.eventNameForApp('auth_state_changed'), event => { + this._setUser(event.user); + this.emitter.emit(this.eventNameForApp('onAuthStateChanged'), this._user); + }); + + this.emitter.addListener(this.eventNameForApp('phone_auth_state_changed'), event => { + const eventKey = `phone:auth:${event.requestKey}:${event.type}`; + this.emitter.emit(eventKey, event.state); + }); + + this.emitter.addListener(this.eventNameForApp('auth_id_token_changed'), auth => { + this._setUser(auth.user); + this.emitter.emit(this.eventNameForApp('onIdTokenChanged'), this._user); + }); + + this.native.addAuthStateListener(); + this.native.addIdTokenListener(); + + // custom authDomain in only available from App's FirebaseOptions, + // but we need it in Auth if it exists. During app configuration we store + // mappings from app name to authDomain, this auth constructor + // is a reasonable time to use the mapping and set it into auth natively + if (!isOther) { + // Only supported on native platforms + this.native.configureAuthDomain(); + } + } + + get languageCode() { + return this._languageCode; + } + + set languageCode(code) { + // For modular API, not recommended to set languageCode directly as it should be set in the native SDKs first + if (!isString(code) && !isNull(code)) { + throw new Error( + "firebase.auth().languageCode = (*) expected 'languageCode' to be a string or null value", + ); + } + // as this is a setter, we can't use async/await. So we set it first so it is available immediately + if (code === null) { + this._languageCode = this.native.APP_LANGUAGE[this.app._name]; + + if (!this.languageCode) { + this._languageCode = this.native.APP_LANGUAGE['[DEFAULT]']; + } + } else { + this._languageCode = code; + } + // This sets it natively + this.setLanguageCode(code); + } + + get config() { + // for modular API, firebase JS SDK has a config object which is not available in native SDKs + return {}; + } + + get tenantId() { + return this._tenantId; + } + + get settings() { + if (!this._settings) { + this._settings = new Settings(this); + } + return this._settings; + } + + get currentUser() { + return this._user; + } + + _setUser(user) { + this._user = user ? createDeprecationProxy(new User(this, user)) : null; + this._authResult = true; + this.emitter.emit(this.eventNameForApp('onUserChanged'), this._user); + return this._user; + } + + _setUserCredential(userCredential) { + const user = createDeprecationProxy(new User(this, userCredential.user)); + this._user = user; + this._authResult = true; + this.emitter.emit(this.eventNameForApp('onUserChanged'), this._user); + return { + additionalUserInfo: userCredential.additionalUserInfo, + user, + }; + } + + async setLanguageCode(code) { + if (!isString(code) && !isNull(code)) { + throw new Error( + "firebase.auth().setLanguageCode(*) expected 'languageCode' to be a string or null value", + ); + } + + await this.native.setLanguageCode(code); + + if (code === null) { + this._languageCode = this.native.APP_LANGUAGE[this.app._name]; + + if (!this.languageCode) { + this._languageCode = this.native.APP_LANGUAGE['[DEFAULT]']; + } + } else { + this._languageCode = code; + } + } + + async setTenantId(tenantId) { + if (!isString(tenantId)) { + throw new Error("firebase.auth().setTenantId(*) expected 'tenantId' to be a string"); + } + this._tenantId = tenantId; + await this.native.setTenantId(tenantId); + } + + onAuthStateChanged(listenerOrObserver) { + const listener = parseListenerOrObserver(listenerOrObserver); + const subscription = this.emitter.addListener( + this.eventNameForApp('onAuthStateChanged'), + listener, + ); + + if (this._authResult) { + Promise.resolve().then(() => { + listener(this._user || null); + }); + } + return () => subscription.remove(); + } + + onIdTokenChanged(listenerOrObserver) { + const listener = parseListenerOrObserver(listenerOrObserver); + const subscription = this.emitter.addListener( + this.eventNameForApp('onIdTokenChanged'), + listener, + ); + + if (this._authResult) { + Promise.resolve().then(() => { + listener(this._user || null); + }); + } + return () => subscription.remove(); + } + + onUserChanged(listenerOrObserver) { + const listener = parseListenerOrObserver(listenerOrObserver); + const subscription = this.emitter.addListener(this.eventNameForApp('onUserChanged'), listener); + if (this._authResult) { + Promise.resolve().then(() => { + listener(this._user || null); + }); + } + + return () => { + subscription.remove(); + }; + } + + signOut() { + return this.native.signOut().then(() => { + this._setUser(null); + }); + } + + signInAnonymously() { + return this.native + .signInAnonymously() + .then(userCredential => this._setUserCredential(userCredential)); + } + + signInWithPhoneNumber(phoneNumber, forceResend) { + if (isAndroid) { + return this.native + .signInWithPhoneNumber(phoneNumber, forceResend || false) + .then(result => new ConfirmationResult(this, result.verificationId)); + } + + return this.native + .signInWithPhoneNumber(phoneNumber) + .then(result => new ConfirmationResult(this, result.verificationId)); + } + + verifyPhoneNumber(phoneNumber, autoVerifyTimeoutOrForceResend, forceResend) { + let _forceResend = forceResend; + let _autoVerifyTimeout = 60; + + if (isBoolean(autoVerifyTimeoutOrForceResend)) { + _forceResend = autoVerifyTimeoutOrForceResend; + } else { + _autoVerifyTimeout = autoVerifyTimeoutOrForceResend; + } + + return new PhoneAuthListener(this, phoneNumber, _autoVerifyTimeout, _forceResend); + } + + verifyPhoneNumberWithMultiFactorInfo(multiFactorHint, session) { + return this.native.verifyPhoneNumberWithMultiFactorInfo(multiFactorHint.uid, session); + } + + verifyPhoneNumberForMultiFactor(phoneInfoOptions) { + const { phoneNumber, session } = phoneInfoOptions; + return this.native.verifyPhoneNumberForMultiFactor(phoneNumber, session); + } + + resolveMultiFactorSignIn(session, verificationId, verificationCode) { + return this.native + .resolveMultiFactorSignIn(session, verificationId, verificationCode) + .then(userCredential => { + return this._setUserCredential(userCredential); + }); + } + + resolveTotpSignIn(session, uid, totpSecret) { + return this.native.resolveTotpSignIn(session, uid, totpSecret).then(userCredential => { + return this._setUserCredential(userCredential); + }); + } + + createUserWithEmailAndPassword(email, password) { + return ( + this.native + .createUserWithEmailAndPassword(email, password) + .then(userCredential => this._setUserCredential(userCredential)) + /* istanbul ignore next - native error handling cannot be unit tested */ + .catch(error => { + if (error.code === 'auth/password-does-not-meet-requirements') { + return this._recachePasswordPolicy() + .catch(() => { + // Silently ignore recache failures - the original error matters more + }) + .then(() => { + throw error; + }); + } + throw error; + }) + ); + } + + signInWithEmailAndPassword(email, password) { + return ( + this.native + .signInWithEmailAndPassword(email, password) + .then(userCredential => this._setUserCredential(userCredential)) + /* istanbul ignore next - native error handling cannot be unit tested */ + .catch(error => { + if (error.code === 'auth/password-does-not-meet-requirements') { + return this._recachePasswordPolicy() + .catch(() => { + // Silently ignore recache failures - the original error matters more + }) + .then(() => { + throw error; + }); + } + throw error; + }) + ); + } + + signInWithCustomToken(customToken) { + return this.native + .signInWithCustomToken(customToken) + .then(userCredential => this._setUserCredential(userCredential)); + } + + signInWithCredential(credential) { + return this.native + .signInWithCredential(credential.providerId, credential.token, credential.secret) + .then(userCredential => this._setUserCredential(userCredential)); + } + + revokeToken(authorizationCode) { + return this.native.revokeToken(authorizationCode); + } + + sendPasswordResetEmail(email, actionCodeSettings = null) { + return this.native.sendPasswordResetEmail(email, actionCodeSettings); + } + + sendSignInLinkToEmail(email, actionCodeSettings = {}) { + return this.native.sendSignInLinkToEmail(email, actionCodeSettings); + } + + isSignInWithEmailLink(emailLink) { + return this.native.isSignInWithEmailLink(emailLink); + } + + signInWithEmailLink(email, emailLink) { + return this.native + .signInWithEmailLink(email, emailLink) + .then(userCredential => this._setUserCredential(userCredential)); + } + + confirmPasswordReset(code, newPassword) { + return ( + this.native + .confirmPasswordReset(code, newPassword) + /* istanbul ignore next - native error handling cannot be unit tested */ + .catch(error => { + if (error.code === 'auth/password-does-not-meet-requirements') { + return this._recachePasswordPolicy() + .catch(() => { + // Silently ignore recache failures - the original error matters more + }) + .then(() => { + throw error; + }); + } + throw error; + }) + ); + } + + applyActionCode(code) { + return this.native.applyActionCode(code).then(user => { + this._setUser(user); + }); + } + + checkActionCode(code) { + return this.native.checkActionCode(code); + } + + fetchSignInMethodsForEmail(email) { + return this.native.fetchSignInMethodsForEmail(email); + } + + verifyPasswordResetCode(code) { + return this.native.verifyPasswordResetCode(code); + } + + useUserAccessGroup(userAccessGroup) { + if (isAndroid) { + return Promise.resolve(); + } + return this.native.useUserAccessGroup(userAccessGroup); + } + + getRedirectResult() { + throw new Error( + 'firebase.auth().getRedirectResult() is unsupported by the native Firebase SDKs.', + ); + } + + setPersistence() { + throw new Error('firebase.auth().setPersistence() is unsupported by the native Firebase SDKs.'); + } + + signInWithPopup(provider) { + return this.native + .signInWithProvider(provider.toObject()) + .then(userCredential => this._setUserCredential(userCredential)); + } + + signInWithRedirect(provider) { + return this.native + .signInWithProvider(provider.toObject()) + .then(userCredential => this._setUserCredential(userCredential)); + } + + // firebase issue - https://github.com/invertase/react-native-firebase/pull/655#issuecomment-349904680 + useDeviceLanguage() { + throw new Error( + 'firebase.auth().useDeviceLanguage() is unsupported by the native Firebase SDKs.', + ); + } + + useEmulator(url) { + if (!url || !isString(url) || !isValidUrl(url)) { + throw new Error('firebase.auth().useEmulator() takes a non-empty string URL'); + } + + let _url = url; + const androidBypassEmulatorUrlRemap = + typeof this.firebaseJson.android_bypass_emulator_url_remap === 'boolean' && + this.firebaseJson.android_bypass_emulator_url_remap; + if (!androidBypassEmulatorUrlRemap && isAndroid && _url) { + if (_url.startsWith('http://localhost')) { + _url = _url.replace('http://localhost', 'http://10.0.2.2'); + // eslint-disable-next-line no-console + console.log( + 'Mapping auth host "localhost" to "10.0.2.2" for android emulators. Use real IP on real devices. You can bypass this behaviour with "android_bypass_emulator_url_remap" flag.', + ); + } + if (_url.startsWith('http://127.0.0.1')) { + _url = _url.replace('http://127.0.0.1', 'http://10.0.2.2'); + // eslint-disable-next-line no-console + console.log( + 'Mapping auth host "127.0.0.1" to "10.0.2.2" for android emulators. Use real IP on real devices. You can bypass this behaviour with "android_bypass_emulator_url_remap" flag.', + ); + } + } + + // Native calls take the host and port split out + const hostPortRegex = /^http:\/\/([\w\d-.]+):(\d+)$/; + const urlMatches = _url.match(hostPortRegex); + if (!urlMatches) { + throw new Error('firebase.auth().useEmulator() unable to parse host and port from URL'); + } + const host = urlMatches[1]; + const port = parseInt(urlMatches[2], 10); + this.native.useEmulator(host, port); + return [host, port]; // undocumented return, useful for unit testing + } + + getMultiFactorResolver(error) { + return getMultiFactorResolver(this, error); + } + + multiFactor(user) { + if (!this.currentUser || user.uid !== this.currentUser.uid) { + throw new Error('firebase.auth().multiFactor() only operates on currentUser'); + } + return new MultiFactorUser(this, user); + } + + getCustomAuthDomain() { + return this.native.getCustomAuthDomain(); + } +} + +// Apply password policy mixin to FirebaseAuthModule +Object.assign(FirebaseAuthModule.prototype, PasswordPolicyMixin); + +// import { SDK_VERSION } from '@react-native-firebase/auth'; +export const SDK_VERSION = version; + +// import auth from '@react-native-firebase/auth'; +// auth().X(...); +export default createModuleNamespace({ + statics, + version, + namespace, + nativeModuleName, + nativeEvents: ['auth_state_changed', 'auth_id_token_changed', 'phone_auth_state_changed'], + hasMultiAppSupport: true, + hasCustomUrlOrRegionSupport: false, + ModuleClass: FirebaseAuthModule, +}); + +// import auth, { firebase } from '@react-native-firebase/auth'; +// auth().X(...); +// firebase.auth().X(...); +export const firebase = getFirebaseRoot(); + +// Register the interop module for non-native platforms. +setReactNativeModule(nativeModuleName, fallBackModule); diff --git a/packages/auth/lib/types/auth.ts b/packages/auth/lib/types/auth.ts new file mode 100644 index 0000000000..f8a0921cf4 --- /dev/null +++ b/packages/auth/lib/types/auth.ts @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library 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 type { ReactNativeFirebase } from '@react-native-firebase/app'; +import type { FirebaseAuthTypes } from './namespaced'; + +export type FirebaseApp = ReactNativeFirebase.FirebaseApp; +export type Auth = FirebaseAuthTypes.Module; +export type NativeFirebaseAuthError = FirebaseAuthTypes.NativeFirebaseAuthError; +export type AuthCredential = FirebaseAuthTypes.AuthCredential; +export type AuthProvider = FirebaseAuthTypes.AuthProvider; +export type OAuthProvider = FirebaseAuthTypes.OAuthProvider; +export type OIDCProvider = FirebaseAuthTypes.OIDCProvider; +export type EmailAuthProvider = FirebaseAuthTypes.EmailAuthProvider; +export type PhoneAuthState = FirebaseAuthTypes.PhoneAuthState; +export type MultiFactorSession = FirebaseAuthTypes.MultiFactorSession; +export type PhoneMultiFactorGenerator = FirebaseAuthTypes.PhoneMultiFactorGenerator; +export type TotpSecret = FirebaseAuthTypes.TotpSecret; +export type TotpMultiFactorGenerator = FirebaseAuthTypes.TotpMultiFactorGenerator; +export type MultiFactorError = FirebaseAuthTypes.MultiFactorError; +export type AdditionalUserInfo = FirebaseAuthTypes.AdditionalUserInfo; +export type UserCredential = FirebaseAuthTypes.UserCredential; +export type UserMetadata = FirebaseAuthTypes.UserMetadata; +export type FactorId = FirebaseAuthTypes.FactorId; +export type MultiFactorInfo = FirebaseAuthTypes.MultiFactorInfo; +export type PhoneMultiFactorInfo = FirebaseAuthTypes.PhoneMultiFactorInfo; +export type TotpMultiFactorInfo = FirebaseAuthTypes.TotpMultiFactorInfo; +export type MultiFactorInfoCommon = FirebaseAuthTypes.MultiFactorInfoCommon; +export type MultiFactorAssertion = FirebaseAuthTypes.MultiFactorAssertion; +export type PhoneMultiFactorEnrollInfoOptions = FirebaseAuthTypes.PhoneMultiFactorEnrollInfoOptions; +export type PhoneMultiFactorSignInInfoOptions = FirebaseAuthTypes.PhoneMultiFactorSignInInfoOptions; +export type MultiFactorResolver = FirebaseAuthTypes.MultiFactorResolver; +export type MultiFactorUser = FirebaseAuthTypes.MultiFactorUser; +export type MultiFactor = FirebaseAuthTypes.MultiFactor; +export type UserInfo = FirebaseAuthTypes.UserInfo; +export type IdTokenResult = FirebaseAuthTypes.IdTokenResult; +export type UpdateProfile = FirebaseAuthTypes.UpdateProfile; +export type ConfirmationResult = FirebaseAuthTypes.ConfirmationResult; +export type ActionCodeSettingsAndroid = FirebaseAuthTypes.ActionCodeSettingsAndroid; +export type ActionCodeInfoData = FirebaseAuthTypes.ActionCodeInfoData; +export type ActionCodeInfo = FirebaseAuthTypes.ActionCodeInfo; +export type ActionCodeSettingsIos = FirebaseAuthTypes.ActionCodeSettingsIos; +export type ActionCodeSettings = FirebaseAuthTypes.ActionCodeSettings; +export type AuthListenerCallback = FirebaseAuthTypes.AuthListenerCallback; +export type PhoneAuthSnapshot = FirebaseAuthTypes.PhoneAuthSnapshot; +export type PhoneAuthError = FirebaseAuthTypes.PhoneAuthError; +export type PhoneAuthListener = FirebaseAuthTypes.PhoneAuthListener; +export type AuthSettings = FirebaseAuthTypes.AuthSettings; +export type User = FirebaseAuthTypes.User; +export type ActionCodeURL = FirebaseAuthTypes.ActionCodeURL; +export type PasswordPolicy = FirebaseAuthTypes.PasswordPolicy; +export type getMultiFactorResolver = FirebaseAuthTypes.getMultiFactorResolver; +export type multiFactor = FirebaseAuthTypes.multiFactor; + +export interface PopupRedirectResolver {} + +export interface ApplicationVerifier { + readonly type: string; + verify(): Promise; +} + +export type Persistence = { + readonly type: 'SESSION' | 'LOCAL' | 'NONE'; +}; + +export interface PasswordValidationStatus { + readonly isValid: boolean; + readonly meetsMinPasswordLength?: boolean; + readonly meetsMaxPasswordLength?: boolean; + readonly containsLowercaseLetter?: boolean; + readonly containsUppercaseLetter?: boolean; + readonly containsNumericCharacter?: boolean; + readonly containsNonAlphanumericCharacter?: boolean; + readonly passwordPolicy: PasswordPolicy; +} diff --git a/packages/auth/lib/types/internal.ts b/packages/auth/lib/types/internal.ts new file mode 100644 index 0000000000..b4732fde4b --- /dev/null +++ b/packages/auth/lib/types/internal.ts @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library 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 type { FirebaseAuthTypes } from './namespaced'; + +export type AuthInternal = FirebaseAuthTypes.Module; +export type UserInternal = FirebaseAuthTypes.User; +export type ConfirmationResultInternal = FirebaseAuthTypes.ConfirmationResult; +export type MultiFactorResolverInternal = FirebaseAuthTypes.MultiFactorResolver; diff --git a/packages/auth/lib/types/namespaced.ts b/packages/auth/lib/types/namespaced.ts new file mode 100644 index 0000000000..6f6a4c3c7f --- /dev/null +++ b/packages/auth/lib/types/namespaced.ts @@ -0,0 +1,2351 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library 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 { ReactNativeFirebase } from '@react-native-firebase/app'; + +/** + * Firebase Authentication package for React Native. + * + * #### Example: Access the firebase export from the `auth` package: + * + * ```js + * import { firebase } from '@react-native-firebase/auth'; + * + * // firebase.auth().X + * ``` + * + * #### Example: Using the default export from the `auth` package: + * + * ```js + * import auth from '@react-native-firebase/auth'; + * + * // auth().X + * ``` + * + * #### Example: Using the default export from the `app` package: + * + * ```js + * import firebase from '@react-native-firebase/app'; + * import '@react-native-firebase/auth'; + * + * // firebase.auth().X + * ``` + * TODO @salakar @ehesp missing auth providers (PhoneAuthProvider, Facebook etc) + * + * @firebase auth + */ +/** + * @deprecated Use the exported auth types directly instead. + * FirebaseAuthTypes namespace is kept for backwards compatibility. + */ +/* eslint-disable @typescript-eslint/no-namespace */ +export declare namespace FirebaseAuthTypes { + import FirebaseModule = ReactNativeFirebase.FirebaseModule; + import NativeFirebaseError = ReactNativeFirebase.NativeFirebaseError; + + export interface AuthError extends NativeFirebaseError { + customData?: Record; + } + + export const OperationType: { + LINK: 'link'; + REAUTHENTICATE: 'reauthenticate'; + SIGN_IN: 'signIn'; + }; + + export interface ActionCodeURL { + apiKey: string; + code: string; + continueUrl?: string | null; + languageCode?: string | null; + operation: string; + tenantId?: string | null; + } + + export interface ApplicationVerifier { + readonly type: string; + verify(): Promise; + } + + export interface PasswordPolicy { + readonly enforcementState?: string; + readonly forceUpgradeOnSignin?: boolean; + readonly schemaVersion: number; + } + + export interface NativeFirebaseAuthError extends NativeFirebaseError { + userInfo: { + /** + * When trying to sign in or link with an AuthCredential which was already associated with an account, + * you might receive an updated credential (depending of provider) which you can use to recover from the error. + */ + authCredential: AuthCredential | null; + /** + * When trying to sign in the user might be prompted for a second factor confirmation. Can + * can use this object to initialize the second factor flow and recover from the error. + */ + resolver: MultiFactorResolver | null; + }; + } + + /** + * Interface that represents the credentials returned by an auth provider. Implementations specify the details + * about each auth provider's credential requirements. + * + * TODO Missing; signInMethod, toJSON, fromJSON + * + * #### Example + * + * ```js + * const provider = firebase.auth.EmailAuthProvider; + * const authCredential = provider.credential('foo@bar.com', '123456'); + * + * await firebase.auth().signInWithCredential(authCredential); + * ``` + */ + export interface AuthCredential { + /** + * The authentication provider ID for the credential. For example, 'facebook.com', or 'google.com'. + */ + providerId: string; + token: string; + secret: string; + } + + /** + * Interface that represents an auth provider. Implemented by other providers. + */ + export interface AuthProvider { + /** + * The provider ID of the provider. + */ + PROVIDER_ID: string; + /** + * Creates a new `AuthCredential`. + * + * @returns {@link AuthCredential}. + * @param token A provider token. + * @param secret A provider secret. + */ + credential: (token: string | null, secret?: string) => AuthCredential; + } + + /** + * Interface that represents an OAuth provider. Implemented by other providers. + */ + export interface OAuthProvider extends AuthProvider { + /** + * The provider ID of the provider. + * @param providerId + */ + // eslint-disable-next-line @typescript-eslint/no-misused-new + new (providerId: string): OAuthProvider; + /** + * Creates a new `AuthCredential`. + * + * @returns {@link AuthCredential}. + * @param token A provider token. + * @param secret A provider secret. + */ + credential: (token: string | null, secret?: string) => AuthCredential; + /** + * Sets the OAuth custom parameters to pass in an OAuth request for sign-in + * operations. + * + * @remarks + * For a detailed list, check the reserved required OAuth 2.0 parameters such as `client_id`, + * `redirect_uri`, `scope`, `response_type`, and `state` are not allowed and will be ignored. + * + * @param customOAuthParameters - The custom OAuth parameters to pass in the OAuth request. + */ + setCustomParameters: (customOAuthParameters: Record) => AuthProvider; + /** + * Retrieve the current list of custom parameters. + * @returns The current map of OAuth custom parameters. + */ + getCustomParameters: () => Record; + /** + * Add an OAuth scope to the credential. + * + * @param scope - Provider OAuth scope to add. + */ + addScope: (scope: string) => AuthProvider; + /** + * Retrieve the current list of OAuth scopes. + */ + getScopes: () => string[]; + } + + /** + * Interface that represents an Open ID Connect auth provider. Implemented by other providers. + */ + export interface OIDCProvider { + /** + * The provider ID of the provider. + */ + PROVIDER_ID: string; + /** + * Creates a new `OIDCProvider`. + * + * @returns {@link AuthCredential}. + * @param oidcSuffix this is the "Provider ID" value from the firebase console fx `azure_test`. + * @param token A provider token. + */ + credential: (oidcSuffix: string, idToken: string) => AuthCredential; + } + + /** + * Email and password auth provider implementation. + */ + export interface EmailAuthProvider { + /** + * The provider ID. Always returns `password`. + */ + PROVIDER_ID: string; + /** + * This corresponds to the sign-in method identifier as returned in {@link fetchSignInMethodsForEmail}. + * + * #### Example + * + * ```js + * const signInMethods = await firebase.auth().fetchSignInMethodsForEmail('...'); + * if (signInMethods.indexOf(firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD) != -1) { + * // User can sign in with email/link + * } + * ``` + */ + EMAIL_LINK_SIGN_IN_METHOD: string; + /** + * This corresponds to the sign-in method identifier as returned in {@link fetchSignInMethodsForEmail}. + * + * #### Example + * + * ```js + * const signInMethods = await firebase.auth().fetchSignInMethodsForEmail('...'); + * if (signInMethods.indexOf(firebase.auth.EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD) != -1) { + * // User can sign in with email/password + * } + * ``` + */ + EMAIL_PASSWORD_SIGN_IN_METHOD: string; + /** + * Returns the auth provider credential. + * + * #### Example + * + * ```js + * const authCredential = firebase.auth.EmailAuthProvider.credential('joe.bloggs@example.com', '123456'); + * ``` + * + * @returns {@link AuthCredential} + * @param email Users email address. + * @param password User account password. + */ + credential: (email: string, password: string) => AuthCredential; + /** + * Initialize an `EmailAuthProvider` credential using an email and an email link after a sign in with email link operation. + * + * #### Example + * + * ```js + * const authCredential = firebase.auth.EmailAuthProvider.credentialWithLink('joe.bloggs@example.com', 'https://myexample.com/invite'); + * ``` + * + * @param email Users email address. + * @param emailLink Sign-in email link. + */ + credentialWithLink: (email: string, emailLink: string) => AuthCredential; + } + + /** + * + */ + export interface PhoneAuthState { + /** + * SMS message with verification code sent to phone number. + */ + CODE_SENT: 'sent'; + /** + * The timeout specified in {@link verifyPhoneNumber} has expired. + */ + AUTO_VERIFY_TIMEOUT: 'timeout'; + /** + * Phone number auto-verification succeeded. + */ + AUTO_VERIFIED: 'verified'; + /** + * Phone number verification failed with an error. + */ + ERROR: 'error'; + } + + export interface MultiFactorSession { + // this is has no documented contents, it is simply returned from some APIs and passed to others + } + + export interface PhoneMultiFactorGenerator { + /** + * Identifies second factors of type phone. + */ + FACTOR_ID: FactorId.PHONE; + + /** + * Build a MultiFactorAssertion to resolve the multi-factor sign in process. + */ + assertion(credential: AuthCredential): MultiFactorAssertion; + } + + /** + * Represents a TOTP secret that is used for enrolling a TOTP second factor. + * Contains the shared secret key and other parameters to generate time-based + * one-time passwords. Implements methods to retrieve the shared secret key, + * generate a QR code URL, and open the QR code URL in an OTP authenticator app. + * + * Differs from standard firebase JS implementation in three ways: + * 1- there is no visibility into ony properties other than the secretKey + * 2- there is an added `openInOtpApp` method supported by native SDKs + * 3- the return value of generateQrCodeUrl is a Promise because react-native bridge is async + * @public + */ + export class TotpSecret { + /** used internally to support non-default auth instances */ + private readonly auth; + /** + * Shared secret key/seed used for enrolling in TOTP MFA and generating OTPs. + */ + readonly secretKey: string; + + private constructor(); + + /** + * Returns a QR code URL as described in + * https://github.com/google/google-authenticator/wiki/Key-Uri-Format + * This can be displayed to the user as a QR code to be scanned into a TOTP app like Google Authenticator. + * If the optional parameters are unspecified, an accountName of userEmail and issuer of firebaseAppName are used. + * + * @param accountName the name of the account/app along with a user identifier. + * @param issuer issuer of the TOTP (likely the app name). + * @returns A Promise that resolves to a QR code URL string. + */ + generateQrCodeUrl(accountName?: string, issuer?: string): Promise; + + /** + * Opens the specified QR Code URL in an OTP authenticator app on the device. + * The shared secret key and account name will be populated in the OTP authenticator app. + * The URL uses the otpauth:// scheme and will be opened on an app that handles this scheme, + * if it exists on the device, possibly opening the ecocystem-specific app store with a generic + * query for compatible apps if no app exists on the device. + * + * @param qrCodeUrl the URL to open in the app, from generateQrCodeUrl + */ + openInOtpApp(qrCodeUrl: string): string; + } + + export interface TotpMultiFactorGenerator { + FACTOR_ID: FactorId.TOTP; + + assertionForSignIn(uid: string, totpSecret: string): MultiFactorAssertion; + + assertionForEnrollment(secret: TotpSecret, code: string): MultiFactorAssertion; + + /** + * @param auth - The Auth instance. Only used for native platforms, should be ignored on web. + */ + generateSecret( + session: FirebaseAuthTypes.MultiFactorSession, + auth: FirebaseAuthTypes.Module, + ): Promise; + } + + export interface MultiFactorError extends AuthError { + /** Details about the MultiFactorError. */ + readonly customData: AuthError['customData'] & { + /** + * The type of operation (sign-in, linking, or re-authentication) that raised the error. + */ + readonly operationType: (typeof OperationType)[keyof typeof OperationType]; + }; + } + + /** + * firebase.auth.X + */ + export interface Statics { + /** + * Return the #{@link MultiFactorUser} instance for the current user. + */ + multiFactor: multiFactor; + /** + * Try and obtain a #{@link MultiFactorResolver} instance based on an error. + * Returns null if no resolver object could be found. + * + */ + getMultiFactorResolver: getMultiFactorResolver; + /** + * Email and password auth provider implementation. + * + * #### Example + * + * ```js + * firebase.auth.EmailAuthProvider; + * ``` + */ + EmailAuthProvider: EmailAuthProvider; + /** + * Phone auth provider implementation. + * + * #### Example + * + * ```js + * firebase.auth.PhoneAuthProvider; + * ``` + */ + PhoneAuthProvider: AuthProvider; + /** + * Google auth provider implementation. + * + * #### Example + * + * ```js + * firebase.auth.GoogleAuthProvider; + * ``` + */ + GoogleAuthProvider: AuthProvider; + /** + * Apple auth provider implementation. Currently this is iOS only. + * + * For Apple Authentication please see our [`@invertase/react-native-apple-authentication`](https://github.com/invertase/react-native-apple-authentication) library which integrates well with Firebase and provides Firebase + Apple Auth examples. + * + * #### Example + * + * ```js + * firebase.auth.AppleAuthProvider; + * ``` + */ + AppleAuthProvider: AuthProvider; + /** + * Github auth provider implementation. + * + * #### Example + * + * ```js + * firebase.auth.GithubAuthProvider; + * ``` + */ + GithubAuthProvider: AuthProvider; + /** + * Twitter auth provider implementation. + * + * #### Example + * + * ```js + * firebase.auth.TwitterAuthProvider; + * ``` + */ + TwitterAuthProvider: AuthProvider; + /** + * Facebook auth provider implementation. + * + * #### Example + * + * ```js + * firebase.auth.FacebookAuthProvider; + * ``` + */ + FacebookAuthProvider: AuthProvider; + /** + * Custom OAuth auth provider implementation. + * + * #### Example + * + * ```js + * firebase.auth.OAuthProvider; + * ``` + */ + OAuthProvider: OAuthProvider; + /** + * Custom Open ID connect auth provider implementation. + * + * #### Example + * + * ```js + * firebase.auth.OIDCAuthProvider; + * ``` + */ + OIDCAuthProvider: OIDCProvider; + /** + * A PhoneAuthState interface. + * + * #### Example + * + * ```js + * firebase.auth.PhoneAuthState; + * ``` + */ + PhoneAuthState: PhoneAuthState; + + /** + * A PhoneMultiFactorGenerator interface. + */ + PhoneMultiFactorGenerator: PhoneMultiFactorGenerator; + SDK_VERSION: string; + } + + /** + * A structure containing additional user information from a federated identity provider via {@link UserCredential}. + * + * #### Example + * + * ```js + * const userCredential = await firebase.auth().signInAnonymously(); + * console.log('Additional user info: ', userCredential.additionalUserInfo); + * ``` + * + * @error auth/operation-not-allowed Thrown if anonymous accounts are not enabled. Enable anonymous accounts in the Firebase Console, under the Auth tab. + */ + export interface AdditionalUserInfo { + /** + * Returns whether the user is new or existing. + */ + isNewUser: boolean; + /** + * Returns an Object containing IDP-specific user data if the provider is one of Facebook, + * GitHub, Google, Twitter, Microsoft, or Yahoo. + */ + profile?: Record; + /** + * Returns the provider ID for specifying which provider the information in `profile` is for. + */ + providerId: string; + /** + * Returns the username if the provider is GitHub or Twitter. + */ + username?: string; + } + + /** + * A structure containing a User, an AuthCredential, the operationType, and any additional user + * information that was returned from the identity provider. operationType could be 'signIn' for + * a sign-in operation, 'link' for a linking operation and 'reauthenticate' for a re-authentication operation. + * + * TODO @salakar; missing credential, operationType + */ + export interface UserCredential { + /** + * Any additional user information assigned to the user. + */ + additionalUserInfo?: AdditionalUserInfo; + /** + * Returns the {@link User} interface of this credential. + */ + user: User; + } + + /** + * Holds the user metadata for the current {@link User}. + * + * #### Example + * + * ```js + * const user = firebase.auth().currentUser; + * console.log('User metadata: ', user.metadata); + * ``` + */ + export interface UserMetadata { + /** + * Returns the timestamp at which this account was created as dictated by the server clock + * as an ISO Date string. + */ + creationTime?: string; + /** + * Returns the last signin timestamp as dictated by the server clock as an ISO Date string. + * This is only accurate up to a granularity of 2 minutes for consecutive sign-in attempts. + */ + lastSignInTime?: string; + } + + /** + * Identifies the type of a second factor. + */ + export enum FactorId { + PHONE = 'phone', + TOTP = 'totp', + } + + /** + * Contains information about a second factor. + */ + export type MultiFactorInfo = PhoneMultiFactorInfo | TotpMultiFactorInfo; + + export interface PhoneMultiFactorInfo extends MultiFactorInfoCommon { + factorId: 'phone'; + /** + * The phone number used for this factor. + */ + phoneNumber: string; + } + + export interface TotpMultiFactorInfo extends MultiFactorInfoCommon { + factorId: 'totp'; + } + + export interface MultiFactorInfoCommon { + /** + * User friendly name for this factor. + */ + displayName?: string; + /** + * Time the second factor was enrolled, in UTC. + */ + enrollmentTime: string; + /** + * Unique id for this factor. + */ + uid: string; + } + + export interface MultiFactorAssertion { + token: string; + secret: string; + } + + export interface PhoneMultiFactorEnrollInfoOptions { + phoneNumber: string; + session: MultiFactorSession; + } + + export interface PhoneMultiFactorSignInInfoOptions { + multiFactorHint?: MultiFactorInfo; + + /** + * Unused in react-native-firebase ipmlementation + */ + multiFactorUid?: string; + + session: MultiFactorSession; + } + + /** + * Facilitates the recovery when a user needs to provide a second factor to sign-in. + */ + export interface MultiFactorResolver { + /** + * A list of enrolled factors that can be used to complete the multi-factor challenge. + */ + hints: MultiFactorInfo[]; + /** + * Serialized session this resolver belongs to. + */ + session: MultiFactorSession; + + /** + * For testing purposes only + */ + _auth?: FirebaseAuthTypes.Module; + + /** + * Resolve the multi factor flow. + */ + resolveSignIn(assertion: MultiFactorAssertion): Promise; + } + + /** + * Try and obtain a #{@link MultiFactorResolver} instance based on an error. + * Returns null if no resolver object could be found. + * + * #### Example + * + * ```js + * const auth = firebase.auth(); + * auth.signInWithEmailAndPassword(email, password).then((user) => { + * // signed in + * }).catch((error) => { + * if (error.code === 'auth/multi-factor-auth-required') { + * const resolver = getMultiFactorResolver(auth, error); + * } + * }); + * ``` + */ + export type getMultiFactorResolver = ( + auth: FirebaseAuthTypes.Module, + error: unknown, + ) => MultiFactorResolver | null; + + /** + * The entry point for most multi-factor operations. + */ + export interface MultiFactorUser { + /** + * Returns the user's enrolled factors. + */ + enrolledFactors: MultiFactorInfo[]; + + /** + * Return the session for this user. + */ + getSession(): Promise; + + /** + * Enroll an additional factor. Provide an optional display name that can be shown to the user. + * The method will ensure the user state is reloaded after successfully enrolling a factor. + */ + enroll(assertion: MultiFactorAssertion, displayName?: string): Promise; + + /** + * Unenroll a previously enrolled multi-factor authentication factor. + * @param option The multi-factor option to unenroll. + */ + unenroll(option: MultiFactorInfo | string): Promise; + } + + /** + * Return the #{@link MultiFactorUser} instance for the current user. + */ + export type multiFactor = (auth: FirebaseAuthTypes.Module) => Promise; + + /** + * Holds information about the user's enrolled factors. + * + * #### Example + * + * ```js + * const user = firebase.auth().currentUser; + * console.log('User multi factors: ', user.multiFactor); + * ``` + */ + export interface MultiFactor { + /** + * Returns the enrolled factors + */ + enrolledFactors: MultiFactorInfo[]; + } + + /** + * Represents a collection of standard profile information for a user. Can be used to expose + * profile information returned by an identity provider, such as Google Sign-In or Facebook Login. + * + * TODO @salakar: isEmailVerified + * + * #### Example + * + * ```js + * const user = firebase.auth().currentUser; + * + * user.providerData.forEach((userInfo) => { + * console.log('User info for provider: ', userInfo); + * }); + * ``` + */ + export interface UserInfo { + /** + * Returns the user's display name, if available. + */ + displayName?: string; + /** + * Returns the email address corresponding to the user's account in the specified provider, if available. + */ + email?: string; + /** + * The phone number normalized based on the E.164 standard (e.g. +16505550101) for the current user. This is null if the user has no phone credential linked to the account. + */ + phoneNumber?: string; + /** + * Returns a url to the user's profile picture, if available. + */ + photoURL?: string; + /** + * Returns the unique identifier of the provider type that this instance corresponds to. + */ + providerId: string; + /** + * Returns a string representing the multi-tenant tenant id. This is null if the user is not associated with a tenant. + */ + tenantId?: string; + /** + * Returns a user identifier as specified by the authentication provider. + */ + uid: string; + } + + /** + * Interface representing ID token result obtained from {@link User#getIdTokenResult}. + * It contains the ID token JWT string and other helper properties for getting different data + * associated with the token as well as all the decoded payload claims. + * + * TODO @salakar validate timestamp types + * + * #### Example + * + * ```js + * const idTokenResult = await firebase.auth().currentUser.getIdTokenResult(); + * console.log('User JWT: ', idTokenResult.token); + * ``` + */ + export interface IdTokenResult { + /** + * The Firebase Auth ID token JWT string. + */ + token: string; + /** + * The authentication time formatted as a UTC string. This is the time the user authenticated + * (signed in) and not the time the token was refreshed. + */ + authTime: string; + /** + * The ID token issued at time formatted as a UTC string. + */ + issuedAtTime: string; + /** + * The ID token expiration time formatted as a UTC string. + */ + expirationTime: string; + /** + * The sign-in provider through which the ID token was obtained (anonymous, custom, + * phone, password, etc). Note, this does not map to provider IDs. + */ + signInProvider: null | string; + /** + * The entire payload claims of the ID token including the standard reserved claims as well as + * the custom claims. + */ + claims: { + [key: string]: any; + }; + } + + /** + * Request used to update user profile information. + * + * #### Example + * + * ```js + * const update = { + * displayName: 'Alias', + * photoURL: 'https://my-cdn.com/assets/user/123.png', + * }; + * + * await firebase.auth().currentUser.updateProfile(update); + * ``` + */ + export interface UpdateProfile { + /** + * An optional display name for the user. Explicitly pass null to clear the displayName. + */ + displayName?: string | null; + /** + * An optional photo URL for the user. Explicitly pass null to clear the photoURL. + */ + photoURL?: string | null; + } + + /** + * A result from a {@link signInWithPhoneNumber} call. + * + * #### Example + * + * ```js + * // Force a new message to be sent + * const result = await firebase.auth().signInWithPhoneNumber('#4423456789'); + * const user = await result.confirm('12345'); + * ``` + */ + export interface ConfirmationResult { + /** + * The phone number authentication operation's verification ID. This can be used along with + * the verification code to initialize a phone auth credential. + */ + verificationId: string | null; + /** + * Finishes the sign in flow. Validates a code that was sent to the users device. + * + * @param verificationCode The code sent to the users device from Firebase. + */ + confirm(verificationCode: string): Promise; + } + + /** + * Android specific options which can be attached to the {@link ActionCodeSettings} object + * to be sent with requests such as {@link User#sendEmailVerification}. + * + * #### Example + * + * ```js + * await firebase.auth().currentUser.sendEmailVerification({ + * android: { + * installApp: true, + * packageName: 'com.awesome.app', + * }, + * }); + * ``` + */ + export interface ActionCodeSettingsAndroid { + /** + * Sets the Android package name. This will try to open the link in an android app if it is installed. + */ + packageName: string; + /** + * 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. + */ + installApp?: boolean; + /** + * 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. The Android app needs to be registered in the Console. + */ + minimumVersion?: string; + } + + /** + * Additional data returned from a {@link checkActionCode} call. + * For the PASSWORD_RESET, VERIFY_EMAIL, and RECOVER_EMAIL actions, this object contains an email field with the address the email was sent to. + * For the RECOVER_EMAIL action, which allows a user to undo an email address change, this object also contains a fromEmail field with the user account's new email address. After the action completes, the user's email address will revert to the value in the email field from the value in fromEmail field. + * + * #### Example + * + * ```js + * const actionCodeInfo = await firebase.auth().checkActionCode('ABCD'); + *Data + * console.log('Action code email: ', actionCodeInfo.data.email); + * console.log('Action code from email: ', actionCodeInfo.data.fromEmail); + * ``` + */ + export interface ActionCodeInfoData { + /** + * This signifies the email before the call was made. + */ + email?: string; + /** + * This signifies the current email associated with the account, which may have changed as a result of the {@link checkActionCode} call performed. + */ + fromEmail?: string; + } + + /** + * The interface returned from a {@link checkActionCode} call. + * + * #### Example + * + * ```js + * const actionCodeInfo = await firebase.auth().checkActionCode('ABCD'); + * console.log('Action code operation: ', actionCodeInfo.operation); + * ``` + */ + export interface ActionCodeInfo { + /** + * The data associated with the action code. + */ + data: ActionCodeInfoData; + /** + * The operation from where the action originated. + */ + operation: 'PASSWORD_RESET' | 'VERIFY_EMAIL' | 'RECOVER_EMAIL' | 'EMAIL_SIGNIN' | 'ERROR'; + } + + /** + * iOS specific options which can be attached to the {@link ActionCodeSettings} object + * to be sent with requests such as {@link User#sendEmailVerification}. + * + * #### Example + * + * ```js + * await firebase.auth().currentUser.sendEmailVerification({ + * iOS: { + * bundleId: '123456', + * }, + * }); + * ``` + */ + export interface ActionCodeSettingsIos { + /** + * Sets the iOS bundle ID. This will try to open the link in an iOS app if it is installed. The iOS app needs to be registered in the Console. + */ + bundleId?: string; + } + + /** + * Options to be sent with requests such as {@link User#sendEmailVerification}. + * + * #### Example + * + * ```js + * await firebase.auth().currentUser.sendEmailVerification({ + * handleCodeInApp: true, + * url: 'app/email-verification', + * }); + * ``` + */ + export interface ActionCodeSettings { + /** + * Android specific settings. + */ + android?: ActionCodeSettingsAndroid; + + /** + * Whether the email action link will be opened in a mobile app or a web link first. The default is false. When set to true, the action code link will be be sent as a Universal Link or Android App Link and will be opened by the app if installed. In the false case, the code will be sent to the web widget first and then on continue will redirect to the app if installed. + */ + handleCodeInApp?: boolean; + + /** + * iOS specific settings. + */ + iOS?: ActionCodeSettingsIos; + + /** + * Sets the dynamic link domain (or subdomain) 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 one. If none is provided, the first domain is used by default. + * Deprecated - use {@link ActionCodeSettings.linkDomain} instead. + */ + dynamicLinkDomain?: string; + + /** + * This URL represents the state/Continue URL in the form of a universal link. This URL can should be constructed as a universal link that would either directly open the app where the action code would be handled or continue to the app after the action code is handled by Firebase. + */ + url: string; + /** + * Firebase Dynamic Links is deprecated and will be shut down as early as August * 2025. + * Instead, use ActionCodeSettings.linkDomain to set a a custom domain. Learn more at: https://firebase.google.com/support/dynamic-links-faq + */ + linkDomain?: string; + } + + /** + * An auth listener callback function for {@link onAuthStateChanged}. + * + * #### Example + * + * ```js + * function listener(user) { + * if (user) { + * // Signed in + * } else { + * // Signed out + * } + * } + * + * firebase.auth().onAuthStateChanged(listener); + * ``` + */ + export type AuthListenerCallback = (user: User | null) => void; + + /** + * A snapshot interface of the current phone auth state. + * + * #### Example + * + * ```js + * firebase.auth().verifyPhoneNumber('+4423456789') + * .on('state_changed', (phoneAuthSnapshot) => { + * console.log('Snapshot state: ', phoneAuthSnapshot.state); + * }); + * ``` + */ + export interface PhoneAuthSnapshot { + /** + * The current phone auth verification state. + * + * - `sent`: On iOS, this is the final event received. Once sent, show a visible input box asking the user to enter the verification code. + * - `timeout`: Auto verification has timed out. Show a visible input box asking the user to enter the verification code. + * - `verified`: The verification code has automatically been verified by the Android device. The snapshot contains the verification ID & code to create a credential. + * - `error`: An error occurred. Handle or allow the promise to reject. + */ + state: 'sent' | 'timeout' | 'verified' | 'error'; + /** + * The verification ID to build a `PhoneAuthProvider` credential. + */ + verificationId: string; + /** + * The verification code. Will only be available if auto verification has taken place. + */ + code: string | null; + /** + * A native JavaScript error if an error occurs. + */ + error: NativeFirebaseError | null; + } + + /** + * A custom error in the event verifying a phone number failed. + * + * #### Example + * + * ```js + * firebase.auth().verifyPhoneNumber('+4423456789') + * .on('state_changed', (phoneAuthSnapshot) => { + * console.log('Snapshot state: ', phoneAuthSnapshot.state); + * }, (phoneAuthError) => { + * console.error('Error: ', phoneAuthError.message); + * }); + * ``` + */ + export interface PhoneAuthError { + /** + * The code the verification failed with. + */ + code: string | null; + /** + * The verification ID which failed. + */ + verificationId: string; + /** + * JavaScript error message. + */ + message: string | null; + /** + * JavaScript error stack trace. + */ + stack: string | null; + } + + /** + * The listener function returned from a {@link verifyPhoneNumber} call. + */ + export interface PhoneAuthListener { + /** + * The phone auth state listener. See {@link PhoneAuthState} for different event state types. + * + * #### Example + * + * ```js + * firebase.auth().verifyPhoneNumber('+4423456789') + * .on('state_changed', (phoneAuthSnapshot) => { + * console.log('State: ', phoneAuthSnapshot.state); + * }, (error) => { + * console.error(error); + * }, (phoneAuthSnapshot) => { + * console.log('Success'); + * }); + * ``` + * + * @param event The event to subscribe to. Currently only `state_changed` is available. + * @param observer The required observer function. Returns a new phone auth snapshot on each event. + * @param errorCb An optional error handler function. This is not required if the `error` snapshot state is being handled in the `observer`. + * @param successCb An optional success handler function. This is not required if the `sent` or `verified` snapshot state is being handled in the `observer`. + */ + on( + event: string, + observer: (snapshot: PhoneAuthSnapshot) => void, + errorCb?: (error: PhoneAuthError) => void, + successCb?: (snapshot: PhoneAuthSnapshot) => void, + ): PhoneAuthListener; + + /** + * A promise handler called once the `on` listener flow has succeeded or rejected. + * + * #### Example + * + * ```js + * firebase.auth().verifyPhoneNumber('+4423456789') + * .on('state_changed', (phoneAuthSnapshot) => { + * if (phoneAuthSnapshot.state === firebase.auth.PhoneAuthState.CODE_SENT) { + * return Promise.resolve(); + * } else { + * return Promise.reject( + * new Error('Code not sent!') + * ); + * } + * }) + * .then((phoneAuthSnapshot) => { + * console.log(phoneAuthSnapshot.state); + * }, (error) => { + * console.error(error.message); + * }); + * ``` + * + * @param onFulfilled Resolved promise handler. + * @param onRejected Rejected promise handler. + */ + then( + onFulfilled?: ((a: PhoneAuthSnapshot) => any) | null, + onRejected?: ((a: NativeFirebaseError) => any) | null, + ): Promise; + + /** + * A promise handler called once the `on` listener flow has rejected. + * + * #### Example + * + * ```js + * firebase.auth().verifyPhoneNumber('+4423456789') + * .on('state_changed', (phoneAuthSnapshot) => { + * return Promise.reject( + * new Error('Code not sent!') + * ); + * }) + * .catch((error) => { + * console.error(error.message); + * }); + * ``` + * + * > Used when no `onRejected` handler is passed to {@link PhoneAuthListener#then}. + * + * @param onRejected Rejected promise handler. + */ + catch(onRejected: (a: NativeFirebaseError) => any): Promise; + } + + /** + * Interface for module auth settings. + * + * #### Example + * + * ```js + * const settings = firebase.auth().settings; + * console.log(settings.appVerificationDisabledForTesting); + * ``` + */ + export interface AuthSettings { + /** + * Forces application verification to use the web reCAPTCHA flow for Phone Authentication. + * + * Once this has been called, every call to PhoneAuthProvider#verifyPhoneNumber() will skip the Play Integrity API verification flow and use the reCAPTCHA flow instead. + * + * > Calling this method a second time will overwrite the previously passed parameter. + * + * @android + * @param appName + * @param forceRecaptchaFlow + * @param promise + */ + forceRecaptchaFlowForTesting: boolean; + + /** + * Flag to disable app verification for the purpose of testing phone authentication. For this property to take effect, it needs to be set before rendering a reCAPTCHA app verifier. When this is disabled, a mock reCAPTCHA is rendered instead. This is useful for manual testing during development or for automated integration tests. + * + * > In order to use this feature, you will need to [whitelist your phone number](https://firebase.google.com/docs/auth/web/phone-auth#test-with-whitelisted-phone-numbers) via the Firebase Console. + * + * @param disabled Boolean value representing whether app verification should be disabled for testing. + */ + appVerificationDisabledForTesting: boolean; + + /** + * Calling this method a second time will overwrite the previously passed parameters. + * Only one number can be configured at a given time. + * + * > The phone number and SMS code here must have been configured in the Firebase Console (Authentication > Sign In Method > Phone). + * + * #### Example + * + * ```js + * await firebase.auth().settings.setAutoRetrievedSmsCodeForPhoneNumber('+4423456789', 'ABCDE'); + * ``` + * + * @android + * @param phoneNumber The users phone number. + * @param smsCode The pre-set SMS code. + */ + setAutoRetrievedSmsCodeForPhoneNumber(phoneNumber: string, smsCode: string): Promise; + } + + /** + * Represents a user's profile information in your Firebase project's user database. It also + * contains helper methods to change or retrieve profile information, as well as to manage that user's authentication state. + * + * #### Example 1 + * + * Subscribing to the users authentication state. + * + * ```js + * firebase.auth().onAuthStateChanged((user) => { + * if (user) { + * console.log('User email: ', user.email); + * } + * }); + * ``` + * + * #### Example 2 + * + * ```js + * const user = firebase.auth().currentUser; + * + * if (user) { + * console.log('User email: ', user.email); + * } + * ``` + */ + export interface User { + /** + * The user's display name (if available). + */ + displayName: string | null; + /** + * - The user's email address (if available). + */ + email: string | null; + /** + * - True if the user's email address has been verified. + */ + emailVerified: boolean; + /** + * Returns true if the user is anonymous; that is, the user account was created with + * {@link signInAnonymously} and has not been linked to another account + * with {@link linkWithCredential}. + */ + isAnonymous: boolean; + + /** + * Returns the {@link UserMetadata} associated with this user. + */ + metadata: UserMetadata; + + /** + * Returns the {@link MultiFactor} associated with this user. + */ + multiFactor: MultiFactor | null; + + /** + * Returns the phone number of the user, as stored in the Firebase project's user database, + * or null if none exists. This can be updated at any time by calling {@link User#updatePhoneNumber}. + */ + phoneNumber: string | null; + + /** + * The URL of the user's profile picture (if available). + */ + photoURL: string | null; + + /** + * Additional provider-specific information about the user. + */ + providerData: UserInfo[]; + + /** + * The authentication provider ID for the current user. + * For example, 'facebook.com', or 'google.com'. + */ + providerId: string; + + /** + * - The user's unique ID. + */ + uid: string; + + /** + * Delete the current user. + * + * #### Example + * + * ```js + * await firebase.auth().currentUser.delete(); + * ``` + * + * @error auth/requires-recent-login Thrown if the user's last sign-in time does not meet the security threshold. Use `auth.User#reauthenticateWithCredential` to resolve. This does not apply if the user is anonymous. + */ + delete(): Promise; + + /** + * Returns the users authentication token. + * + * #### Example + * + * ```js + * // Force a token refresh + * const idToken = await firebase.auth().currentUser.getIdToken(true); + * ``` + * + * @param forceRefresh A boolean value which forces Firebase to refresh the token. + */ + getIdToken(forceRefresh?: boolean): Promise; + + /** + * Returns a firebase.auth.IdTokenResult object which contains the ID token JWT string and + * other helper properties for getting different data associated with the token as well as + * all the decoded payload claims. + * + * #### Example + * + * ```js + * // Force a token refresh + * const idTokenResult = await firebase.auth().currentUser.getIdTokenResult(true); + * ``` + * + * @param forceRefresh boolean Force refresh regardless of token expiration. + */ + getIdTokenResult(forceRefresh?: boolean): Promise; + + /** + * Link the user with a 3rd party credential provider. + * + * #### Example + * + * ```js + * const facebookCredential = firebase.auth.FacebookAuthProvider.credential('access token from Facebook'); + * const userCredential = await firebase.auth().currentUser.linkWithCredential(facebookCredential); + * ``` + * + * @error auth/provider-already-linked Thrown if the provider has already been linked to the user. This error is thrown even if this is not the same provider's account that is currently linked to the user. + * @error auth/invalid-credential Thrown if the provider's credential is not valid. This can happen if it has already expired when calling link, or if it used invalid token(s). See the Firebase documentation for your provider, and make sure you pass in the correct parameters to the credential method. + * @error auth/credential-already-in-use Thrown if the account corresponding to the credential already exists among your users, or is already linked to a Firebase User. + * @error auth/email-already-in-use Thrown if the email corresponding to the credential already exists among your users. + * @error auth/operation-not-allowed Thrown if you have not enabled the provider in the Firebase Console. Go to the Firebase Console for your project, in the Auth section and the Sign in Method tab and configure the provider. + * @error auth/invalid-email Thrown if the email used in a auth.EmailAuthProvider.credential is invalid. + * @error auth/wrong-password Thrown if the password used in a auth.EmailAuthProvider.credential is not correct or when the user associated with the email does not have a password. + * @error auth/invalid-verification-code Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. + * @error auth/invalid-verification-id Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. + * @throws on iOS {@link NativeFirebaseAuthError}, on Android {@link NativeFirebaseError} + * @param credential A created {@link AuthCredential}. + */ + linkWithCredential(credential: AuthCredential): Promise; + + /** + * Link the user with a federated 3rd party credential provider (Microsoft, Yahoo). + * The APIs here are the web-compatible linkWithPopup and linkWithRedirect but both + * share the same underlying native SDK behavior and may be used interchangably. + * + * #### Example + * + * ```js + * const provider = new firebase.auth.OAuthProvider('microsoft.com'); + * const userCredential = await firebase.auth().currentUser.linkWithPopup(provider); + * ``` + * + * @error auth/provider-already-linked Thrown if the provider has already been linked to the user. This error is thrown even if this is not the same provider's account that is currently linked to the user. + * @error auth/invalid-credential Thrown if the provider's credential is not valid. This can happen if it has already expired when calling link, or if it used invalid token(s). See the Firebase documentation for your provider, and make sure you pass in the correct parameters to the credential method. + * @error auth/credential-already-in-use Thrown if the account corresponding to the credential already exists among your users, or is already linked to a Firebase User. + * @error auth/email-already-in-use Thrown if the email corresponding to the credential already exists among your users. + * @error auth/operation-not-allowed Thrown if you have not enabled the provider in the Firebase Console. Go to the Firebase Console for your project, in the Auth section and the Sign in Method tab and configure the provider. + * @error auth/invalid-email Thrown if the email used in a auth.EmailAuthProvider.credential is invalid. + * @error auth/wrong-password Thrown if the password used in a auth.EmailAuthProvider.credential is not correct or when the user associated with the email does not have a password. + * @error auth/invalid-verification-code Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. + * @error auth/invalid-verification-id Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. + * @throws on iOS {@link NativeFirebaseAuthError}, on Android {@link NativeFirebaseError} + * @param provider A created {@link AuthProvider}. + */ + linkWithPopup(provider: AuthProvider): Promise; + + /** + * Link the user with a federated 3rd party credential provider (Microsoft, Yahoo). + * The APIs here are the web-compatible linkWithPopup and linkWithRedirect but both + * share the same underlying native SDK behavior and may be used interchangably. + * + * #### Example + * + * ```js + * const provider = new firebase.auth.OAuthProvider('microsoft.com'); + * const userCredential = await firebase.auth().currentUser.linkWithRedirect(provider); + * ``` + * + * @error auth/provider-already-linked Thrown if the provider has already been linked to the user. This error is thrown even if this is not the same provider's account that is currently linked to the user. + * @error auth/invalid-credential Thrown if the provider's credential is not valid. This can happen if it has already expired when calling link, or if it used invalid token(s). See the Firebase documentation for your provider, and make sure you pass in the correct parameters to the credential method. + * @error auth/credential-already-in-use Thrown if the account corresponding to the credential already exists among your users, or is already linked to a Firebase User. + * @error auth/email-already-in-use Thrown if the email corresponding to the credential already exists among your users. + * @error auth/operation-not-allowed Thrown if you have not enabled the provider in the Firebase Console. Go to the Firebase Console for your project, in the Auth section and the Sign in Method tab and configure the provider. + * @error auth/invalid-email Thrown if the email used in a auth.EmailAuthProvider.credential is invalid. + * @error auth/wrong-password Thrown if the password used in a auth.EmailAuthProvider.credential is not correct or when the user associated with the email does not have a password. + * @error auth/invalid-verification-code Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. + * @error auth/invalid-verification-id Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. + * @throws on iOS {@link NativeFirebaseAuthError}, on Android {@link NativeFirebaseError} + * @param provider A created {@link AuthProvider}. + */ + linkWithRedirect(provider: AuthProvider): Promise; + + /** + * Re-authenticate a user with a third-party authentication provider. + * + * #### Example + * + * ```js + * const facebookCredential = firebase.auth.FacebookAuthProvider.credential('access token from Facebook'); + * const userCredential = await firebase.auth().currentUser.reauthenticateWithCredential(facebookCredential); + * ``` + * + * @error auth/user-mismatch Thrown if the credential given does not correspond to the user. + * @error auth/user-not-found Thrown if the credential given does not correspond to any existing user. + * @error auth/invalid-credential Thrown if the provider's credential is not valid. This can happen if it has already expired when calling link, or if it used invalid token(s). See the Firebase documentation for your provider, and make sure you pass in the correct parameters to the credential method. + * @error auth/invalid-email Thrown if the email used in a auth.EmailAuthProvider.credential is invalid. + * @error auth/wrong-password Thrown if the password used in a auth.EmailAuthProvider.credential is not correct or when the user associated with the email does not have a password. + * @error auth/invalid-verification-code Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. + * @error auth/invalid-verification-id Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. + * @param credential A created {@link AuthCredential}. + */ + reauthenticateWithCredential(credential: AuthCredential): Promise; + + /** + * Re-authenticate a user with a federated authentication provider (Microsoft, Yahoo). For native platforms, this will open a browser window. + * #### Example + * + * ```js + * const provider = new firebase.auth.OAuthProvider('microsoft.com'); + * const userCredential = await firebase.auth().currentUser.reauthenticateWithProvider(provider); + * ``` + * + * @error auth/user-mismatch Thrown if the credential given does not correspond to the user. + * @error auth/user-not-found Thrown if the credential given does not correspond to any existing user. + * @error auth/invalid-credential Thrown if the provider's credential is not valid. This can happen if it has already expired when calling link, or if it used invalid token(s). See the Firebase documentation for your provider, and make sure you pass in the correct parameters to the credential method. + * @error auth/invalid-email Thrown if the email used in a auth.EmailAuthProvider.credential is invalid. + * @error auth/wrong-password Thrown if the password used in a auth.EmailAuthProvider.credential is not correct or when the user associated with the email does not have a password. + * @error auth/invalid-verification-code Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. + * @error auth/invalid-verification-id Thrown if the credential is a auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. + * @param provider A created {@link AuthProvider}. + * @returns A promise that resolves with no value. + */ + reauthenticateWithRedirect(provider: AuthProvider): Promise; + /** + * Re-authenticate a user with a federated authentication provider (Microsoft, Yahoo). For native platforms, this will open a browser window. + * pop-up equivalent on native platforms. + * + * @param provider - The auth provider. + * @returns A promise that resolves with the user credentials. + */ + reauthenticateWithPopup(provider: AuthProvider): Promise; + /** + * Refreshes the current user. + * + * #### Example + * + * ```js + * await firebase.auth().currentUser.reload(); + * ``` + */ + reload(): Promise; + + /** + * Sends a verification email to a user. + * + * #### Example + * + * ```js + * await firebase.auth().currentUser.sendEmailVerification({ + * handleCodeInApp: true, + * }); + * ``` + * + * > This will Promise reject if the user is anonymous. + * + * @error auth/missing-android-pkg-name An Android package name must be provided if the Android app is required to be installed. + * @error auth/missing-continue-uri A continue URL must be provided in the request. + * @error auth/missing-ios-bundle-id An iOS bundle ID must be provided if an App Store ID is provided. + * @error auth/invalid-continue-uri The continue URL provided in the request is invalid. + * @error auth/unauthorized-continue-uri The domain of the continue URL is not whitelisted. Whitelist the domain in the Firebase console. + * @param actionCodeSettings Any optional additional settings to be set before sending the verification email. + */ + sendEmailVerification(actionCodeSettings?: ActionCodeSettings): Promise; + /** + * Sends a link to the user's email address, when clicked, the user's Authentication email address will be updated to whatever + * was passed as the first argument. + * + * #### Example + * + * ```js + * await firebase.auth().currentUser.verifyBeforeUpdateEmail( + * 'foo@emailaddress.com', + * { + * handleCodeInApp: true, + * }); + * ``` + * + * > This will Promise reject if the user is anonymous. + * + * @error auth/missing-android-pkg-name An Android package name must be provided if the Android app is required to be installed. + * @error auth/missing-continue-uri A continue URL must be provided in the request. + * @error auth/missing-ios-bundle-id An iOS bundle ID must be provided if an App Store ID is provided. + * @error auth/invalid-continue-uri The continue URL provided in the request is invalid. + * @error auth/unauthorized-continue-uri The domain of the continue URL is not whitelisted. Whitelist the domain in the Firebase console. + * @param actionCodeSettings Any optional additional settings to be set before sending the verification email. + */ + verifyBeforeUpdateEmail(email: string, actionCodeSettings?: ActionCodeSettings): Promise; + + /** + * Returns a JSON-serializable representation of this object. + * + * #### Example + * + * ```js + * const user = firebase.auth().currentUser.toJSON(); + * ``` + */ + toJSON(): object; + + /** + * Unlinks a provider from a user account. + * + * #### Example + * + * ```js + * const user = await firebase.auth().currentUser.unlink('facebook.com'); + * ``` + * + * @error auth/no-such-provider Thrown if the user does not have this provider linked or when the provider ID given does not exist. + * @param providerId + */ + unlink(providerId: string): Promise; + + /** + * Updates the user's email address. + * + * See Firebase docs for more information on security & email validation. + * + * #### Example + * + * ```js + * await firebase.auth().currentUser.updateEmail('joe.bloggs@new-email.com'); + * ``` + * + * > This will Promise reject if the user is anonymous. + * + * @error auth/invalid-email Thrown if the email used is invalid. + * @error auth/email-already-in-use Thrown if the email is already used by another user. + * @error auth/requires-recent-login Thrown if the user's last sign-in time does not meet the security threshold. + * @param email The users new email address. + */ + updateEmail(email: string): Promise; + + /** + * Updates the users password. + * + * Important: this is a security sensitive operation that requires the user to have recently signed in. + * If this requirement isn't met, ask the user to authenticate again and then call firebase.User#reauthenticate. + * + * #### Example + * + * ```js + * await firebase.auth().currentUser.updatePassword('654321'); + * ``` + * + * > This will Promise reject is the user is anonymous. + * + * @error auth/weak-password Thrown if the password is not strong enough. + * @error auth/requires-recent-login Thrown if the user's last sign-in time does not meet the security threshold. + * @param password The users new password. + */ + updatePassword(password: string): Promise; + + /** + * Updates the user's phone number. + * + * See Firebase docs for more information on security & email validation. + * + * #### Example + * + * ```js + * const snapshot = await firebase.auth().verifyPhoneNumber('+4423456789') + * .on(...); // See PhoneAuthListener - wait for successful verification + * + * const credential = firebase.auth.PhoneAuthProvider.credential(snapshot.verificationId, snapshot.code); + * + * // Update user with new verified phone number + * await firebase.auth().currentUser.updatePhoneNumber(credential); + * ``` + * + * > This will Promise reject is the user is anonymous. + * + * @error auth/invalid-verification-code Thrown if the verification code of the credential is not valid. + * @error auth/invalid-verification-id Thrown if the verification ID of the credential is not valid. + * @param credential A created `PhoneAuthCredential`. + */ + updatePhoneNumber(credential: AuthCredential): Promise; + + /** + * Updates a user's profile data. + * + * #### Example + * + * ```js + * await firebase.auth().currentUser.updateProfile({ + * displayName: 'Alias', + * }); + * ``` + */ + updateProfile(updates: UpdateProfile): Promise; + } + + /** + * The Firebase Authentication service is available for the default app or a given app. + * + * #### Example 1 + * + * Get the auth instance for the **default app**: + * + * ```js + * const authForDefaultApp = firebase.auth(); + * ``` + * + * #### Example 2 + * + * Get the auth instance for a **secondary app**: + * + * ```js + * const otherApp = firebase.app('otherApp'); + * const authForOtherApp = firebase.auth(otherApp); + * ``` + * + * TODO @salakar missing updateCurrentUser + */ + export class Module extends FirebaseModule { + /** + * The current `FirebaseApp` instance for this Firebase service. + */ + app: ReactNativeFirebase.FirebaseApp; + + /** + * Returns the current tenant Id or null if it has never been set + * + * #### Example + * + * ```js + * const tenantId = firebase.auth().tenantId; + * ``` + */ + tenantId: string | null; + /** + * Returns the current language code. + * + * #### Example + * + * ```js + * const language = firebase.auth().languageCode; + * ``` + */ + get languageCode(): string; + /** + * Returns the current `AuthSettings`. + */ + settings: AuthSettings; + + /** + * Returns the currently signed-in user (or null if no user signed in). See the User interface documentation for detailed usage. + * + * #### Example + * + * ```js + * const user = firebase.auth().currentUser; + * ``` + * + * > It is recommended to use {@link onAuthStateChanged} to track whether the user is currently signed in. + */ + currentUser: User | null; + /** + * Sets the tenant id. + * + * #### Example + * + * ```js + * await firebase.auth().setTenantId('tenant-123'); + * ``` + * + * @error auth/invalid-tenant-id if the tenant id is invalid for some reason + * @param tenantId the tenantID current app bind to. + */ + setTenantId(tenantId: string): Promise; + /** + * Sets the language code. + * + * #### Example + * + * ```js + * // Set language to French + * await firebase.auth().setLanguageCode('fr'); + * ``` + * + * @param code An ISO language code. + * 'null' value will set the language code to the app's current language. + */ + setLanguageCode(languageCode: string | null): Promise; + /** + * Listen for changes in the users auth state (logging in and out). + * This method returns a unsubscribe function to stop listening to events. + * Always ensure you unsubscribe from the listener when no longer needed to prevent updates to components no longer in use. + * + * #### Example + * + * ```js + * const unsubscribe = firebase.auth().onAuthStateChanged((user) => { + * if (user) { + * // Signed in + * } else { + * // Signed out + * } + * }); + * + * // Unsubscribe from further state changes + * unsubscribe(); + * ``` + * + * @param listener A listener function which triggers when auth state changed (for example signing out). + */ + onAuthStateChanged(listener: CallbackOrObserver): () => void; + + /** + * Listen for changes in ID token. + * ID token can be verified (if desired) using the [admin SDK or a 3rd party JWT library](https://firebase.google.com/docs/auth/admin/verify-id-tokens) + * This method returns a unsubscribe function to stop listening to events. + * Always ensure you unsubscribe from the listener when no longer needed to prevent updates to components no longer in use. + * + * #### Example + * + * ```js + * const unsubscribe = firebase.auth().onIdTokenChanged((user) => { + * if (user) { + * // User is signed in or token was refreshed. + * } + * }); + * + * // Unsubscribe from further state changes + * unsubscribe(); + * ``` + * + * @param listener A listener function which triggers when the users ID token changes. + */ + onIdTokenChanged(listener: CallbackOrObserver): () => void; + + /** + * Adds a listener to observe changes to the User object. This is a superset of everything from + * {@link onAuthStateChanged}, {@link onIdTokenChanged} and user changes. The goal of this + * method is to provide easier listening to all user changes, such as when credentials are + * linked and unlinked, without manually having to call {@link User#reload}. + * + * #### Example + * + * ```js + * const unsubscribe = firebase.auth().onUserChanged((user) => { + * if (user) { + * // User is signed in or token was refreshed. + * } + * }); + * + * // Unsubscribe from further state changes + * unsubscribe(); + * ``` + * + * > This is an experimental feature and is only part of React Native Firebase. + * + * @react-native-firebase + * @param listener A listener function which triggers when the users data changes. + */ + onUserChanged(listener: CallbackOrObserver): () => void; + + /** + * Signs the user out. + * + * Triggers the {@link onAuthStateChanged} listener. + * + * #### Example + * + * ```js + * await firebase.auth().signOut(); + * ``` + * + */ + signOut(): Promise; + + /** + * Sign in a user anonymously. If the user has already signed in, that user will be returned. + * + * #### Example + * + * ```js + * const userCredential = await firebase.auth().signInAnonymously(); + * ``` + * + * @error auth/operation-not-allowed Thrown if anonymous accounts are not enabled. Enable anonymous accounts in the Firebase Console, under the Auth tab. + */ + signInAnonymously(): Promise; + + /** + * Signs in the user using their phone number. + * + * #### Example + * + * ```js + * // Force a new message to be sent + * const result = await firebase.auth().signInWithPhoneNumber('#4423456789', true); + * ``` + * + * @error auth/invalid-phone-number Thrown if the phone number has an invalid format. + * @error auth/missing-phone-number Thrown if the phone number is missing. + * @error auth/quota-exceeded Thrown if the SMS quota for the Firebase project has been exceeded. + * @error auth/user-disabled Thrown if the user corresponding to the given phone number has been disabled. + * @error auth/operation-not-allowed Thrown if you have not enabled the provider in the Firebase Console. Go to the Firebase Console for your project, in the Auth section and the Sign in Method tab and configure the provider. + * @param phoneNumber The devices phone number. + * @param forceResend Forces a new message to be sent if it was already recently sent. + */ + signInWithPhoneNumber(phoneNumber: string, forceResend?: boolean): Promise; + + /** + * Returns a PhoneAuthListener to listen to phone verification events, + * on the final completion event a PhoneAuthCredential can be generated for + * authentication purposes. + * + * #### Example + * + * ```js + * firebase.auth().verifyPhoneNumber('+4423456789', ) + * .on('state_changed', (phoneAuthSnapshot) => { + * console.log('Snapshot state: ', phoneAuthSnapshot.state); + * }); + * ``` + * + * @param phoneNumber The phone number identifier supplied by the user. Its format is normalized on the server, so it can be in any format here. (e.g. +16505550101). + * @param autoVerifyTimeoutOrForceResend If a number, sets in seconds how to to wait until auto verification times out. If boolean, sets the `forceResend` parameter. + * @param forceResend If true, resend the verification message even if it was recently sent. + */ + verifyPhoneNumber( + phoneNumber: string, + autoVerifyTimeoutOrForceResend?: number | boolean, + forceResend?: boolean, + ): PhoneAuthListener; + + /** + * Obtain a verification id to complete the multi-factor sign-in flow. + */ + verifyPhoneNumberWithMultiFactorInfo( + hint: MultiFactorInfo, + session: MultiFactorSession, + ): Promise; + + /** + * Send an SMS to the user for verification of second factor + * @param phoneInfoOptions the phone number and session to use during enrollment + */ + verifyPhoneNumberForMultiFactor( + phoneInfoOptions: PhoneMultiFactorEnrollInfoOptions, + ): Promise; + + /** + * Creates a new user with an email and password. + * + * This method also signs the user in once the account has been created. + * + * #### Example + * + * ```js + * const userCredential = await firebase.auth().createUserWithEmailAndPassword('joe.bloggs@example.com', '123456'); + * ``` + * + * @error auth/email-already-in-use Thrown if there already exists an account with the given email address. + * @error auth/invalid-email Thrown if the email address is not valid. + * @error auth/operation-not-allowed Thrown if email/password accounts are not enabled. Enable email/password accounts in the Firebase Console, under the Auth tab. + * @error auth/weak-password Thrown if the password is not strong enough. + * @param email The users email address. + * @param password The users password. + */ + createUserWithEmailAndPassword(email: string, password: string): Promise; + + /** + * Signs a user in with an email and password. + * + * ⚠️ Note: + * If "Email Enumeration Protection" is enabled in your Firebase Authentication settings (enabled by default), + * Firebase may return a generic `auth/invalid-login-credentials` error instead of more specific ones like + * `auth/user-not-found` or `auth/wrong-password`. This behavior is intended to prevent leaking information + * about whether an account with the given email exists. + * + * To receive detailed error codes, you must disable "Email Enumeration Protection", which may increase + * security risks if not properly handled on the frontend. + * + * #### Example + * + * ```js + * const userCredential = await firebase.auth().signInWithEmailAndPassword('joe.bloggs@example.com', '123456'); + * ``` + * + * @error auth/invalid-email Thrown if the email address is not valid. + * @error auth/user-disabled Thrown if the user corresponding to the given email has been disabled. + * @error auth/user-not-found Thrown if there is no user corresponding to the given email. (May be suppressed if email enumeration protection is enabled.) + * @error auth/wrong-password Thrown if the password is invalid or missing. (May be suppressed if email enumeration protection is enabled.) + * @param email The user's email address. + * @param password The user's password. + */ + signInWithEmailAndPassword(email: string, password: string): Promise; + + /** + * Signs a user in with a custom token. + * + * #### Example + * + * ```js + * // Create a custom token via the Firebase Admin SDK. + * const token = await firebase.auth().createCustomToken(uid, customClaims); + * ... + * // Use the token on the device to sign in. + * const userCredential = await firebase.auth().signInWithCustomToken(token); + * ``` + * + * @error auth/custom-token-mismatch Thrown if the custom token is for a different Firebase App. + * @error auth/invalid-custom-token Thrown if the custom token format is incorrect. + * @param customToken A custom token generated from the Firebase Admin SDK. + */ + signInWithCustomToken(customToken: string): Promise; + + /** + * Signs the user in with a generated credential. + * + * #### Example + * + * ```js + * // Generate a Firebase credential + * const credential = firebase.auth.FacebookAuthProvider.credential('access token from Facebook'); + * // Sign the user in with the credential + * const userCredential = await firebase.auth().signInWithCredential(credential); + * ``` + * + * @error auth/account-exists-with-different-credential Thrown if there already exists an account with the email address asserted by the credential. + * @error auth/invalid-credential Thrown if the credential is malformed or has expired. + * @error auth/operation-not-allowed Thrown if the type of account corresponding to the credential is not enabled. Enable the account type in the Firebase Console, under the Auth tab. + * @error auth/user-disabled Thrown if the user corresponding to the given credential has been disabled. + * @error auth/user-not-found Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and there is no user corresponding to the given email. + * @error auth/wrong-password Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and the password is invalid for the given email, or if the account corresponding to the email does not have a password set. + * @error auth/invalid-verification-code Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. + * @error auth/invalid-verification-id Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. + * @param credential A generated `AuthCredential`, for example from social auth. + */ + signInWithCredential(credential: AuthCredential): Promise; + + /** + * Signs the user in with a specified provider. This is a web-compatible API along with signInWithRedirect. + * They both share the same call to the underlying native SDK signInWithProvider method. + * + * #### Example + * + * ```js + * // create a new OAuthProvider + * const provider = firebase.auth.OAuthProvider('microsoft.com'); + * // Sign the user in with the provider + * const userCredential = await firebase.auth().signInWithPopup(provider); + * ``` + * + * @error auth/account-exists-with-different-credential Thrown if there already exists an account with the email address asserted by the credential. + * @error auth/invalid-credential Thrown if the credential is malformed or has expired. + * @error auth/operation-not-allowed Thrown if the type of account corresponding to the credential is not enabled. Enable the account type in the Firebase Console, under the Auth tab. + * @error auth/user-disabled Thrown if the user corresponding to the given credential has been disabled. + * @error auth/user-not-found Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and there is no user corresponding to the given email. + * @error auth/wrong-password Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and the password is invalid for the given email, or if the account corresponding to the email does not have a password set. + * @error auth/invalid-verification-code Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. + * @error auth/invalid-verification-id Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. + * @param provider An `AuthProvider` configured for your desired provider, e.g. "microsoft.com" + */ + signInWithPopup(provider: AuthProvider): Promise; + + /** + * Signs the user in with a specified provider. This is a web-compatible API along with signInWithPopup. + * They both share the same call to the underlying native SDK signInWithProvider method. + * + * #### Example + * + * ```js + * // create a new OAuthProvider + * const provider = firebase.auth.OAuthProvider('microsoft.com'); + * // Sign the user in with the provider + * const userCredential = await firebase.auth().signInWithRedirect(provider); + * ``` + * + * @error auth/account-exists-with-different-credential Thrown if there already exists an account with the email address asserted by the credential. + * @error auth/invalid-credential Thrown if the credential is malformed or has expired. + * @error auth/operation-not-allowed Thrown if the type of account corresponding to the credential is not enabled. Enable the account type in the Firebase Console, under the Auth tab. + * @error auth/user-disabled Thrown if the user corresponding to the given credential has been disabled. + * @error auth/user-not-found Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and there is no user corresponding to the given email. + * @error auth/wrong-password Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and the password is invalid for the given email, or if the account corresponding to the email does not have a password set. + * @error auth/invalid-verification-code Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. + * @error auth/invalid-verification-id Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. + * @param provider An `AuthProvider` configured for your desired provider, e.g. "microsoft.com" + */ + signInWithRedirect(provider: AuthProvider): Promise; + + /** + * Revokes a user's Sign in with Apple token. + * + * #### Example + * + * ```js + * // Generate an Apple ID authorizationCode for the currently logged in user (ie, with @invertase/react-native-apple-authentication) + * const { authorizationCode } = await appleAuth.performRequest({ requestedOperation: appleAuth.Operation.REFRESH }); + * // Revoke the token + * await firebase.auth().revokeToken(authorizationCode); + * ``` + * + * @param authorizationCode A generated authorization code from Sign in with Apple. + */ + revokeToken(authorizationCode: string): Promise; + + /** + * Signs the user in with a federated OAuth provider supported by Firebase (Microsoft, Yahoo). + * + * From Firebase Docs: + * Unlike other OAuth providers supported by Firebase such as Google, Facebook, and Twitter, where + * sign-in can directly be achieved with OAuth access token based credentials, Firebase Auth does not + * support the same capability for providers such as Microsoft due to the inability of the Firebase Auth + * server to verify the audience of Microsoft OAuth access tokens. + * + * #### Example + * ```js + * // Generate an OAuth instance + * const provider = new firebase.auth.OAuthProvider('microsoft.com'); + * // Optionally add scopes to the OAuth instance + * provider.addScope('mail.read'); + * // Optionally add custom parameters to the OAuth instance + * provider.setCustomParameters({ + * prompt: 'consent', + * }); + * // Sign in using the OAuth provider + * const userCredential = await firebase.auth().signInWithProvider(provider); + * ``` + * + * @error auth/account-exists-with-different-credential Thrown if there already exists an account with the email address asserted by the credential. + * @error auth/invalid-credential Thrown if the credential is malformed or has expired. + * @error auth/operation-not-allowed Thrown if the type of account corresponding to the credential is not enabled. Enable the account type in the Firebase Console, under the Auth tab. + * @error auth/user-disabled Thrown if the user corresponding to the given credential has been disabled. + * @error auth/user-not-found Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and there is no user corresponding to the given email. + * @error auth/wrong-password Thrown if signing in with a credential from firebase.auth.EmailAuthProvider.credential and the password is invalid for the given email, or if the account corresponding to the email does not have a password set. + * @error auth/invalid-verification-code Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification code of the credential is not valid. + * @error auth/invalid-verification-id Thrown if the credential is a firebase.auth.PhoneAuthProvider.credential and the verification ID of the credential is not valid. + * @param provider A generated `AuthProvider`, for example from social auth. + */ + signInWithProvider(provider: AuthProvider): Promise; + + /** + * Sends a password reset email to the given email address. + * Unlike the web SDK, the email will contain a password reset link rather than a code. + * + * #### Example + * + * ```js + * await firebase.auth().sendPasswordResetEmail('joe.bloggs@example.com'); + * ``` + * + * @error auth/invalid-email Thrown if the email address is not valid. + * @error auth/missing-android-pkg-name An Android package name must be provided if the Android app is required to be installed. + * @error auth/missing-continue-uri A continue URL must be provided in the request. + * @error auth/missing-ios-bundle-id An iOS Bundle ID must be provided if an App Store ID is provided. + * @error auth/invalid-continue-uri The continue URL provided in the request is invalid. + * @error auth/unauthorized-continue-uri The domain of the continue URL is not whitelisted. Whitelist the domain in the Firebase console. + * @error auth/user-not-found Thrown if there is no user corresponding to the email address. + * @param email The users email address. + * @param actionCodeSettings Additional settings to be set before sending the reset email. + */ + sendPasswordResetEmail(email: string, actionCodeSettings?: ActionCodeSettings): Promise; + + /** + * Sends a sign in link to the user. + * + * #### Example + * + * ```js + * await firebase.auth().sendSignInLinkToEmail('joe.bloggs@example.com'); + * ``` + * + * @error auth/argument-error Thrown if handleCodeInApp is false. + * @error auth/invalid-email Thrown if the email address is not valid. + * @error auth/missing-android-pkg-name An Android package name must be provided if the Android app is required to be installed. + * @error auth/missing-continue-uri A continue URL must be provided in the request. + * @error auth/missing-ios-bundle-id An iOS Bundle ID must be provided if an App Store ID is provided. + * @error auth/invalid-continue-uri The continue URL provided in the request is invalid. + * @error auth/unauthorized-continue-uri The domain of the continue URL is not whitelisted. Whitelist the domain in the Firebase console. + * @param email The users email address. + * @param actionCodeSettings The action code settings. The action code settings which provides Firebase with instructions on how to construct the email link. This includes the sign in completion URL or the deep link for mobile redirects, the mobile apps to use when the sign-in link is opened on an Android or iOS device. Mobile app redirects will only be applicable if the developer configures and accepts the Firebase Dynamic Links terms of condition. The Android package name and iOS bundle ID will be respected only if they are configured in the same Firebase Auth project used. + */ + sendSignInLinkToEmail(email: string, actionCodeSettings?: ActionCodeSettings): Promise; + + /** + * Checks if an incoming link is a sign-in with email link suitable for signInWithEmailLink. + * Note that android and other platforms require `apiKey` link parameter for signInWithEmailLink + * + * #### Example + * + * ```js + * const valid = await firebase.auth().isSignInWithEmailLink(link); + * ``` + * + * @param emailLink The email link to verify prior to using signInWithEmailLink + */ + isSignInWithEmailLink(emailLink: string): Promise; + + /** + * Signs the user in with an email link. + * + * #### Example + * + * ```js + * const userCredential = await firebase.auth().signInWithEmailLink('joe.bloggs@example.com', link); + * ``` + * + * @error auth/expired-action-code Thrown if OTP in email link expires. + * @error auth/invalid-email Thrown if the email address is not valid. + * @error auth/user-disabled Thrown if the user corresponding to the given email has been disabled. + * @param email The users email to sign in with. + * @param emailLink An email link. + */ + signInWithEmailLink(email: string, emailLink: string): Promise; + + /** + * Completes the password reset process with the confirmation code and new password, via + * {@link sendPasswordResetEmail}. + * + * #### Example + * + * ```js + * await firebase.auth().confirmPasswordReset('ABCD', '1234567'); + * ``` + * + * @error auth/expired-action-code Thrown if the password reset code has expired. + * @error auth/invalid-action-code Thrown if the password reset code is invalid. This can happen if the code is malformed or has already been used. + * @error auth/user-disabled Thrown if the user corresponding to the given password reset code has been disabled. + * @error auth/user-not-found Thrown if there is no user corresponding to the password reset code. This may have happened if the user was deleted between when the code was issued and when this method was called. + * @error auth/weak-password Thrown if the new password is not strong enough. + * @param code The code from the password reset email. + * @param newPassword The new password. + */ + confirmPasswordReset(code: string, newPassword: string): Promise; + + /** + * Applies a verification code sent to the user by email or other out-of-band mechanism. + * + * #### Example + * + * ```js + * await firebase.auth().applyActionCode('ABCD'); + * ``` + * + * @error auth/expired-action-code Thrown if the action code has expired. + * @error auth/invalid-action-code Thrown if the action code is invalid. This can happen if the code is malformed or has already been used. + * @error auth/user-disabled Thrown if the user corresponding to the given action code has been disabled. + * @error auth/user-not-found Thrown if there is no user corresponding to the action code. This may have happened if the user was deleted between when the action code was issued and when this method was called. + * @param code A verification code sent to the user. + */ + applyActionCode(code: string): Promise; + + /** + * Checks a verification code sent to the user by email or other out-of-band mechanism. + * + * #### Example + * + * ```js + * const actionCodeInfo = await firebase.auth().checkActionCode('ABCD'); + * console.log('Action code operation: ', actionCodeInfo.operation); + * ``` + * + * @error auth/expired-action-code Thrown if the action code has expired. + * @error auth/invalid-action-code Thrown if the action code is invalid. This can happen if the code is malformed or has already been used. + * @error auth/user-disabled Thrown if the user corresponding to the given action code has been disabled. + * @error auth/user-not-found Thrown if there is no user corresponding to the action code. This may have happened if the user was deleted between when the action code was issued and when this method was called. + * @param code A verification code sent to the user. + */ + checkActionCode(code: string): Promise; + + /** + * Returns a list of authentication methods that can be used to sign in a given user (identified by its main email address). + * + * ⚠️ Note: + * If "Email Enumeration Protection" is enabled in your Firebase Authentication settings (which is the default), + * this method may return an empty array even if the email is registered, especially when called from an unauthenticated context. + * + * This is a security measure to prevent leaking account existence via email enumeration attacks. + * Do not use the result of this method to directly inform the user whether an email is registered. + * + * #### Example + * + * ```js + * const methods = await firebase.auth().fetchSignInMethodsForEmail('joe.bloggs@example.com'); + * + * if (methods.length > 0) { + * // Likely a registered user — offer sign-in + * } else { + * // Could be unregistered OR email enumeration protection is active — offer registration + * } + * ``` + * + * @error auth/invalid-email Thrown if the email address is not valid. + * @param email The user's email address. + */ + fetchSignInMethodsForEmail(email: string): Promise; + + /** + * Checks a password reset code sent to the user by email or other out-of-band mechanism. + * TODO salakar: confirm return behavior (Returns the user's email address if valid.) + * + * #### Example + * + * ```js + * const verifiedEmail = await firebase.auth().verifyPasswordResetCode('ABCD'); + * ``` + * + * @error auth/expired-action-code Thrown if the password reset code has expired. + * @error auth/invalid-action-code Thrown if the password reset code is invalid. This can happen if the code is malformed or has already been used. + * @error auth/user-disabled Thrown if the user corresponding to the given password reset code has been disabled. + * @error auth/user-not-found Thrown if there is no user corresponding to the password reset code. This may have happened if the user was deleted between when the code was issued and when this method was called. + * @param code A password reset code. + * @returns {string} The user's email address if valid + */ + verifyPasswordResetCode(code: string): Promise; + /** + * Switch userAccessGroup and current user to the given accessGroup and the user stored in it. + * Sign in a user with any sign in method, and the same current user is available in all + * apps in the access group. + * + * Set the `useAccessGroup` argument to `null` to stop sharing the auth state (default behaviour), the user state will no longer be + * available to any other apps. + * + * @platform ios + * + * @error auth/keychain-error Thrown if you attempt to access an inaccessible keychain + * @param userAccessGroup A string of the keychain id i.e. "TEAMID.com.example.group1" + */ + useUserAccessGroup(userAccessGroup: string): Promise; + /** + * Modify this Auth instance to communicate with the Firebase Auth emulator. + * This must be called synchronously immediately following the first call to firebase.auth(). + * Do not use with production credentials as emulator traffic is not encrypted. + * + * Note: on android, hosts 'localhost' and '127.0.0.1' are automatically remapped to '10.0.2.2' (the + * "host" computer IP address for android emulators) to make the standard development experience easy. + * If you want to use the emulator on a real android device, you will need to specify the actual host + * computer IP address. + * + * @param url: emulator URL, must have host and port (eg, 'http://localhost:9099') + */ + useEmulator(url: string): void; + /** + * Provides a MultiFactorResolver suitable for completion of a multi-factor flow. + * + * @param error: The MultiFactorError raised during a sign-in, or reauthentication operation. + */ + getMultiFactorResolver(error: MultiFactorError): MultiFactorResolver; + /** + * The MultiFactorUser corresponding to the user. + * + * This is used to access all multi-factor properties and operations related to the user. + * @param user The user. + */ + multiFactor(user: User): MultiFactorUser; + /** + * Returns the custom auth domain for the auth instance. + */ + getCustomAuthDomain(): Promise; + /** + * Sets the language code on the auth instance. This is to match Firebase JS SDK behavior. + * Please use the `setLanguageCode` method for setting the language code. + */ + set languageCode(code: string | null); + /** + * Gets the config used to initialize this auth instance. This is to match Firebase JS SDK behavior. + * It returns an empty map as the config is not available in the native SDK. + */ + get config(): Record; + } +} + +export type CallbackOrObserver any> = T | { next: T }; + +/** + * Attach namespace to `firebase.` and `FirebaseApp.`. + */ +declare module '@react-native-firebase/app' { + namespace ReactNativeFirebase { + import FirebaseModuleWithStaticsAndApp = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp; + interface Module { + auth: FirebaseModuleWithStaticsAndApp; + } + interface FirebaseApp { + auth(): FirebaseAuthTypes.Module; + } + } +} From 0872c2434a56e3767433fdaf33c17df354cd693d Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Tue, 21 Apr 2026 10:46:07 +0100 Subject: [PATCH 03/45] refactor(auth): type namespaced module and native bridge --- packages/auth/lib/namespaced.ts | 336 ++++++++++++++++++++-------- packages/auth/lib/types/internal.ts | 258 ++++++++++++++++++++- packages/auth/tsconfig.json | 8 +- 3 files changed, 503 insertions(+), 99 deletions(-) diff --git a/packages/auth/lib/namespaced.ts b/packages/auth/lib/namespaced.ts index a86a4de6c2..c3a9544574 100644 --- a/packages/auth/lib/namespaced.ts +++ b/packages/auth/lib/namespaced.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -26,11 +25,13 @@ import { isValidUrl, parseListenerOrObserver, } from '@react-native-firebase/app/dist/module/common'; +import type { ReactNativeFirebase } from '@react-native-firebase/app'; import { setReactNativeModule } from '@react-native-firebase/app/dist/module/internal/nativeModule'; import { FirebaseModule, createModuleNamespace, getFirebaseRoot, + type ModuleConfig, } from '@react-native-firebase/app/dist/module/internal'; import ConfirmationResult from './ConfirmationResult'; import PhoneAuthListener from './PhoneAuthListener'; @@ -53,13 +54,35 @@ import { TotpSecret } from './TotpSecret'; import { version } from './version'; import fallBackModule from './web/RNFBAuthModule'; import { PasswordPolicyMixin } from './password-policy/PasswordPolicyMixin'; +import type { CallbackOrObserver, FirebaseAuthTypes } from './types/namespaced'; +import type { + AuthIdTokenChangedEventInternal, + AuthInternal, + AuthStateChangedEventInternal, + NativePhoneAuthCredentialInternal, + NativeUserCredentialInternal, + NativeUserInternal, + PasswordPolicyInternal, + PasswordValidationStatusInternal, + PhoneAuthStateChangedEventInternal, +} from './types/internal'; + +type AuthProviderWithObjectInternal = FirebaseAuthTypes.AuthProvider & { + toObject(): Record; +}; + +type AuthErrorWithCodeInternal = Error & { + code?: string; +}; const PhoneAuthState = { CODE_SENT: 'sent', AUTO_VERIFY_TIMEOUT: 'timeout', AUTO_VERIFIED: 'verified', ERROR: 'error', -}; +} as const; + +const nativeEvents = ['auth_state_changed', 'auth_id_token_changed', 'phone_auth_state_changed']; export { AppleAuthProvider, @@ -97,37 +120,57 @@ const statics = { const namespace = 'auth'; const nativeModuleName = 'RNFBAuthModule'; -class FirebaseAuthModule extends FirebaseModule { - constructor(...args) { - super(...args); +class FirebaseAuthModule extends FirebaseModule { + _user: FirebaseAuthTypes.User | null; + _settings: FirebaseAuthTypes.AuthSettings | null; + _authResult: boolean; + _languageCode: string; + _tenantId: string | null; + _projectPasswordPolicy: PasswordPolicyInternal | null; + _tenantPasswordPolicies: Record; + _getPasswordPolicyInternal!: () => PasswordPolicyInternal | null; + _updatePasswordPolicy!: () => Promise; + _recachePasswordPolicy!: () => Promise; + validatePassword!: (password: string) => Promise; + + constructor( + app: ReactNativeFirebase.FirebaseAppBase, + config: ModuleConfig, + customUrlOrRegion?: string | null, + ) { + super(app, config, customUrlOrRegion); this._user = null; this._settings = null; this._authResult = false; - this._languageCode = this.native.APP_LANGUAGE[this.app._name]; + this._languageCode = this.native.APP_LANGUAGE[this.app.name] ?? ''; this._tenantId = null; this._projectPasswordPolicy = null; this._tenantPasswordPolicies = {}; if (!this.languageCode) { - this._languageCode = this.native.APP_LANGUAGE['[DEFAULT]']; + this._languageCode = this.native.APP_LANGUAGE['[DEFAULT]'] ?? ''; } - if (this.native.APP_USER[this.app._name]) { - this._setUser(this.native.APP_USER[this.app._name]); + const initialUser = this.native.APP_USER[this.app.name]; + if (initialUser) { + this._setUser(initialUser); } this.emitter.addListener(this.eventNameForApp('auth_state_changed'), event => { - this._setUser(event.user); + const authEvent = event as AuthStateChangedEventInternal; + this._setUser(authEvent.user); this.emitter.emit(this.eventNameForApp('onAuthStateChanged'), this._user); }); this.emitter.addListener(this.eventNameForApp('phone_auth_state_changed'), event => { - const eventKey = `phone:auth:${event.requestKey}:${event.type}`; - this.emitter.emit(eventKey, event.state); + const phoneAuthEvent = event as PhoneAuthStateChangedEventInternal; + const eventKey = `phone:auth:${phoneAuthEvent.requestKey}:${phoneAuthEvent.type}`; + this.emitter.emit(eventKey, phoneAuthEvent.state); }); - this.emitter.addListener(this.eventNameForApp('auth_id_token_changed'), auth => { - this._setUser(auth.user); + this.emitter.addListener(this.eventNameForApp('auth_id_token_changed'), event => { + const authEvent = event as AuthIdTokenChangedEventInternal; + this._setUser(authEvent.user); this.emitter.emit(this.eventNameForApp('onIdTokenChanged'), this._user); }); @@ -144,11 +187,11 @@ class FirebaseAuthModule extends FirebaseModule { } } - get languageCode() { + get languageCode(): string { return this._languageCode; } - set languageCode(code) { + set languageCode(code: string | null) { // For modular API, not recommended to set languageCode directly as it should be set in the native SDKs first if (!isString(code) && !isNull(code)) { throw new Error( @@ -157,47 +200,57 @@ class FirebaseAuthModule extends FirebaseModule { } // as this is a setter, we can't use async/await. So we set it first so it is available immediately if (code === null) { - this._languageCode = this.native.APP_LANGUAGE[this.app._name]; + this._languageCode = this.native.APP_LANGUAGE[this.app.name] ?? ''; if (!this.languageCode) { - this._languageCode = this.native.APP_LANGUAGE['[DEFAULT]']; + this._languageCode = this.native.APP_LANGUAGE['[DEFAULT]'] ?? ''; } } else { this._languageCode = code; } // This sets it natively - this.setLanguageCode(code); + void this.setLanguageCode(code); } - get config() { + get config(): Record { // for modular API, firebase JS SDK has a config object which is not available in native SDKs return {}; } - get tenantId() { + get tenantId(): string | null { return this._tenantId; } - get settings() { + get settings(): FirebaseAuthTypes.AuthSettings { if (!this._settings) { - this._settings = new Settings(this); + this._settings = new Settings( + this as unknown as AuthInternal, + ) as FirebaseAuthTypes.AuthSettings; } return this._settings; } - get currentUser() { + get currentUser(): FirebaseAuthTypes.User | null { return this._user; } - _setUser(user) { - this._user = user ? createDeprecationProxy(new User(this, user)) : null; + _setUser(user?: NativeUserInternal | null): FirebaseAuthTypes.User | null { + this._user = user + ? (createDeprecationProxy( + new User(this as unknown as AuthInternal, user), + ) as FirebaseAuthTypes.User) + : null; this._authResult = true; this.emitter.emit(this.eventNameForApp('onUserChanged'), this._user); return this._user; } - _setUserCredential(userCredential) { - const user = createDeprecationProxy(new User(this, userCredential.user)); + _setUserCredential( + userCredential: NativeUserCredentialInternal, + ): FirebaseAuthTypes.UserCredential { + const user = createDeprecationProxy( + new User(this as unknown as AuthInternal, userCredential.user), + ) as FirebaseAuthTypes.User; this._user = user; this._authResult = true; this.emitter.emit(this.eventNameForApp('onUserChanged'), this._user); @@ -207,7 +260,7 @@ class FirebaseAuthModule extends FirebaseModule { }; } - async setLanguageCode(code) { + async setLanguageCode(code: string | null): Promise { if (!isString(code) && !isNull(code)) { throw new Error( "firebase.auth().setLanguageCode(*) expected 'languageCode' to be a string or null value", @@ -217,17 +270,17 @@ class FirebaseAuthModule extends FirebaseModule { await this.native.setLanguageCode(code); if (code === null) { - this._languageCode = this.native.APP_LANGUAGE[this.app._name]; + this._languageCode = this.native.APP_LANGUAGE[this.app.name] ?? ''; if (!this.languageCode) { - this._languageCode = this.native.APP_LANGUAGE['[DEFAULT]']; + this._languageCode = this.native.APP_LANGUAGE['[DEFAULT]'] ?? ''; } } else { this._languageCode = code; } } - async setTenantId(tenantId) { + async setTenantId(tenantId: string): Promise { if (!isString(tenantId)) { throw new Error("firebase.auth().setTenantId(*) expected 'tenantId' to be a string"); } @@ -235,8 +288,12 @@ class FirebaseAuthModule extends FirebaseModule { await this.native.setTenantId(tenantId); } - onAuthStateChanged(listenerOrObserver) { - const listener = parseListenerOrObserver(listenerOrObserver); + onAuthStateChanged( + listenerOrObserver: CallbackOrObserver, + ): () => void { + const listener = parseListenerOrObserver( + listenerOrObserver, + ) as FirebaseAuthTypes.AuthListenerCallback; const subscription = this.emitter.addListener( this.eventNameForApp('onAuthStateChanged'), listener, @@ -250,8 +307,12 @@ class FirebaseAuthModule extends FirebaseModule { return () => subscription.remove(); } - onIdTokenChanged(listenerOrObserver) { - const listener = parseListenerOrObserver(listenerOrObserver); + onIdTokenChanged( + listenerOrObserver: CallbackOrObserver, + ): () => void { + const listener = parseListenerOrObserver( + listenerOrObserver, + ) as FirebaseAuthTypes.AuthListenerCallback; const subscription = this.emitter.addListener( this.eventNameForApp('onIdTokenChanged'), listener, @@ -265,8 +326,12 @@ class FirebaseAuthModule extends FirebaseModule { return () => subscription.remove(); } - onUserChanged(listenerOrObserver) { - const listener = parseListenerOrObserver(listenerOrObserver); + onUserChanged( + listenerOrObserver: CallbackOrObserver, + ): () => void { + const listener = parseListenerOrObserver( + listenerOrObserver, + ) as FirebaseAuthTypes.AuthListenerCallback; const subscription = this.emitter.addListener(this.eventNameForApp('onUserChanged'), listener); if (this._authResult) { Promise.resolve().then(() => { @@ -279,33 +344,48 @@ class FirebaseAuthModule extends FirebaseModule { }; } - signOut() { + signOut(): Promise { return this.native.signOut().then(() => { this._setUser(null); }); } - signInAnonymously() { + signInAnonymously(): Promise { return this.native .signInAnonymously() - .then(userCredential => this._setUserCredential(userCredential)); + .then((userCredential: NativeUserCredentialInternal) => + this._setUserCredential(userCredential), + ); } - signInWithPhoneNumber(phoneNumber, forceResend) { + signInWithPhoneNumber( + phoneNumber: string, + forceResend?: boolean, + ): Promise { if (isAndroid) { return this.native .signInWithPhoneNumber(phoneNumber, forceResend || false) - .then(result => new ConfirmationResult(this, result.verificationId)); + .then( + (result: NativePhoneAuthCredentialInternal) => + new ConfirmationResult(this as unknown as AuthInternal, result.verificationId), + ); } return this.native .signInWithPhoneNumber(phoneNumber) - .then(result => new ConfirmationResult(this, result.verificationId)); + .then( + (result: NativePhoneAuthCredentialInternal) => + new ConfirmationResult(this as unknown as AuthInternal, result.verificationId), + ); } - verifyPhoneNumber(phoneNumber, autoVerifyTimeoutOrForceResend, forceResend) { + verifyPhoneNumber( + phoneNumber: string, + autoVerifyTimeoutOrForceResend?: number | boolean, + forceResend?: boolean, + ): FirebaseAuthTypes.PhoneAuthListener { let _forceResend = forceResend; - let _autoVerifyTimeout = 60; + let _autoVerifyTimeout: number | undefined = 60; if (isBoolean(autoVerifyTimeoutOrForceResend)) { _forceResend = autoVerifyTimeoutOrForceResend; @@ -313,39 +393,64 @@ class FirebaseAuthModule extends FirebaseModule { _autoVerifyTimeout = autoVerifyTimeoutOrForceResend; } - return new PhoneAuthListener(this, phoneNumber, _autoVerifyTimeout, _forceResend); + return new PhoneAuthListener( + this as unknown as AuthInternal, + phoneNumber, + _autoVerifyTimeout, + _forceResend, + ) as FirebaseAuthTypes.PhoneAuthListener; } - verifyPhoneNumberWithMultiFactorInfo(multiFactorHint, session) { + verifyPhoneNumberWithMultiFactorInfo( + multiFactorHint: FirebaseAuthTypes.MultiFactorInfo, + session: FirebaseAuthTypes.MultiFactorSession, + ): Promise { return this.native.verifyPhoneNumberWithMultiFactorInfo(multiFactorHint.uid, session); } - verifyPhoneNumberForMultiFactor(phoneInfoOptions) { + verifyPhoneNumberForMultiFactor( + phoneInfoOptions: FirebaseAuthTypes.PhoneMultiFactorEnrollInfoOptions, + ): Promise { const { phoneNumber, session } = phoneInfoOptions; return this.native.verifyPhoneNumberForMultiFactor(phoneNumber, session); } - resolveMultiFactorSignIn(session, verificationId, verificationCode) { + resolveMultiFactorSignIn( + session: FirebaseAuthTypes.MultiFactorSession, + verificationId: string, + verificationCode: string, + ): Promise { return this.native .resolveMultiFactorSignIn(session, verificationId, verificationCode) - .then(userCredential => { + .then((userCredential: NativeUserCredentialInternal) => { return this._setUserCredential(userCredential); }); } - resolveTotpSignIn(session, uid, totpSecret) { - return this.native.resolveTotpSignIn(session, uid, totpSecret).then(userCredential => { - return this._setUserCredential(userCredential); - }); + resolveTotpSignIn( + session: FirebaseAuthTypes.MultiFactorSession, + uid: string, + totpSecret: string, + ): Promise { + return this.native + .resolveTotpSignIn(session, uid, totpSecret) + .then((userCredential: NativeUserCredentialInternal) => { + return this._setUserCredential(userCredential); + }); } - createUserWithEmailAndPassword(email, password) { + createUserWithEmailAndPassword( + email: string, + password: string, + ): Promise { return ( this.native .createUserWithEmailAndPassword(email, password) - .then(userCredential => this._setUserCredential(userCredential)) + .then((userCredential: NativeUserCredentialInternal) => + this._setUserCredential(userCredential), + ) /* istanbul ignore next - native error handling cannot be unit tested */ - .catch(error => { + .catch((error: AuthErrorWithCodeInternal) => { if (error.code === 'auth/password-does-not-meet-requirements') { return this._recachePasswordPolicy() .catch(() => { @@ -360,13 +465,18 @@ class FirebaseAuthModule extends FirebaseModule { ); } - signInWithEmailAndPassword(email, password) { + signInWithEmailAndPassword( + email: string, + password: string, + ): Promise { return ( this.native .signInWithEmailAndPassword(email, password) - .then(userCredential => this._setUserCredential(userCredential)) + .then((userCredential: NativeUserCredentialInternal) => + this._setUserCredential(userCredential), + ) /* istanbul ignore next - native error handling cannot be unit tested */ - .catch(error => { + .catch((error: AuthErrorWithCodeInternal) => { if (error.code === 'auth/password-does-not-meet-requirements') { return this._recachePasswordPolicy() .catch(() => { @@ -381,46 +491,60 @@ class FirebaseAuthModule extends FirebaseModule { ); } - signInWithCustomToken(customToken) { + signInWithCustomToken(customToken: string): Promise { return this.native .signInWithCustomToken(customToken) - .then(userCredential => this._setUserCredential(userCredential)); + .then((userCredential: NativeUserCredentialInternal) => + this._setUserCredential(userCredential), + ); } - signInWithCredential(credential) { + signInWithCredential( + credential: FirebaseAuthTypes.AuthCredential, + ): Promise { return this.native .signInWithCredential(credential.providerId, credential.token, credential.secret) - .then(userCredential => this._setUserCredential(userCredential)); + .then((userCredential: NativeUserCredentialInternal) => + this._setUserCredential(userCredential), + ); } - revokeToken(authorizationCode) { + revokeToken(authorizationCode: string): Promise { return this.native.revokeToken(authorizationCode); } - sendPasswordResetEmail(email, actionCodeSettings = null) { + sendPasswordResetEmail( + email: string, + actionCodeSettings: FirebaseAuthTypes.ActionCodeSettings | null = null, + ): Promise { return this.native.sendPasswordResetEmail(email, actionCodeSettings); } - sendSignInLinkToEmail(email, actionCodeSettings = {}) { + sendSignInLinkToEmail( + email: string, + actionCodeSettings?: FirebaseAuthTypes.ActionCodeSettings, + ): Promise { return this.native.sendSignInLinkToEmail(email, actionCodeSettings); } - isSignInWithEmailLink(emailLink) { + isSignInWithEmailLink(emailLink: string): Promise { return this.native.isSignInWithEmailLink(emailLink); } - signInWithEmailLink(email, emailLink) { + signInWithEmailLink(email: string, emailLink: string): Promise { return this.native .signInWithEmailLink(email, emailLink) - .then(userCredential => this._setUserCredential(userCredential)); + .then((userCredential: NativeUserCredentialInternal) => + this._setUserCredential(userCredential), + ); } - confirmPasswordReset(code, newPassword) { + confirmPasswordReset(code: string, newPassword: string): Promise { return ( this.native .confirmPasswordReset(code, newPassword) /* istanbul ignore next - native error handling cannot be unit tested */ - .catch(error => { + .catch((error: AuthErrorWithCodeInternal) => { if (error.code === 'auth/password-does-not-meet-requirements') { return this._recachePasswordPolicy() .catch(() => { @@ -435,61 +559,69 @@ class FirebaseAuthModule extends FirebaseModule { ); } - applyActionCode(code) { + applyActionCode(code: string): Promise { return this.native.applyActionCode(code).then(user => { this._setUser(user); }); } - checkActionCode(code) { + checkActionCode(code: string): Promise { return this.native.checkActionCode(code); } - fetchSignInMethodsForEmail(email) { + fetchSignInMethodsForEmail(email: string): Promise { return this.native.fetchSignInMethodsForEmail(email); } - verifyPasswordResetCode(code) { + verifyPasswordResetCode(code: string): Promise { return this.native.verifyPasswordResetCode(code); } - useUserAccessGroup(userAccessGroup) { + useUserAccessGroup(userAccessGroup: string): Promise { if (isAndroid) { return Promise.resolve(); } - return this.native.useUserAccessGroup(userAccessGroup); + return this.native.useUserAccessGroup(userAccessGroup).then(() => undefined); } - getRedirectResult() { + getRedirectResult(): Promise { throw new Error( 'firebase.auth().getRedirectResult() is unsupported by the native Firebase SDKs.', ); } - setPersistence() { + setPersistence(): Promise { throw new Error('firebase.auth().setPersistence() is unsupported by the native Firebase SDKs.'); } - signInWithPopup(provider) { + signInWithPopup( + provider: FirebaseAuthTypes.AuthProvider, + ): Promise { return this.native - .signInWithProvider(provider.toObject()) - .then(userCredential => this._setUserCredential(userCredential)); + .signInWithProvider((provider as AuthProviderWithObjectInternal).toObject()) + .then((userCredential: NativeUserCredentialInternal) => + this._setUserCredential(userCredential), + ); } - signInWithRedirect(provider) { + signInWithRedirect( + provider: FirebaseAuthTypes.AuthProvider, + ): Promise { return this.native - .signInWithProvider(provider.toObject()) - .then(userCredential => this._setUserCredential(userCredential)); + .signInWithProvider((provider as AuthProviderWithObjectInternal).toObject()) + .then((userCredential: NativeUserCredentialInternal) => + this._setUserCredential(userCredential), + ); } // firebase issue - https://github.com/invertase/react-native-firebase/pull/655#issuecomment-349904680 - useDeviceLanguage() { + useDeviceLanguage(): void { throw new Error( 'firebase.auth().useDeviceLanguage() is unsupported by the native Firebase SDKs.', ); } - useEmulator(url) { + useEmulator(url: string): [string, number] { if (!url || !isString(url) || !isValidUrl(url)) { throw new Error('firebase.auth().useEmulator() takes a non-empty string URL'); } @@ -522,23 +654,35 @@ class FirebaseAuthModule extends FirebaseModule { throw new Error('firebase.auth().useEmulator() unable to parse host and port from URL'); } const host = urlMatches[1]; - const port = parseInt(urlMatches[2], 10); + const portString = urlMatches[2]; + if (!host || !portString) { + throw new Error('firebase.auth().useEmulator() unable to parse host and port from URL'); + } + const port = parseInt(portString, 10); this.native.useEmulator(host, port); return [host, port]; // undocumented return, useful for unit testing } - getMultiFactorResolver(error) { - return getMultiFactorResolver(this, error); + getMultiFactorResolver( + error: FirebaseAuthTypes.MultiFactorError, + ): FirebaseAuthTypes.MultiFactorResolver { + return getMultiFactorResolver( + this as unknown as AuthInternal, + error, + ) as FirebaseAuthTypes.MultiFactorResolver; } - multiFactor(user) { + multiFactor(user: FirebaseAuthTypes.User): FirebaseAuthTypes.MultiFactorUser { if (!this.currentUser || user.uid !== this.currentUser.uid) { throw new Error('firebase.auth().multiFactor() only operates on currentUser'); } - return new MultiFactorUser(this, user); + return new MultiFactorUser( + this as unknown as AuthInternal, + user, + ) as FirebaseAuthTypes.MultiFactorUser; } - getCustomAuthDomain() { + getCustomAuthDomain(): Promise { return this.native.getCustomAuthDomain(); } } @@ -556,7 +700,7 @@ export default createModuleNamespace({ version, namespace, nativeModuleName, - nativeEvents: ['auth_state_changed', 'auth_id_token_changed', 'phone_auth_state_changed'], + nativeEvents, hasMultiAppSupport: true, hasCustomUrlOrRegionSupport: false, ModuleClass: FirebaseAuthModule, diff --git a/packages/auth/lib/types/internal.ts b/packages/auth/lib/types/internal.ts index b4732fde4b..36fc9819db 100644 --- a/packages/auth/lib/types/internal.ts +++ b/packages/auth/lib/types/internal.ts @@ -15,9 +15,263 @@ * */ +import type { ReactNativeFirebase } from '@react-native-firebase/app'; +import type {} from '@react-native-firebase/app/dist/module/internal/NativeModules'; +import type { + ModuleConfig, + NativeErrorUserInfo, +} from '@react-native-firebase/app/dist/module/types/internal'; +import type EventEmitter from 'react-native/Libraries/vendor/emitter/EventEmitter'; import type { FirebaseAuthTypes } from './namespaced'; -export type AuthInternal = FirebaseAuthTypes.Module; -export type UserInternal = FirebaseAuthTypes.User; +export interface NativeUserMetadataInternal { + creationTime: string; + lastSignInTime: string; +} + +export interface NativeUserInternal { + uid: string; + providerId: string; + providerData: FirebaseAuthTypes.UserInfo[]; + displayName?: string | null; + email?: string | null; + emailVerified?: boolean; + isAnonymous?: boolean; + metadata: NativeUserMetadataInternal; + multiFactor?: FirebaseAuthTypes.MultiFactor | null; + phoneNumber?: string | null; + photoURL?: string | null; + tenantId?: string | null; +} + +export interface NativeUserCredentialInternal { + additionalUserInfo?: FirebaseAuthTypes.AdditionalUserInfo; + user: NativeUserInternal; +} + +export interface NativePhoneAuthCredentialInternal { + verificationId: string; + code?: string | null; +} + +export interface NativePhoneAuthErrorInternal { + verificationId: string; + error: NativeErrorUserInfo; +} + +export interface AuthStateChangedEventInternal { + user: NativeUserInternal | null; +} + +export interface AuthIdTokenChangedEventInternal { + user: NativeUserInternal | null; +} + +export interface PhoneAuthStateChangedEventInternal { + requestKey: string; + type: + | 'onCodeSent' + | 'onVerificationFailed' + | 'onVerificationComplete' + | 'onCodeAutoRetrievalTimeout'; + state: NativePhoneAuthCredentialInternal | NativePhoneAuthErrorInternal; +} + +export type AuthNativeEventInternal = + | AuthStateChangedEventInternal + | AuthIdTokenChangedEventInternal + | PhoneAuthStateChangedEventInternal; + +export type PasswordPolicyInternal = FirebaseAuthTypes.PasswordPolicy; + +export type PasswordValidationStatusInternal = { + isValid: boolean; + meetsMinPasswordLength?: boolean; + meetsMaxPasswordLength?: boolean; + containsLowercaseLetter?: boolean; + containsUppercaseLetter?: boolean; + containsNumericCharacter?: boolean; + containsNonAlphanumericCharacter?: boolean; + passwordPolicy: PasswordPolicyInternal; +}; + +export interface PasswordPolicyHostInternal { + app: ReactNativeFirebase.FirebaseApp; + _tenantId: string | null; + _projectPasswordPolicy: PasswordPolicyInternal | null; + _tenantPasswordPolicies: Record; +} + +export interface PasswordPolicyMixinInternal { + _getPasswordPolicyInternal(): PasswordPolicyInternal | null; + _updatePasswordPolicy(): Promise; + _recachePasswordPolicy(): Promise; + validatePassword(password: string): Promise; +} + +export interface RNFBAuthModule { + APP_LANGUAGE: Record; + APP_USER: Record; + addAuthStateListener(): void | Promise; + addIdTokenListener(): void | Promise; + configureAuthDomain(): void | Promise; + setLanguageCode(code: string | null): Promise; + setTenantId(tenantId: string): Promise; + signOut(): Promise; + signInAnonymously(): Promise; + signInWithPhoneNumber( + phoneNumber: string, + forceResend?: boolean, + ): Promise; + verifyPhoneNumber( + phoneNumber: string, + requestKey: string, + timeout?: number, + forceResend?: boolean, + ): void | Promise; + verifyPhoneNumberWithMultiFactorInfo( + uid: string, + session: FirebaseAuthTypes.MultiFactorSession, + ): Promise; + verifyPhoneNumberForMultiFactor( + phoneNumber: string, + session: FirebaseAuthTypes.MultiFactorSession, + ): Promise; + resolveMultiFactorSignIn( + session: FirebaseAuthTypes.MultiFactorSession, + verificationId: string, + verificationCode: string, + ): Promise; + resolveTotpSignIn( + session: FirebaseAuthTypes.MultiFactorSession, + uid: string, + totpSecret: string, + ): Promise; + createUserWithEmailAndPassword( + email: string, + password: string, + ): Promise; + signInWithEmailAndPassword( + email: string, + password: string, + ): Promise; + signInWithCustomToken(customToken: string): Promise; + signInWithCredential( + providerId: string, + token: string, + secret?: string | null, + ): Promise; + revokeToken(authorizationCode: string): Promise; + sendPasswordResetEmail( + email: string, + actionCodeSettings?: FirebaseAuthTypes.ActionCodeSettings | null, + ): Promise; + sendSignInLinkToEmail( + email: string, + actionCodeSettings?: FirebaseAuthTypes.ActionCodeSettings, + ): Promise; + isSignInWithEmailLink(emailLink: string): Promise; + signInWithEmailLink(email: string, emailLink: string): Promise; + confirmPasswordReset(code: string, newPassword: string): Promise; + applyActionCode(code: string): Promise; + checkActionCode(code: string): Promise; + fetchSignInMethodsForEmail(email: string): Promise; + verifyPasswordResetCode(code: string): Promise; + useUserAccessGroup(userAccessGroup: string): Promise; + signInWithProvider(provider: Record): Promise; + useEmulator(host: string, port: number): void; + getCustomAuthDomain(): Promise; + confirmationResultConfirm(verificationCode: string): Promise; + delete(): Promise; + getIdToken(forceRefresh: boolean): Promise; + getIdTokenResult(forceRefresh: boolean): Promise; + linkWithCredential( + providerId: string, + token: string, + secret?: string | null, + ): Promise; + linkWithProvider(provider: Record): Promise; + reauthenticateWithCredential( + providerId: string, + token: string, + secret?: string | null, + ): Promise; + reauthenticateWithProvider( + provider: Record, + ): Promise; + reload(): Promise; + sendEmailVerification( + actionCodeSettings?: FirebaseAuthTypes.ActionCodeSettings, + ): Promise; + unlink(providerId: string): Promise; + updateEmail(email: string): Promise; + updatePassword(password: string): Promise; + updatePhoneNumber( + providerId: string, + token: string, + secret?: string | null, + ): Promise; + updateProfile(updates: FirebaseAuthTypes.UpdateProfile): Promise; + verifyBeforeUpdateEmail( + newEmail: string, + actionCodeSettings?: FirebaseAuthTypes.ActionCodeSettings, + ): Promise; + forceRecaptchaFlowForTesting(forceRecaptchaFlow: boolean): void | Promise; + setAppVerificationDisabledForTesting(disabled: boolean): void | Promise; + setAutoRetrievedSmsCodeForPhoneNumber(phoneNumber: string, smsCode: string): Promise; + getSession(): Promise; + finalizeMultiFactorEnrollment(token: string, secret: string, displayName?: string): Promise; + finalizeTotpEnrollment( + totpSecret: string, + verificationCode: string, + displayName?: string, + ): Promise; + unenrollMultiFactor(enrollmentId: string | FirebaseAuthTypes.MultiFactorInfo): Promise; + getMultiFactorResolver(error: unknown): FirebaseAuthTypes.MultiFactorResolver | null; + generateTotpSecret(session: FirebaseAuthTypes.MultiFactorSession): Promise<{ secretKey: string }>; + generateQrCodeUrl(secretKey: string, accountName: string, issuer: string): Promise; + openInOtpApp(secretKey: string, qrCodeUrl: string): string | void; + assertionForSignIn( + uid: string, + verificationCode: string, + ): { uid: string; verificationCode: string }; +} + +export type AuthInternal = { + app: ReactNativeFirebase.FirebaseApp; + currentUser: FirebaseAuthTypes.User | null; + native: RNFBAuthModule; + emitter: EventEmitter; + eventNameForApp(...args: Array): string; + _config: ModuleConfig; + _tenantId: string | null; + _projectPasswordPolicy: PasswordPolicyInternal | null; + _tenantPasswordPolicies: Record; + _setUser(user?: NativeUserInternal | null): FirebaseAuthTypes.User | null; + _setUserCredential( + userCredential: NativeUserCredentialInternal, + ): FirebaseAuthTypes.UserCredential; + resolveMultiFactorSignIn( + session: FirebaseAuthTypes.MultiFactorSession, + verificationId: string, + verificationCode: string, + ): Promise; + resolveTotpSignIn( + session: FirebaseAuthTypes.MultiFactorSession, + uid: string, + totpSecret: string, + ): Promise; +} & PasswordPolicyMixinInternal; + +export type UserInternal = FirebaseAuthTypes.User & { + _auth?: AuthInternal; +}; + export type ConfirmationResultInternal = FirebaseAuthTypes.ConfirmationResult; export type MultiFactorResolverInternal = FirebaseAuthTypes.MultiFactorResolver; + +declare module '@react-native-firebase/app/dist/module/internal/NativeModules' { + interface ReactNativeFirebaseNativeModules { + RNFBAuthModule: RNFBAuthModule; + } +} diff --git a/packages/auth/tsconfig.json b/packages/auth/tsconfig.json index e74ce68d3a..9abc838514 100644 --- a/packages/auth/tsconfig.json +++ b/packages/auth/tsconfig.json @@ -6,11 +6,17 @@ "paths": { "@react-native-firebase/app/dist/module/common/*": ["../app/dist/typescript/lib/common/*"], "@react-native-firebase/app/dist/module/common": ["../app/dist/typescript/lib/common"], + "@react-native-firebase/app/dist/module/internal/NativeModules": [ + "../app/dist/typescript/lib/internal/NativeModules" + ], "@react-native-firebase/app/dist/module/internal/*": [ "../app/dist/typescript/lib/internal/*" ], "@react-native-firebase/app/dist/module/internal": ["../app/dist/typescript/lib/internal"], - "@react-native-firebase/app": ["../app/dist/typescript/lib"] + "@react-native-firebase/app": ["../app/dist/typescript/lib"], + "@react-native-firebase/app/dist/module/types/internal": [ + "../app/dist/typescript/lib/types/internal" + ] } }, "include": ["lib/**/*"], From 229cea092b482cf8e65ae4bffb6c50ebae3dd815 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Tue, 21 Apr 2026 11:33:00 +0100 Subject: [PATCH 04/45] refactor(auth): align modular API with firebase-js-sdk --- packages/auth/lib/index.ts | 8 + packages/auth/lib/modular.ts | 797 ++++++++++++-------------------- packages/auth/lib/types/auth.ts | 48 +- packages/auth/tsconfig.json | 3 + 4 files changed, 363 insertions(+), 493 deletions(-) diff --git a/packages/auth/lib/index.ts b/packages/auth/lib/index.ts index a7a0a0006f..84404c72f2 100644 --- a/packages/auth/lib/index.ts +++ b/packages/auth/lib/index.ts @@ -25,11 +25,16 @@ export type { AdditionalUserInfo, ApplicationVerifier, Auth, + AuthErrorMap, AuthCredential, AuthListenerCallback, AuthProvider, AuthSettings, + CompleteFn, + Config, ConfirmationResult, + Dependencies, + ErrorFn, FactorId, FirebaseApp, IdTokenResult, @@ -42,7 +47,9 @@ export type { MultiFactorSession, MultiFactorUser, NativeFirebaseAuthError, + NextFn, OIDCProvider, + Observer, PasswordPolicy, PasswordValidationStatus, Persistence, @@ -59,6 +66,7 @@ export type { UserCredential, UserInfo, UserMetadata, + Unsubscribe, } from './types/auth'; export * from './types/namespaced'; export * from './modular'; diff --git a/packages/auth/lib/modular.ts b/packages/auth/lib/modular.ts index acd09c1cd6..18ac58f8a1 100644 --- a/packages/auth/lib/modular.ts +++ b/packages/auth/lib/modular.ts @@ -1,5 +1,3 @@ -// @ts-nocheck -/* eslint-disable @typescript-eslint/no-unused-vars */ /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -17,626 +15,440 @@ */ import { getApp } from '@react-native-firebase/app'; -import { MultiFactorUser } from './multiFactor'; import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/dist/module/common'; +import { MultiFactorUser } from './multiFactor'; +import type { FirebaseApp } from '@react-native-firebase/app'; +import type { + ActionCodeInfo, + ActionCodeSettings, + ActionCodeURL, + AdditionalUserInfo, + ApplicationVerifier, + Auth, + AuthCredential, + AuthProvider, + CompleteFn, + ConfirmationResult, + Dependencies, + ErrorFn, + IdTokenResult, + MultiFactorError, + MultiFactorResolver, + MultiFactorUser as MultiFactorUserType, + NextFn, + Observer, + PasswordValidationStatus, + Persistence, + PhoneAuthListener, + PopupRedirectResolver, + UpdateProfile, + User, + UserCredential, +} from './types/auth'; +import type { UserInternal } from './types/internal'; + +type AnyFn = (...args: any[]) => any; + +type WithModularDeprecationArg = ( + ...args: [...Parameters, typeof MODULAR_DEPRECATION_ARG] +) => ReturnType; + +type AuthWithPasswordValidationInternal = Auth & { + validatePassword(password: string): Promise; +}; + +type NextOrObserverInternal = NextFn | Observer; + +function callAuthMethod( + auth: Auth, + method: F, + ...args: Parameters +): ReturnType { + return (method as unknown as WithModularDeprecationArg).call( + auth, + ...args, + MODULAR_DEPRECATION_ARG, + ); +} -/** - * @typedef {import('@firebase/app-types').FirebaseApp} FirebaseApp - * @typedef {import('..').FirebaseAuthTypes} FirebaseAuthTypes - * @typedef {import('..').FirebaseAuthTypes.Module} Auth - * @typedef {import('..').FirebaseAuthTypes.CallbackOrObserver} CallbackOrObserver - * @typedef {import('..').FirebaseAuthTypes.AuthListenerCallback} AuthListenerCallback - * @typedef {import('..').FirebaseAuthTypes.ActionCodeInfo} ActionCodeInfo - * @typedef {import('..').FirebaseAuthTypes.UserCredential} UserCredential - * @typedef {import('..').FirebaseAuthTypes.MultiFactorError} MultiFactorError - * @typedef {import('..').FirebaseAuthTypes.MultiFactorUser} MultiFactorUser - * @typedef {import('..').FirebaseAuthTypes.MultiFactorResolver} MultiFactorResolver - * @typedef {import('..').FirebaseAuthTypes.ConfirmationResult} ConfirmationResult - * @typedef {import('..').FirebaseAuthTypes.AuthCredential} AuthCredential - * @typedef {import('..').FirebaseAuthTypes.AuthProvider} AuthProvider - * @typedef {import('..').FirebaseAuthTypes.PhoneAuthListener} PhoneAuthListener - * @typedef {import('..').FirebaseAuthTypes.ActionCodeSettings} ActionCodeSettings - * @typedef {import('..').FirebaseAuthTypes.User} User - * @typedef {import('..').FirebaseAuthTypes.IdTokenResult} IdTokenResult - * @typedef {import('..').FirebaseAuthTypes.AdditionalUserInfo} AdditionalUserInfo - * @typedef {import('..').FirebaseAuthTypes.ActionCodeURL} ActionCodeURL - * @typedef {import('..').FirebaseAuthTypes.ApplicationVerifier} ApplicationVerifier - */ +function callUserMethod( + user: User, + method: F, + ...args: Parameters +): ReturnType { + return (method as unknown as WithModularDeprecationArg).call( + user, + ...args, + MODULAR_DEPRECATION_ARG, + ); +} /** * Returns the Auth instance associated with the provided FirebaseApp. - * @param {FirebaseApp} [app] - The Firebase app instance. - * @returns {Auth} */ -export function getAuth(app) { +export function getAuth(app?: FirebaseApp): Auth { if (app) { return getApp(app.name).auth(); } + return getApp().auth(); } /** * This function allows more control over the Auth instance than getAuth(). - * @param {FirebaseApp} app - The Firebase app instance. - * @param {any} [deps] - Optional. Dependencies for the Auth instance. - * @returns {Auth} */ -export function initializeAuth(app, deps) { - if (app) { - return getApp(app.name).auth(); - } - return getApp().auth(); +export function initializeAuth(app: FirebaseApp, _deps?: Dependencies): Auth { + return getApp(app.name).auth(); } -/** - * Applies a verification code sent to the user by email or other out-of-band mechanism. - * @param {Auth} auth - The Auth instance. - * @param {string} oobCode - The out-of-band code sent to the user. - * @returns {Promise} - */ -export async function applyActionCode(auth, oobCode) { - return auth.applyActionCode.call(auth, oobCode, MODULAR_DEPRECATION_ARG); +export function applyActionCode(auth: Auth, oobCode: string): Promise { + return callAuthMethod(auth, auth.applyActionCode, oobCode); } -/** - * Adds a blocking callback that runs before an auth state change sets a new user. - * @param {Auth} auth - The Auth instance. - * @param {(user: User | null) => void} callback - A callback function to run before the auth state changes. - * @param {() => void} [onAbort] - Optional. A callback function to run if the operation is aborted. - */ -export function beforeAuthStateChanged(auth, callback, onAbort) { +export function beforeAuthStateChanged( + _auth: Auth, + _callback: (user: User | null) => void | Promise, + _onAbort?: () => void, +): () => void { throw new Error('beforeAuthStateChanged is unsupported by the native Firebase SDKs'); } -/** - * Checks a verification code sent to the user by email or other out-of-band mechanism. - * @param {Auth} auth - The Auth instance. - * @param {string} oobCode - The out-of-band code sent to the user. - * @returns {Promise} - */ -export async function checkActionCode(auth, oobCode) { - return auth.checkActionCode.call(auth, oobCode, MODULAR_DEPRECATION_ARG); +export function checkActionCode(auth: Auth, oobCode: string): Promise { + return callAuthMethod(auth, auth.checkActionCode, oobCode); } -/** - * Completes the password reset process, given a confirmation code and new password. - * @param {Auth} auth - The Auth instance. - * @param {string} oobCode - The out-of-band code sent to the user. - * @param {string} newPassword - The new password. - * @returns {Promise} - */ -export async function confirmPasswordReset(auth, oobCode, newPassword) { - return auth.confirmPasswordReset.call(auth, oobCode, newPassword, MODULAR_DEPRECATION_ARG); +export function confirmPasswordReset( + auth: Auth, + oobCode: string, + newPassword: string, +): Promise { + return callAuthMethod(auth, auth.confirmPasswordReset, oobCode, newPassword); } -/** - * Changes the Auth instance to communicate with the Firebase Auth Emulator, instead of production Firebase Auth services. - * @param {Auth} auth - The Auth instance. - * @param {string} url - The URL of the Firebase Auth Emulator. - * @param {{ disableWarnings: boolean }} [options] - Optional. Options for the emulator connection. - */ -export function connectAuthEmulator(auth, url, options) { - auth.useEmulator.call(auth, url, options, MODULAR_DEPRECATION_ARG); +export function connectAuthEmulator( + auth: Auth, + url: string, + _options?: { disableWarnings?: boolean }, +): void { + callAuthMethod(auth, auth.useEmulator, url); } -/** - * Creates a new user account associated with the specified email address and password. - * @param {Auth} auth - The Auth instance. - * @param {string} email - The user's email address. - * @param {string} password - The user's password. - * @returns {Promise} - */ -export async function createUserWithEmailAndPassword(auth, email, password) { - return auth.createUserWithEmailAndPassword.call(auth, email, password, MODULAR_DEPRECATION_ARG); +export function createUserWithEmailAndPassword( + auth: Auth, + email: string, + password: string, +): Promise { + return callAuthMethod(auth, auth.createUserWithEmailAndPassword, email, password); } -/** - * Gets the list of possible sign in methods for the given email address. - * @param {Auth} auth - The Auth instance. - * @param {string} email - The user's email address. - * @returns {Promise} - */ -export async function fetchSignInMethodsForEmail(auth, email) { - return auth.fetchSignInMethodsForEmail.call(auth, email, MODULAR_DEPRECATION_ARG); +export function fetchSignInMethodsForEmail(auth: Auth, email: string): Promise { + return callAuthMethod(auth, auth.fetchSignInMethodsForEmail, email); } -/** - * Provides a MultiFactorResolver suitable for completion of a multi-factor flow. - * @param {Auth} auth - The Auth instance. - * @param {MultiFactorError} error - The multi-factor error. - * @returns {MultiFactorResolver} - */ -export function getMultiFactorResolver(auth, error) { - return auth.getMultiFactorResolver.call(auth, error, MODULAR_DEPRECATION_ARG); +export function getMultiFactorResolver(auth: Auth, error: MultiFactorError): MultiFactorResolver { + return callAuthMethod(auth, auth.getMultiFactorResolver, error); } -/** - * Returns a UserCredential from the redirect-based sign-in flow. - * @param {Auth} auth - The Auth instance. - * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. - * @returns {Promise} - */ -export async function getRedirectResult(auth, resolver) { +export function getRedirectResult( + _auth: Auth, + _resolver?: PopupRedirectResolver, +): Promise { throw new Error('getRedirectResult is unsupported by the native Firebase SDKs'); } -/** - * Checks if an incoming link is a sign-in with email link suitable for signInWithEmailLink(). - * @param {Auth} auth - The Auth instance. - * @param {string} emailLink - The email link to check. - * @returns {Promise} - */ -export function isSignInWithEmailLink(auth, emailLink) { - return auth.isSignInWithEmailLink.call(auth, emailLink, MODULAR_DEPRECATION_ARG); +export function isSignInWithEmailLink(auth: Auth, emailLink: string): Promise { + return callAuthMethod(auth, auth.isSignInWithEmailLink, emailLink); } -/** - * Adds an observer for changes to the user's sign-in state. - * @param {Auth} auth - The Auth instance. - * @param {CallbackOrObserver} nextOrObserver - A callback function or observer for auth state changes. - * @returns {() => void} - */ -export function onAuthStateChanged(auth, nextOrObserver) { - return auth.onAuthStateChanged.call(auth, nextOrObserver, MODULAR_DEPRECATION_ARG); +export function onAuthStateChanged( + auth: Auth, + nextOrObserver: NextOrObserverInternal, + _error?: ErrorFn, + _completed?: CompleteFn, +): () => void { + // The legacy callback overload exists for JS SDK compatibility, but native auth listeners + // never invoke separate error/completed callbacks. + return callAuthMethod(auth, auth.onAuthStateChanged, nextOrObserver); } -/** - * Adds an observer for changes to the signed-in user's ID token. - * @param {Auth} auth - The Auth instance. - * @param {CallbackOrObserver} nextOrObserver - A callback function or observer for ID token changes. - * @returns {() => void} - */ -export function onIdTokenChanged(auth, nextOrObserver) { - return auth.onIdTokenChanged.call(auth, nextOrObserver, MODULAR_DEPRECATION_ARG); +export function onIdTokenChanged( + auth: Auth, + nextOrObserver: NextOrObserverInternal, + _error?: ErrorFn, + _completed?: CompleteFn, +): () => void { + // The legacy callback overload exists for JS SDK compatibility, but native auth listeners + // never invoke separate error/completed callbacks. + return callAuthMethod(auth, auth.onIdTokenChanged, nextOrObserver); } -/** - * Revoke the given access token, Currently only supports Apple OAuth access tokens. - * @param auth - The Auth Instance. - * @param token - The Access Token - */ -export async function revokeAccessToken(auth, token) { +export function revokeAccessToken(_auth: Auth, _token: string): Promise { throw new Error('revokeAccessToken() is only supported on Web'); -} //TO DO: Add Support +} -/** - * Sends a password reset email to the given email address. - * @param {Auth} auth - The Auth instance. - * @param {string} email - The user's email address. - * @param {ActionCodeSettings} [actionCodeSettings] - Optional. Action code settings. - * @returns {Promise} - */ -export async function sendPasswordResetEmail(auth, email, actionCodeSettings) { - return auth.sendPasswordResetEmail.call(auth, email, actionCodeSettings, MODULAR_DEPRECATION_ARG); +export function sendPasswordResetEmail( + auth: Auth, + email: string, + actionCodeSettings?: ActionCodeSettings, +): Promise { + return callAuthMethod(auth, auth.sendPasswordResetEmail, email, actionCodeSettings); } -/** - * Sends a sign-in email link to the user with the specified email. - * @param {Auth} auth - The Auth instance. - * @param {string} email - The user's email address. - * @param {ActionCodeSettings} [actionCodeSettings] - Optional. Action code settings. - * @returns {Promise} - */ -export async function sendSignInLinkToEmail(auth, email, actionCodeSettings) { - return auth.sendSignInLinkToEmail.call(auth, email, actionCodeSettings, MODULAR_DEPRECATION_ARG); +export function sendSignInLinkToEmail( + auth: Auth, + email: string, + actionCodeSettings: ActionCodeSettings, +): Promise { + return callAuthMethod(auth, auth.sendSignInLinkToEmail, email, actionCodeSettings); } -/** - * Changes the type of persistence on the Auth instance for the currently saved Auth session and applies this type of persistence for future sign-in requests, including sign-in with redirect requests. - * @param {Auth} auth - The Auth instance. - * @param {Persistence} persistence - The persistence type. - * @returns {Promise} - */ -export async function setPersistence(auth, persistence) { +export function setPersistence(_auth: Auth, _persistence: Persistence): Promise { throw new Error('setPersistence is unsupported by the native Firebase SDKs'); } -/** - * Asynchronously signs in as an anonymous user. - * @param {Auth} auth - The Auth instance. - * @returns {Promise} - */ -export async function signInAnonymously(auth) { - return auth.signInAnonymously.call(auth, MODULAR_DEPRECATION_ARG); +export function signInAnonymously(auth: Auth): Promise { + return callAuthMethod(auth, auth.signInAnonymously); } -/** - * Asynchronously signs in with the given credentials. - * @param {Auth} auth - The Auth instance. - * @param {AuthCredential} credential - The auth credentials. - * @returns {Promise} - */ -export async function signInWithCredential(auth, credential) { - return auth.signInWithCredential.call(auth, credential, MODULAR_DEPRECATION_ARG); +export function signInWithCredential( + auth: Auth, + credential: AuthCredential, +): Promise { + return callAuthMethod(auth, auth.signInWithCredential, credential); } -/** - * Asynchronously signs in using a custom token. - * @param {Auth} auth - The Auth instance. - * @param {string} customToken - The custom token. - * @returns {Promise} - */ -export async function signInWithCustomToken(auth, customToken) { - return auth.signInWithCustomToken.call(auth, customToken, MODULAR_DEPRECATION_ARG); +export function signInWithCustomToken(auth: Auth, customToken: string): Promise { + return callAuthMethod(auth, auth.signInWithCustomToken, customToken); } -/** - * Asynchronously signs in using an email and password. - * @param {Auth} auth - The Auth instance. - * @param {string} email - The user's email address. - * @param {string} password - The user's password. - * @returns {Promise} - */ -export async function signInWithEmailAndPassword(auth, email, password) { - return auth.signInWithEmailAndPassword.call(auth, email, password, MODULAR_DEPRECATION_ARG); +export function signInWithEmailAndPassword( + auth: Auth, + email: string, + password: string, +): Promise { + return callAuthMethod(auth, auth.signInWithEmailAndPassword, email, password); } -/** - * Asynchronously signs in using an email and sign-in email link. - * @param {Auth} auth - The Auth instance. - * @param {string} email - The user's email address. - * @param {string} emailLink - The email link. - * @returns {Promise} - */ -export async function signInWithEmailLink(auth, email, emailLink) { - return auth.signInWithEmailLink.call(auth, email, emailLink, MODULAR_DEPRECATION_ARG); +export function signInWithEmailLink( + auth: Auth, + email: string, + emailLink: string, +): Promise { + return callAuthMethod(auth, auth.signInWithEmailLink, email, emailLink); } -/** - * Asynchronously signs in using a phone number. - * @param {Auth} auth - The Auth instance. - * @param {string} phoneNumber - The user's phone number. - * @param {ApplicationVerifier} appVerifier - The application verifier. - * @returns {Promise} - */ -export async function signInWithPhoneNumber(auth, phoneNumber, appVerifier) { - return auth.signInWithPhoneNumber.call(auth, phoneNumber, appVerifier, MODULAR_DEPRECATION_ARG); +export function signInWithPhoneNumber( + auth: Auth, + phoneNumber: string, + _appVerifier?: ApplicationVerifier, +): Promise { + // Native SDKs own the verification flow, so the modular wrapper intentionally ignores the + // JS SDK's optional ApplicationVerifier and forwards only the phone number. + const signInWithPhoneNumberInternal = auth.signInWithPhoneNumber as unknown as ( + phoneNumber: string, + ) => Promise; + + return callAuthMethod(auth, signInWithPhoneNumberInternal, phoneNumber); } -/** - * Asynchronously verifies a phone number. - * @param {Auth} auth - The Auth instance. - * @param {string} phoneNumber - The user's phone number. - * @param {number | boolean} autoVerifyTimeoutOrForceResend - The auto verify timeout or force resend flag. - * @param {boolean} [forceResend] - Optional. Whether to force resend. - * @returns {PhoneAuthListener} - */ -export function verifyPhoneNumber(auth, phoneNumber, autoVerifyTimeoutOrForceResend, forceResend) { - return auth.verifyPhoneNumber.call( - auth, - phoneNumber, - autoVerifyTimeoutOrForceResend, - forceResend, - MODULAR_DEPRECATION_ARG, - ); +export function verifyPhoneNumber( + auth: Auth, + phoneNumber: string, + autoVerifyTimeoutOrForceResend?: number | boolean, + forceResend?: boolean, +): PhoneAuthListener { + return ( + auth.verifyPhoneNumber as unknown as WithModularDeprecationArg< + ( + phoneNumber: string, + autoVerifyTimeoutOrForceResend?: number | boolean, + forceResend?: boolean, + ) => PhoneAuthListener + > + ).call(auth, phoneNumber, autoVerifyTimeoutOrForceResend, forceResend, MODULAR_DEPRECATION_ARG); } -/** - * Authenticates a Firebase client using a popup-based OAuth authentication flow. - * @param {Auth} auth - The Auth instance. - * @param {AuthProvider} provider - The auth provider. - * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. - * @returns {Promise} - */ -export async function signInWithPopup(auth, provider, resolver) { - return auth.signInWithPopup.call(auth, provider, resolver, MODULAR_DEPRECATION_ARG); +export function signInWithPopup( + auth: Auth, + provider: AuthProvider, + _resolver?: PopupRedirectResolver, +): Promise { + return callAuthMethod(auth, auth.signInWithPopup, provider); } -/** - * Authenticates a Firebase client using a full-page redirect flow. - * @param {Auth} auth - The Auth instance. - * @param {AuthProvider} provider - The auth provider. - * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. - * @returns {Promise} - */ -export async function signInWithRedirect(auth, provider, resolver) { - return auth.signInWithRedirect.call(auth, provider, resolver, MODULAR_DEPRECATION_ARG); +export function signInWithRedirect( + auth: Auth, + provider: AuthProvider, + _resolver?: PopupRedirectResolver, +): Promise { + // Native provider flows complete immediately and return a credential instead of following the + // browser redirect contract from the Firebase JS SDK. + return callAuthMethod(auth, auth.signInWithRedirect, provider); } -/** - * Signs out the current user. - * @param {Auth} auth - The Auth instance. - * @returns {Promise} - */ -export async function signOut(auth) { - return auth.signOut.call(auth, MODULAR_DEPRECATION_ARG); +export function signOut(auth: Auth): Promise { + return callAuthMethod(auth, auth.signOut); } -/** - * Asynchronously sets the provided user as Auth.currentUser on the Auth instance. - * @param {Auth} auth - The Auth instance. - * @param {User} user - The user to set as the current user. - * @returns {Promise} - */ -export async function updateCurrentUser(auth, user) { +export function updateCurrentUser(_auth: Auth, _user: User | null): Promise { throw new Error('updateCurrentUser is unsupported by the native Firebase SDKs'); } -/** - * Sets the current language to the default device/browser preference. - * @param {Auth} auth - The Auth instance. - */ -export function useDeviceLanguage(auth) { +export function useDeviceLanguage(_auth: Auth): void { throw new Error('useDeviceLanguage is unsupported by the native Firebase SDKs'); } -/** - * Sets the language code. - * @param {Auth} auth - The Auth instance. - * @param {string} languageCode - The language code. - */ -export function setLanguageCode(auth, languageCode) { - return auth.setLanguageCode.call(auth, languageCode, MODULAR_DEPRECATION_ARG); +export function setLanguageCode(auth: Auth, languageCode: string | null): Promise { + return callAuthMethod(auth, auth.setLanguageCode, languageCode); } -/** - * Configures a shared user access group to sync auth state across multiple apps via the Keychain. - * @param {Auth} auth - The Auth instance. - * @param {string} userAccessGroup - The user access group. - * @returns {Promise} - */ -export function useUserAccessGroup(auth, userAccessGroup) { - return auth.useUserAccessGroup.call(auth, userAccessGroup, MODULAR_DEPRECATION_ARG); +export function useUserAccessGroup(auth: Auth, userAccessGroup: string): Promise { + return callAuthMethod(auth, auth.useUserAccessGroup, userAccessGroup).then(() => undefined); } -/** - * Verifies the password reset code sent to the user by email or other out-of-band mechanism. - * @param {Auth} auth - The Auth instance. - * @param {string} code - The password reset code. - * @returns {Promise} - */ -export async function verifyPasswordResetCode(auth, code) { - return auth.verifyPasswordResetCode.call(auth, code, MODULAR_DEPRECATION_ARG); +export function verifyPasswordResetCode(auth: Auth, code: string): Promise { + return callAuthMethod(auth, auth.verifyPasswordResetCode, code); } -/** - * Parses the email action link string and returns an ActionCodeURL if the link is valid, otherwise returns null. - * @param {string} link - The email action link string. - * @returns {ActionCodeURL | null} - */ -export function parseActionCodeURL(link) { +export function parseActionCodeURL(_link: string): ActionCodeURL | null { throw new Error('parseActionCodeURL is unsupported by the native Firebase SDKs'); } -/** - * Deletes and signs out the user. - * @param {User} user - The user to delete. - * @returns {Promise} - */ -export async function deleteUser(user) { - return user.delete.call(user, MODULAR_DEPRECATION_ARG); +export function deleteUser(user: User): Promise { + return callUserMethod(user, user.delete); } -/** - * Returns a JSON Web Token (JWT) used to identify the user to a Firebase service. - * @param {User} user - The user to get the token for. - * @param {boolean} [forceRefresh] - Optional. Whether to force refresh the token. - * @returns {Promise} - */ -export async function getIdToken(user, forceRefresh) { - return user.getIdToken.call(user, forceRefresh, MODULAR_DEPRECATION_ARG); +export function getIdToken(user: User, forceRefresh?: boolean): Promise { + return callUserMethod(user, user.getIdToken, forceRefresh); } -/** - * Returns a deserialized JSON Web Token (JWT) used to identify the user to a Firebase service. - * @param {User} user - The user to get the token result for. - * @param {boolean} [forceRefresh] - Optional. Whether to force refresh the token. - * @returns {Promise} - */ -export async function getIdTokenResult(user, forceRefresh) { - return user.getIdTokenResult.call(user, forceRefresh, MODULAR_DEPRECATION_ARG); +export function getIdTokenResult(user: User, forceRefresh?: boolean): Promise { + return callUserMethod(user, user.getIdTokenResult, forceRefresh); } -/** - * Links the user account with the given credentials. - * @param {User} user - The user to link the credentials with. - * @param {AuthCredential} credential - The auth credentials. - * @returns {Promise} - */ -export async function linkWithCredential(user, credential) { - return user.linkWithCredential.call(user, credential, MODULAR_DEPRECATION_ARG); +export function linkWithCredential( + user: User, + credential: AuthCredential, +): Promise { + return callUserMethod(user, user.linkWithCredential, credential); } -/** - * Links the user account with the given phone number. - * @param {User} user - The user to link the phone number with. - * @param {string} phoneNumber - The phone number. - * @param {ApplicationVerifier} appVerifier - The application verifier. - * @returns {Promise} - */ -export async function linkWithPhoneNumber(user, phoneNumber, appVerifier) { +export function linkWithPhoneNumber( + _user: User, + _phoneNumber: string, + _appVerifier?: ApplicationVerifier, +): Promise { throw new Error('linkWithPhoneNumber is unsupported by the native Firebase SDKs'); } -/** - * Links the authenticated provider to the user account using a pop-up based OAuth flow. - * @param {User} user - The user to link the provider with. - * @param {AuthProvider} provider - The auth provider. - * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. - * @returns {Promise} - */ -export async function linkWithPopup(user, provider, resolver) { - return user.linkWithPopup.call(user, provider, resolver, MODULAR_DEPRECATION_ARG); +export function linkWithPopup( + user: User, + provider: AuthProvider, + _resolver?: PopupRedirectResolver, +): Promise { + return callUserMethod(user, user.linkWithPopup, provider); } -/** - * Links the OAuthProvider to the user account using a full-page redirect flow. - * @param {User} user - The user to link the provider with. - * @param {AuthProvider} provider - The auth provider. - * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. - * @returns {Promise} - */ -export async function linkWithRedirect(user, provider, resolver) { - return user.linkWithRedirect.call(user, provider, resolver, MODULAR_DEPRECATION_ARG); +export function linkWithRedirect( + user: User, + provider: AuthProvider, + _resolver?: PopupRedirectResolver, +): Promise { + // Native provider flows complete immediately and return a credential instead of following the + // browser redirect contract from the Firebase JS SDK. + return callUserMethod(user, user.linkWithRedirect, provider); } -/** - * The MultiFactorUser corresponding to the user. - * @param {User} user - The user to get the multi-factor user for. - * @returns {MultiFactorUser} - */ -export function multiFactor(user) { - return new MultiFactorUser(user._auth || getAuth(), user); +export function multiFactor(user: User): MultiFactorUserType { + return new MultiFactorUser( + (user as UserInternal)._auth || getAuth(), + user, + ) as MultiFactorUserType; } -/** - * Re-authenticates a user using a fresh credential. - * @param {User} user - The user to re-authenticate. - * @param {AuthCredential} credential - The auth credentials. - * @returns {Promise} - */ -export async function reauthenticateWithCredential(user, credential) { - return user.reauthenticateWithCredential.call(user, credential, MODULAR_DEPRECATION_ARG); +export function reauthenticateWithCredential( + user: User, + credential: AuthCredential, +): Promise { + return callUserMethod(user, user.reauthenticateWithCredential, credential); } -/** - * Re-authenticates a user using a fresh phone credential. - * @param {User} user - The user to re-authenticate. - * @param {string} phoneNumber - The phone number. - * @param {ApplicationVerifier} appVerifier - The application verifier. - * @returns {Promise} - */ -export async function reauthenticateWithPhoneNumber(user, phoneNumber, appVerifier) { +export function reauthenticateWithPhoneNumber( + _user: User, + _phoneNumber: string, + _appVerifier?: ApplicationVerifier, +): Promise { throw new Error('reauthenticateWithPhoneNumber is unsupported by the native Firebase SDKs'); } -/** - * Re-authenticate a user with a federated authentication provider (Microsoft, Yahoo). For native platforms, this will open a browser window. - * @param {User} user - The user to re-authenticate. - * @param {AuthProvider} provider - The auth provider. - * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. Web only. - * @returns {Promise} - */ -export async function reauthenticateWithPopup(user, provider, resolver) { - return user.reauthenticateWithPopup.call(user, provider, resolver, MODULAR_DEPRECATION_ARG); +export function reauthenticateWithPopup( + user: User, + provider: AuthProvider, + _resolver?: PopupRedirectResolver, +): Promise { + return callUserMethod(user, user.reauthenticateWithPopup, provider); } -/** - * Re-authenticate a user with a federated authentication provider (Microsoft, Yahoo). For native platforms, this will open a browser window. - * @param {User} user - The user to re-authenticate. - * @param {AuthProvider} provider - The auth provider. - * @param {PopupRedirectResolver} [resolver] - Optional. The popup redirect resolver. Web only. - * @returns {Promise} - */ -export async function reauthenticateWithRedirect(user, provider, resolver) { - return user.reauthenticateWithRedirect.call(user, provider, resolver, MODULAR_DEPRECATION_ARG); +export function reauthenticateWithRedirect( + user: User, + provider: AuthProvider, + _resolver?: PopupRedirectResolver, +): Promise { + return callUserMethod(user, user.reauthenticateWithRedirect, provider); } -/** - * Reloads user account data, if signed in. - * @param {User} user - The user to reload data for. - * @returns {Promise} - */ -export async function reload(user) { - return user.reload.call(user, MODULAR_DEPRECATION_ARG); +export function reload(user: User): Promise { + return callUserMethod(user, user.reload); } -/** - * Sends a verification email to a user. - * @param {User} user - The user to send the email to. - * @param {ActionCodeSettings} [actionCodeSettings] - Optional. Action code settings. - * @returns {Promise} - */ -export async function sendEmailVerification(user, actionCodeSettings) { - return user.sendEmailVerification.call(user, actionCodeSettings, MODULAR_DEPRECATION_ARG); +export function sendEmailVerification( + user: User, + actionCodeSettings?: ActionCodeSettings, +): Promise { + return callUserMethod(user, user.sendEmailVerification, actionCodeSettings); } -/** - * Unlinks a provider from a user account. - * @param {User} user - The user to unlink the provider from. - * @param {string} providerId - The provider ID. - * @returns {Promise} - */ -export async function unlink(user, providerId) { - return user.unlink.call(user, providerId, MODULAR_DEPRECATION_ARG); +export function unlink(user: User, providerId: string): Promise { + return callUserMethod(user, user.unlink, providerId); } -/** - * Updates the user's email address. - * @param {User} user - The user to update the email for. - * @param {string} newEmail - The new email address. - * @returns {Promise} - */ -export async function updateEmail(user, newEmail) { - return user.updateEmail.call(user, newEmail, MODULAR_DEPRECATION_ARG); +export function updateEmail(user: User, newEmail: string): Promise { + return callUserMethod(user, user.updateEmail, newEmail); } -/** - * Updates the user's password. - * @param {User} user - The user to update the password for. - * @param {string} newPassword - The new password. - * @returns {Promise} - */ -export async function updatePassword(user, newPassword) { - return user.updatePassword.call(user, newPassword, MODULAR_DEPRECATION_ARG); +export function updatePassword(user: User, newPassword: string): Promise { + return callUserMethod(user, user.updatePassword, newPassword); } -/** - * Updates the user's phone number. - * @param {User} user - The user to update the phone number for. - * @param {AuthCredential} credential - The auth credentials. - * @returns {Promise} - */ -export async function updatePhoneNumber(user, credential) { - return user.updatePhoneNumber.call(user, credential, MODULAR_DEPRECATION_ARG); +export function updatePhoneNumber(user: User, credential: AuthCredential): Promise { + return callUserMethod(user, user.updatePhoneNumber, credential); } -/** - * Updates a user's profile data. - * @param {User} user - The user to update the profile for. - * @param {{ displayName?: string | null, photoURL?: string | null }} profile - An object containing the profile data to update. - * @returns {Promise} - */ -export async function updateProfile(user, { displayName, photoURL: photoUrl }) { - return user.updateProfile.call( - user, - { displayName, photoURL: photoUrl }, - MODULAR_DEPRECATION_ARG, - ); +export function updateProfile(user: User, profile: UpdateProfile): Promise { + return callUserMethod(user, user.updateProfile, { + displayName: profile.displayName, + photoURL: profile.photoURL, + }); } -/** - * Sends a verification email to a new email address. - * @param {User} user - The user to send the email to. - * @param {string} newEmail - The new email address. - * @param {ActionCodeSettings} [actionCodeSettings] - Optional. Action code settings. - * @returns {Promise} - */ -export async function verifyBeforeUpdateEmail(user, newEmail, actionCodeSettings) { - return user.verifyBeforeUpdateEmail.call( - user, - newEmail, - actionCodeSettings, - MODULAR_DEPRECATION_ARG, - ); +export function verifyBeforeUpdateEmail( + user: User, + newEmail: string, + actionCodeSettings?: ActionCodeSettings, +): Promise { + return callUserMethod(user, user.verifyBeforeUpdateEmail, newEmail, actionCodeSettings); } -/** - * Extracts provider specific AdditionalUserInfo for the given credential. - * @param {UserCredential} userCredential - The user credential. - * @returns {AdditionalUserInfo | null} - */ -export function getAdditionalUserInfo(userCredential) { - return userCredential.additionalUserInfo; +export function getAdditionalUserInfo(userCredential: UserCredential): AdditionalUserInfo | null { + return userCredential.additionalUserInfo ?? null; } -/** - * Returns the custom auth domain for the auth instance. - * @param {Auth} auth - The Auth instance. - * @returns {Promise} - */ -export function getCustomAuthDomain(auth) { - return auth.getCustomAuthDomain.call(auth, MODULAR_DEPRECATION_ARG); +export function getCustomAuthDomain(auth: Auth): Promise { + return callAuthMethod(auth, auth.getCustomAuthDomain); } -/** - * Returns a password validation status - * @param {Auth} auth - The Auth instance. - * @param {string} password - The password to validate. - * @returns {Promise} - */ -export async function validatePassword(auth, password) { - if (!auth || !auth.app) { +export function validatePassword(auth: Auth, password: string): Promise { + if (!auth || !('app' in auth)) { throw new Error( "firebase.auth().validatePassword(*) 'auth' must be a valid Auth instance with an 'app' property. Received: undefined", ); @@ -648,5 +460,10 @@ export async function validatePassword(auth, password) { ); } - return auth.validatePassword.call(auth, password, MODULAR_DEPRECATION_ARG); + const authWithPasswordValidation = auth as AuthWithPasswordValidationInternal; + return callAuthMethod( + authWithPasswordValidation, + authWithPasswordValidation.validatePassword, + password, + ); } diff --git a/packages/auth/lib/types/auth.ts b/packages/auth/lib/types/auth.ts index f8a0921cf4..4210932aee 100644 --- a/packages/auth/lib/types/auth.ts +++ b/packages/auth/lib/types/auth.ts @@ -16,8 +16,17 @@ */ import type { ReactNativeFirebase } from '@react-native-firebase/app'; +import type { + CompleteFn, + ErrorFn, + NextFn, + Observer, + Unsubscribe, +} from '@react-native-firebase/app/dist/module/types/common'; import type { FirebaseAuthTypes } from './namespaced'; +export type { CompleteFn, ErrorFn, NextFn, Observer, Unsubscribe }; + export type FirebaseApp = ReactNativeFirebase.FirebaseApp; export type Auth = FirebaseAuthTypes.Module; export type NativeFirebaseAuthError = FirebaseAuthTypes.NativeFirebaseAuthError; @@ -59,24 +68,57 @@ export type AuthListenerCallback = FirebaseAuthTypes.AuthListenerCallback; export type PhoneAuthSnapshot = FirebaseAuthTypes.PhoneAuthSnapshot; export type PhoneAuthError = FirebaseAuthTypes.PhoneAuthError; export type PhoneAuthListener = FirebaseAuthTypes.PhoneAuthListener; -export type AuthSettings = FirebaseAuthTypes.AuthSettings; export type User = FirebaseAuthTypes.User; export type ActionCodeURL = FirebaseAuthTypes.ActionCodeURL; -export type PasswordPolicy = FirebaseAuthTypes.PasswordPolicy; export type getMultiFactorResolver = FirebaseAuthTypes.getMultiFactorResolver; export type multiFactor = FirebaseAuthTypes.multiFactor; +export interface Config { + apiKey: string; + apiHost: string; + apiScheme: string; + tokenApiHost: string; + sdkClientVersion: string; + authDomain?: string; +} + +export interface AuthErrorMap {} + export interface PopupRedirectResolver {} +export interface Dependencies { + persistence?: Persistence | Persistence[]; + popupRedirectResolver?: PopupRedirectResolver; + errorMap?: AuthErrorMap; +} + export interface ApplicationVerifier { readonly type: string; verify(): Promise; } export type Persistence = { - readonly type: 'SESSION' | 'LOCAL' | 'NONE'; + readonly type: 'SESSION' | 'LOCAL' | 'NONE' | 'COOKIE'; }; +export interface AuthSettings { + appVerificationDisabledForTesting: boolean; +} + +export interface PasswordPolicy { + readonly customStrengthOptions: { + readonly minPasswordLength?: number; + readonly maxPasswordLength?: number; + readonly containsLowercaseLetter?: boolean; + readonly containsUppercaseLetter?: boolean; + readonly containsNumericCharacter?: boolean; + readonly containsNonAlphanumericCharacter?: boolean; + }; + readonly allowedNonAlphanumericCharacters: string; + readonly enforcementState: string; + readonly forceUpgradeOnSignin: boolean; +} + export interface PasswordValidationStatus { readonly isValid: boolean; readonly meetsMinPasswordLength?: boolean; diff --git a/packages/auth/tsconfig.json b/packages/auth/tsconfig.json index 9abc838514..0e79144fc2 100644 --- a/packages/auth/tsconfig.json +++ b/packages/auth/tsconfig.json @@ -14,6 +14,9 @@ ], "@react-native-firebase/app/dist/module/internal": ["../app/dist/typescript/lib/internal"], "@react-native-firebase/app": ["../app/dist/typescript/lib"], + "@react-native-firebase/app/dist/module/types/common": [ + "../app/dist/typescript/lib/types/common" + ], "@react-native-firebase/app/dist/module/types/internal": [ "../app/dist/typescript/lib/types/internal" ] From abf22c2f74f1000df5184669f3b3892702d91135 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Tue, 21 Apr 2026 11:39:42 +0100 Subject: [PATCH 05/45] chore: port over public auth types --- .../packages/auth/auth-js-sdk.d.ts | 4067 +++++++++++++++++ 1 file changed, 4067 insertions(+) create mode 100644 .github/scripts/compare-types/packages/auth/auth-js-sdk.d.ts diff --git a/.github/scripts/compare-types/packages/auth/auth-js-sdk.d.ts b/.github/scripts/compare-types/packages/auth/auth-js-sdk.d.ts new file mode 100644 index 0000000000..a237bcb009 --- /dev/null +++ b/.github/scripts/compare-types/packages/auth/auth-js-sdk.d.ts @@ -0,0 +1,4067 @@ +/** + * Firebase Authentication + * + * @packageDocumentation + */ + +import { CompleteFn } from '@firebase/util'; +import { ErrorFactory } from '@firebase/util'; +import { ErrorFn } from '@firebase/util'; +import { FirebaseApp } from '@firebase/app'; +import { FirebaseError } from '@firebase/util'; +import { NextFn } from '@firebase/util'; +import { Observer } from '@firebase/util'; +import { Unsubscribe } from '@firebase/util'; + +/** + * A response from {@link checkActionCode}. + * + * @public + */ +export declare interface ActionCodeInfo { + /** + * The data associated with the action code. + * + * @remarks + * For the {@link ActionCodeOperation}.PASSWORD_RESET, {@link ActionCodeOperation}.VERIFY_EMAIL, and + * {@link ActionCodeOperation}.RECOVER_EMAIL actions, this object contains an email field with the address + * the email was sent to. + * + * For the {@link ActionCodeOperation}.RECOVER_EMAIL action, which allows a user to undo an email address + * change, this object also contains a `previousEmail` field with the user account's current + * email address. After the action completes, the user's email address will revert to the value + * in the `email` field from the value in `previousEmail` field. + * + * For the {@link ActionCodeOperation}.VERIFY_AND_CHANGE_EMAIL action, which allows a user to verify the + * email before updating it, this object contains a `previousEmail` field with the user account's + * email address before updating. After the action completes, the user's email address will be + * updated to the value in the `email` field from the value in `previousEmail` field. + * + * For the {@link ActionCodeOperation}.REVERT_SECOND_FACTOR_ADDITION action, which allows a user to + * unenroll a newly added second factor, this object contains a `multiFactorInfo` field with + * the information about the second factor. For phone second factor, the `multiFactorInfo` + * is a {@link MultiFactorInfo} object, which contains the phone number. + */ + data: { + email?: string | null; + multiFactorInfo?: MultiFactorInfo | null; + previousEmail?: string | null; + }; + /** + * The type of operation that generated the action code. + */ + operation: (typeof ActionCodeOperation)[keyof typeof ActionCodeOperation]; +} + +/** + * An enumeration of the possible email action types. + * + * @public + */ +export declare const ActionCodeOperation: { + /** The email link sign-in action. */ + readonly EMAIL_SIGNIN: "EMAIL_SIGNIN"; + /** The password reset action. */ + readonly PASSWORD_RESET: "PASSWORD_RESET"; + /** The email revocation action. */ + readonly RECOVER_EMAIL: "RECOVER_EMAIL"; + /** The revert second factor addition email action. */ + readonly REVERT_SECOND_FACTOR_ADDITION: "REVERT_SECOND_FACTOR_ADDITION"; + /** The revert second factor addition email action. */ + readonly VERIFY_AND_CHANGE_EMAIL: "VERIFY_AND_CHANGE_EMAIL"; + /** The email verification action. */ + readonly VERIFY_EMAIL: "VERIFY_EMAIL"; +}; + +/** + * An interface that defines the required continue/state URL with optional Android and iOS + * bundle identifiers. + * + * @public + */ +export declare interface ActionCodeSettings { + /** + * Sets the Android package name. + * + * @remarks + * This will try to open the link in an Android app if it is installed. + */ + android?: { + installApp?: boolean; + minimumVersion?: string; + packageName: string; + }; + /** + * When set to true, the action code link will be be sent as a Universal Link or Android App + * Link and will be opened by the app if installed. + * + * @remarks + * In the false case, the code will be sent to the web widget first and then on continue will + * redirect to the app if installed. + * + * @defaultValue false + */ + handleCodeInApp?: boolean; + /** + * Sets the iOS bundle ID. + * + * @remarks + * This will try to open the link in an iOS app if it is installed. + */ + iOS?: { + bundleId: string; + }; + /** + * Sets the link continue/state URL. + * + * @remarks + * This has different meanings in different contexts: + * - When the link is handled in the web action widgets, this is the deep link in the + * `continueUrl` query parameter. + * - When the link is handled in the app directly, this is the `continueUrl` query parameter in + * the deep link of the Dynamic Link or Hosting link. + */ + url: string; + /** + * When multiple custom dynamic link domains are defined for a project, specify which one to use + * when the link is to be opened via a specified mobile app (for example, `example.page.link`). + * + * + * @defaultValue The first domain is automatically selected. + * + * @deprecated Firebase Dynamic Links is deprecated and will be shut down as early as August + * 2025. Instead, use {@link ActionCodeSettings.linkDomain} to set a custom domain for mobile + * links. Learn more in the {@link https://firebase.google.com/support/dynamic-links-faq | Dynamic Links deprecation FAQ}. + */ + dynamicLinkDomain?: string; + /** + * The optional custom Firebase Hosting domain to use when the link is to be opened via + * a specified mobile app. The domain must be configured in Firebase Hosting and owned + * by the project. This cannot be a default Hosting domain (`web.app` or `firebaseapp.com`). + * + * @defaultValue The default Hosting domain will be used (for example, `example.firebaseapp.com`). + */ + linkDomain?: string; +} + +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * A utility class to parse email action URLs such as password reset, email verification, + * email link sign in, etc. + * + * @public + */ +export declare class ActionCodeURL { + /** + * The API key of the email action link. + */ + readonly apiKey: string; + /** + * The action code of the email action link. + */ + readonly code: string; + /** + * The continue URL of the email action link. Null if not provided. + */ + readonly continueUrl: string | null; + /** + * The language code of the email action link. Null if not provided. + */ + readonly languageCode: string | null; + /** + * The action performed by the email action link. It returns from one of the types from + * {@link ActionCodeInfo} + */ + readonly operation: string; + /** + * The tenant ID of the email action link. Null if the email action is from the parent project. + */ + readonly tenantId: string | null; + /* Excluded from this release type: __constructor */ + /** + * Parses the email action link string and returns an {@link ActionCodeURL} if the link is valid, + * otherwise returns null. + * + * @param link - The email action link string. + * @returns The {@link ActionCodeURL} object, or null if the link is invalid. + * + * @public + */ + static parseLink(link: string): ActionCodeURL | null; +} + +/** + * A structure containing additional user information from a federated identity provider. + * + * @public + */ +export declare interface AdditionalUserInfo { + /** + * Whether the user is new (created via sign-up) or existing (authenticated using sign-in). + */ + readonly isNewUser: boolean; + /** + * Map containing IDP-specific user data. + */ + readonly profile: Record | null; + /** + * Identifier for the provider used to authenticate this user. + */ + readonly providerId: string | null; + /** + * The username if the provider is GitHub or Twitter. + */ + readonly username?: string | null; +} + +declare interface APIUserInfo { + localId?: string; + displayName?: string; + photoUrl?: string; + email?: string; + emailVerified?: boolean; + phoneNumber?: string; + lastLoginAt?: number; + createdAt?: number; + tenantId?: string; + passwordHash?: string; + providerUserInfo?: ProviderUserInfo[]; + mfaInfo?: MfaEnrollment[]; +} + +/** + * A verifier for domain verification and abuse prevention. + * + * @remarks + * Currently, the only implementation is {@link RecaptchaVerifier}. + * + * @public + */ +export declare interface ApplicationVerifier { + /** + * Identifies the type of application verifier (e.g. "recaptcha"). + */ + readonly type: string; + /** + * Executes the verification process. + * + * @returns A Promise for a token that can be used to assert the validity of a request. + */ + verify(): Promise; +} + +declare interface ApplicationVerifierInternal extends ApplicationVerifier { + /* Excluded from this release type: _reset */ +} + +/** + * Applies a verification code sent to the user by email or other out-of-band mechanism. + * + * @param auth - The {@link Auth} instance. + * @param oobCode - A verification code sent to the user. + * + * @public + */ +export declare function applyActionCode(auth: Auth, oobCode: string): Promise; + +declare type AppName = string; + +/** + * Interface representing Firebase Auth service. + * + * @remarks + * See {@link https://firebase.google.com/docs/auth/ | Firebase Authentication} for a full guide + * on how to use the Firebase Auth service. + * + * @public + */ +export declare interface Auth { + /** The {@link @firebase/app#FirebaseApp} associated with the `Auth` service instance. */ + readonly app: FirebaseApp; + /** The name of the app associated with the `Auth` service instance. */ + readonly name: string; + /** The {@link Config} used to initialize this instance. */ + readonly config: Config; + /** + * Changes the type of persistence on the `Auth` instance. + * + * @remarks + * This will affect the currently saved Auth session and applies this type of persistence for + * future sign-in requests, including sign-in with redirect requests. + * + * This makes it easy for a user signing in to specify whether their session should be + * remembered or not. It also makes it easier to never persist the Auth state for applications + * that are shared by other users or have sensitive data. + * + * This method does not work in a Node.js environment. + * + * @example + * ```javascript + * auth.setPersistence(browserSessionPersistence); + * ``` + * + * @param persistence - The {@link Persistence} to use. + */ + setPersistence(persistence: Persistence): Promise; + /** + * The {@link Auth} instance's language code. + * + * @remarks + * This is a readable/writable property. When set to null, the default Firebase Console language + * setting is applied. The language code will propagate to email action templates (password + * reset, email verification and email change revocation), SMS templates for phone authentication, + * reCAPTCHA verifier and OAuth popup/redirect operations provided the specified providers support + * localization with the language code specified. + */ + languageCode: string | null; + /** + * The {@link Auth} instance's tenant ID. + * + * @remarks + * This is a readable/writable property. When you set the tenant ID of an {@link Auth} instance, all + * future sign-in/sign-up operations will pass this tenant ID and sign in or sign up users to + * the specified tenant project. When set to null, users are signed in to the parent project. + * + * @example + * ```javascript + * // Set the tenant ID on Auth instance. + * auth.tenantId = 'TENANT_PROJECT_ID'; + * + * // All future sign-in request now include tenant ID. + * const result = await signInWithEmailAndPassword(auth, email, password); + * // result.user.tenantId should be 'TENANT_PROJECT_ID'. + * ``` + * + * @defaultValue null + */ + tenantId: string | null; + /** + * The {@link Auth} instance's settings. + * + * @remarks + * This is used to edit/read configuration related options such as app verification mode for + * phone authentication. + */ + readonly settings: AuthSettings; + /** + * Adds an observer for changes to the user's sign-in state. + * + * @remarks + * To keep the old behavior, see {@link Auth.onIdTokenChanged}. + * + * @param nextOrObserver - callback triggered on change. + * @param error - Deprecated. This callback is never triggered. Errors + * on signing in/out can be caught in promises returned from + * sign-in/sign-out functions. + * @param completed - Deprecated. This callback is never triggered. + */ + onAuthStateChanged(nextOrObserver: NextOrObserver, error?: ErrorFn, completed?: CompleteFn): Unsubscribe; + /** + * Adds a blocking callback that runs before an auth state change + * sets a new user. + * + * @param callback - callback triggered before new user value is set. + * If this throws, it blocks the user from being set. + * @param onAbort - callback triggered if a later `beforeAuthStateChanged()` + * callback throws, allowing you to undo any side effects. + */ + beforeAuthStateChanged(callback: (user: User | null) => void | Promise, onAbort?: () => void): Unsubscribe; + /** + * Adds an observer for changes to the signed-in user's ID token. + * + * @remarks + * This includes sign-in, sign-out, and token refresh events. + * + * @param nextOrObserver - callback triggered on change. + * @param error - Deprecated. This callback is never triggered. Errors + * on signing in/out can be caught in promises returned from + * sign-in/sign-out functions. + * @param completed - Deprecated. This callback is never triggered. + */ + onIdTokenChanged(nextOrObserver: NextOrObserver, error?: ErrorFn, completed?: CompleteFn): Unsubscribe; + /** + * returns a promise that resolves immediately when the initial + * auth state is settled. When the promise resolves, the current user might be a valid user + * or `null` if the user signed out. + */ + authStateReady(): Promise; + /** The currently signed-in user (or null). */ + readonly currentUser: User | null; + /** The current emulator configuration (or null). */ + readonly emulatorConfig: EmulatorConfig | null; + /** + * Asynchronously sets the provided user as {@link Auth.currentUser} on the {@link Auth} instance. + * + * @remarks + * A new instance copy of the user provided will be made and set as currentUser. + * + * This will trigger {@link Auth.onAuthStateChanged} and {@link Auth.onIdTokenChanged} listeners + * like other sign in methods. + * + * The operation fails with an error if the user to be updated belongs to a different Firebase + * project. + * + * @param user - The new {@link User}. + */ + updateCurrentUser(user: User | null): Promise; + /** + * Sets the current language to the default device/browser preference. + */ + useDeviceLanguage(): void; + /** + * Signs out the current user. This does not automatically revoke the user's ID token. + * + * @remarks + * This method is not supported by {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + */ + signOut(): Promise; +} + +/** + * Interface that represents the credentials returned by an {@link AuthProvider}. + * + * @remarks + * Implementations specify the details about each auth provider's credential requirements. + * + * @public + */ +export declare class AuthCredential { + /** + * The authentication provider ID for the credential. + * + * @remarks + * For example, 'facebook.com', or 'google.com'. + */ + readonly providerId: string; + /** + * The authentication sign in method for the credential. + * + * @remarks + * For example, {@link SignInMethod}.EMAIL_PASSWORD, or + * {@link SignInMethod}.EMAIL_LINK. This corresponds to the sign-in method + * identifier as returned in {@link fetchSignInMethodsForEmail}. + */ + readonly signInMethod: string; + /* Excluded from this release type: __constructor */ + /** + * Returns a JSON-serializable representation of this object. + * + * @returns a JSON-serializable representation of this object. + */ + toJSON(): object; + /* Excluded from this release type: _getIdTokenResponse */ + /* Excluded from this release type: _linkToIdToken */ + /* Excluded from this release type: _getReauthenticationResolver */ +} + +/** + * Interface for an `Auth` error. + * + * @public + */ +export declare interface AuthError extends FirebaseError { + /** Details about the Firebase Auth error. */ + readonly customData: { + /** The name of the Firebase App which triggered this error. */ + readonly appName: string; + /** The email address of the user's account, used for sign-in and linking. */ + readonly email?: string; + /** The phone number of the user's account, used for sign-in and linking. */ + readonly phoneNumber?: string; + /** + * The tenant ID being used for sign-in and linking. + * + * @remarks + * If you use {@link signInWithRedirect} to sign in, + * you have to set the tenant ID on the {@link Auth} instance again as the tenant ID is not persisted + * after redirection. + */ + readonly tenantId?: string; + }; +} + +/* Excluded from this release type: AuthErrorCode */ + +/** + * A map of potential `Auth` error codes, for easier comparison with errors + * thrown by the SDK. + * + * @remarks + * Note that you can't tree-shake individual keys + * in the map, so by using the map you might substantially increase your + * bundle size. + * + * @public + */ +export declare const AuthErrorCodes: { + readonly ADMIN_ONLY_OPERATION: "auth/admin-restricted-operation"; + readonly ARGUMENT_ERROR: "auth/argument-error"; + readonly APP_NOT_AUTHORIZED: "auth/app-not-authorized"; + readonly APP_NOT_INSTALLED: "auth/app-not-installed"; + readonly CAPTCHA_CHECK_FAILED: "auth/captcha-check-failed"; + readonly CODE_EXPIRED: "auth/code-expired"; + readonly CORDOVA_NOT_READY: "auth/cordova-not-ready"; + readonly CORS_UNSUPPORTED: "auth/cors-unsupported"; + readonly CREDENTIAL_ALREADY_IN_USE: "auth/credential-already-in-use"; + readonly CREDENTIAL_MISMATCH: "auth/custom-token-mismatch"; + readonly CREDENTIAL_TOO_OLD_LOGIN_AGAIN: "auth/requires-recent-login"; + readonly DEPENDENT_SDK_INIT_BEFORE_AUTH: "auth/dependent-sdk-initialized-before-auth"; + readonly DYNAMIC_LINK_NOT_ACTIVATED: "auth/dynamic-link-not-activated"; + readonly EMAIL_CHANGE_NEEDS_VERIFICATION: "auth/email-change-needs-verification"; + readonly EMAIL_EXISTS: "auth/email-already-in-use"; + readonly EMULATOR_CONFIG_FAILED: "auth/emulator-config-failed"; + readonly EXPIRED_OOB_CODE: "auth/expired-action-code"; + readonly EXPIRED_POPUP_REQUEST: "auth/cancelled-popup-request"; + readonly INTERNAL_ERROR: "auth/internal-error"; + readonly INVALID_API_KEY: "auth/invalid-api-key"; + readonly INVALID_APP_CREDENTIAL: "auth/invalid-app-credential"; + readonly INVALID_APP_ID: "auth/invalid-app-id"; + readonly INVALID_AUTH: "auth/invalid-user-token"; + readonly INVALID_AUTH_EVENT: "auth/invalid-auth-event"; + readonly INVALID_CERT_HASH: "auth/invalid-cert-hash"; + readonly INVALID_CODE: "auth/invalid-verification-code"; + readonly INVALID_CONTINUE_URI: "auth/invalid-continue-uri"; + readonly INVALID_CORDOVA_CONFIGURATION: "auth/invalid-cordova-configuration"; + readonly INVALID_CUSTOM_TOKEN: "auth/invalid-custom-token"; + readonly INVALID_DYNAMIC_LINK_DOMAIN: "auth/invalid-dynamic-link-domain"; + readonly INVALID_EMAIL: "auth/invalid-email"; + readonly INVALID_EMULATOR_SCHEME: "auth/invalid-emulator-scheme"; + readonly INVALID_IDP_RESPONSE: "auth/invalid-credential"; + readonly INVALID_LOGIN_CREDENTIALS: "auth/invalid-credential"; + readonly INVALID_MESSAGE_PAYLOAD: "auth/invalid-message-payload"; + readonly INVALID_MFA_SESSION: "auth/invalid-multi-factor-session"; + readonly INVALID_OAUTH_CLIENT_ID: "auth/invalid-oauth-client-id"; + readonly INVALID_OAUTH_PROVIDER: "auth/invalid-oauth-provider"; + readonly INVALID_OOB_CODE: "auth/invalid-action-code"; + readonly INVALID_ORIGIN: "auth/unauthorized-domain"; + readonly INVALID_PASSWORD: "auth/wrong-password"; + readonly INVALID_PERSISTENCE: "auth/invalid-persistence-type"; + readonly INVALID_PHONE_NUMBER: "auth/invalid-phone-number"; + readonly INVALID_PROVIDER_ID: "auth/invalid-provider-id"; + readonly INVALID_RECIPIENT_EMAIL: "auth/invalid-recipient-email"; + readonly INVALID_SENDER: "auth/invalid-sender"; + readonly INVALID_SESSION_INFO: "auth/invalid-verification-id"; + readonly INVALID_TENANT_ID: "auth/invalid-tenant-id"; + readonly MFA_INFO_NOT_FOUND: "auth/multi-factor-info-not-found"; + readonly MFA_REQUIRED: "auth/multi-factor-auth-required"; + readonly MISSING_ANDROID_PACKAGE_NAME: "auth/missing-android-pkg-name"; + readonly MISSING_APP_CREDENTIAL: "auth/missing-app-credential"; + readonly MISSING_AUTH_DOMAIN: "auth/auth-domain-config-required"; + readonly MISSING_CODE: "auth/missing-verification-code"; + readonly MISSING_CONTINUE_URI: "auth/missing-continue-uri"; + readonly MISSING_IFRAME_START: "auth/missing-iframe-start"; + readonly MISSING_IOS_BUNDLE_ID: "auth/missing-ios-bundle-id"; + readonly MISSING_OR_INVALID_NONCE: "auth/missing-or-invalid-nonce"; + readonly MISSING_MFA_INFO: "auth/missing-multi-factor-info"; + readonly MISSING_MFA_SESSION: "auth/missing-multi-factor-session"; + readonly MISSING_PHONE_NUMBER: "auth/missing-phone-number"; + readonly MISSING_PASSWORD: "auth/missing-password"; + readonly MISSING_SESSION_INFO: "auth/missing-verification-id"; + readonly MODULE_DESTROYED: "auth/app-deleted"; + readonly NEED_CONFIRMATION: "auth/account-exists-with-different-credential"; + readonly NETWORK_REQUEST_FAILED: "auth/network-request-failed"; + readonly NULL_USER: "auth/null-user"; + readonly NO_AUTH_EVENT: "auth/no-auth-event"; + readonly NO_SUCH_PROVIDER: "auth/no-such-provider"; + readonly OPERATION_NOT_ALLOWED: "auth/operation-not-allowed"; + readonly OPERATION_NOT_SUPPORTED: "auth/operation-not-supported-in-this-environment"; + readonly POPUP_BLOCKED: "auth/popup-blocked"; + readonly POPUP_CLOSED_BY_USER: "auth/popup-closed-by-user"; + readonly PROVIDER_ALREADY_LINKED: "auth/provider-already-linked"; + readonly QUOTA_EXCEEDED: "auth/quota-exceeded"; + readonly REDIRECT_CANCELLED_BY_USER: "auth/redirect-cancelled-by-user"; + readonly REDIRECT_OPERATION_PENDING: "auth/redirect-operation-pending"; + readonly REJECTED_CREDENTIAL: "auth/rejected-credential"; + readonly SECOND_FACTOR_ALREADY_ENROLLED: "auth/second-factor-already-in-use"; + readonly SECOND_FACTOR_LIMIT_EXCEEDED: "auth/maximum-second-factor-count-exceeded"; + readonly TENANT_ID_MISMATCH: "auth/tenant-id-mismatch"; + readonly TIMEOUT: "auth/timeout"; + readonly TOKEN_EXPIRED: "auth/user-token-expired"; + readonly TOO_MANY_ATTEMPTS_TRY_LATER: "auth/too-many-requests"; + readonly UNAUTHORIZED_DOMAIN: "auth/unauthorized-continue-uri"; + readonly UNSUPPORTED_FIRST_FACTOR: "auth/unsupported-first-factor"; + readonly UNSUPPORTED_PERSISTENCE: "auth/unsupported-persistence-type"; + readonly UNSUPPORTED_TENANT_OPERATION: "auth/unsupported-tenant-operation"; + readonly UNVERIFIED_EMAIL: "auth/unverified-email"; + readonly USER_CANCELLED: "auth/user-cancelled"; + readonly USER_DELETED: "auth/user-not-found"; + readonly USER_DISABLED: "auth/user-disabled"; + readonly USER_MISMATCH: "auth/user-mismatch"; + readonly USER_SIGNED_OUT: "auth/user-signed-out"; + readonly WEAK_PASSWORD: "auth/weak-password"; + readonly WEB_STORAGE_UNSUPPORTED: "auth/web-storage-unsupported"; + readonly ALREADY_INITIALIZED: "auth/already-initialized"; + readonly RECAPTCHA_NOT_ENABLED: "auth/recaptcha-not-enabled"; + readonly MISSING_RECAPTCHA_TOKEN: "auth/missing-recaptcha-token"; + readonly INVALID_RECAPTCHA_TOKEN: "auth/invalid-recaptcha-token"; + readonly INVALID_RECAPTCHA_ACTION: "auth/invalid-recaptcha-action"; + readonly MISSING_CLIENT_TYPE: "auth/missing-client-type"; + readonly MISSING_RECAPTCHA_VERSION: "auth/missing-recaptcha-version"; + readonly INVALID_RECAPTCHA_VERSION: "auth/invalid-recaptcha-version"; + readonly INVALID_REQ_TYPE: "auth/invalid-req-type"; + readonly INVALID_HOSTING_LINK_DOMAIN: "auth/invalid-hosting-link-domain"; +}; + +/** + * A mapping of error codes to error messages. + * + * @remarks + * + * While error messages are useful for debugging (providing verbose textual + * context around what went wrong), these strings take up a lot of space in the + * compiled code. When deploying code in production, using {@link prodErrorMap} + * will save you roughly 10k compressed/gzipped over {@link debugErrorMap}. You + * can select the error map during initialization: + * + * ```javascript + * initializeAuth(app, {errorMap: debugErrorMap}) + * ``` + * + * When initializing Auth, {@link prodErrorMap} is default. + * + * @public + */ +export declare interface AuthErrorMap { +} + +/* Excluded from this release type: AuthErrorParams */ + +/* Excluded from this release type: AuthEvent */ + +/* Excluded from this release type: AuthEventConsumer */ + +declare interface AuthEventError extends Error { + code: string; + message: string; +} + +/* Excluded from this release type: AuthEventType */ + +/* Excluded from this release type: AuthInternal */ + +declare class AuthPopup { + readonly window: Window | null; + associatedEvent: string | null; + constructor(window: Window | null); + close(): void; +} + +/** + * Interface that represents an auth provider, used to facilitate creating {@link AuthCredential}. + * + * @public + */ +export declare interface AuthProvider { + /** + * Provider for which credentials can be constructed. + */ + readonly providerId: string; +} + +/** + * Interface representing an {@link Auth} instance's settings. + * + * @remarks Currently used for enabling/disabling app verification for phone Auth testing. + * + * @public + */ +export declare interface AuthSettings { + /** + * When set, this property disables app verification for the purpose of testing phone + * authentication. For this property to take effect, it needs to be set before rendering a + * reCAPTCHA app verifier. When this is disabled, a mock reCAPTCHA is rendered instead. This is + * useful for manual testing during development or for automated integration tests. + * + * In order to use this feature, you will need to + * {@link https://firebase.google.com/docs/auth/web/phone-auth#test-with-whitelisted-phone-numbers | whitelist your phone number} + * via the Firebase Console. + * + * The default value is false (app verification is enabled). + */ + appVerificationDisabledForTesting: boolean; +} + +/** + * MFA Info as returned by the API. + */ +declare interface BaseMfaEnrollment { + mfaEnrollmentId: string; + enrolledAt: number; + displayName?: string; +} + +/** + * Common code to all OAuth providers. This is separate from the + * {@link OAuthProvider} so that child providers (like + * {@link GoogleAuthProvider}) don't inherit the `credential` instance method. + * Instead, they rely on a static `credential` method. + */ +declare abstract class BaseOAuthProvider extends FederatedAuthProvider implements AuthProvider { + /* Excluded from this release type: scopes */ + /** + * Add an OAuth scope to the credential. + * + * @param scope - Provider OAuth scope to add. + */ + addScope(scope: string): AuthProvider; + /** + * Retrieve the current list of OAuth scopes. + */ + getScopes(): string[]; +} + +/** + * Adds a blocking callback that runs before an auth state change + * sets a new user. + * + * @param auth - The {@link Auth} instance. + * @param callback - callback triggered before new user value is set. + * If this throws, it blocks the user from being set. + * @param onAbort - callback triggered if a later `beforeAuthStateChanged()` + * callback throws, allowing you to undo any side effects. + */ +export declare function beforeAuthStateChanged(auth: Auth, callback: (user: User | null) => void | Promise, onAbort?: () => void): Unsubscribe; + +/** + * An implementation of {@link Persistence} of type `COOKIE`, for use on the client side in + * applications leveraging hybrid rendering and middleware. + * + * @remarks This persistence method requires companion middleware to function, such as that provided + * by {@link https://firebaseopensource.com/projects/firebaseextended/reactfire/ | ReactFire} for + * NextJS. + * @beta + */ +export declare const browserCookiePersistence: Persistence; + +/** + * An implementation of {@link Persistence} of type `LOCAL` using `localStorage` + * for the underlying storage. + * + * @public + */ +export declare const browserLocalPersistence: Persistence; + +/** + * An implementation of {@link PopupRedirectResolver} suitable for browser + * based applications. + * + * @remarks + * This method does not work in a Node.js environment. + * + * @public + */ +export declare const browserPopupRedirectResolver: PopupRedirectResolver; + +/** + * An implementation of {@link Persistence} of `SESSION` using `sessionStorage` + * for the underlying storage. + * + * @public + */ +export declare const browserSessionPersistence: Persistence; + +/** + * Checks a verification code sent to the user by email or other out-of-band mechanism. + * + * @returns metadata about the code. + * + * @param auth - The {@link Auth} instance. + * @param oobCode - A verification code sent to the user. + * + * @public + */ +export declare function checkActionCode(auth: Auth, oobCode: string): Promise; + +/* Excluded from this release type: ClientPlatform */ +export { CompleteFn } + +/** + * Interface representing the `Auth` config. + * + * @public + */ +export declare interface Config { + /** + * The API Key used to communicate with the Firebase Auth backend. + */ + apiKey: string; + /** + * The host at which the Firebase Auth backend is running. + */ + apiHost: string; + /** + * The scheme used to communicate with the Firebase Auth backend. + */ + apiScheme: string; + /** + * The host at which the Secure Token API is running. + */ + tokenApiHost: string; + /** + * The SDK Client Version. + */ + sdkClientVersion: string; + /** + * The domain at which the web widgets are hosted (provided via Firebase Config). + */ + authDomain?: string; +} + +/* Excluded from this release type: ConfigInternal */ + +/** + * A result from a phone number sign-in, link, or reauthenticate call. + * + * @public + */ +export declare interface ConfirmationResult { + /** + * The phone number authentication operation's verification ID. + * + * @remarks + * This can be used along with the verification code to initialize a + * {@link PhoneAuthCredential}. + */ + readonly verificationId: string; + /** + * Finishes a phone number sign-in, link, or reauthentication. + * + * @example + * ```javascript + * const confirmationResult = await signInWithPhoneNumber(auth, phoneNumber, applicationVerifier); + * // Obtain verificationCode from the user. + * const userCredential = await confirmationResult.confirm(verificationCode); + * ``` + * + * @param verificationCode - The code that was sent to the user's mobile device. + */ + confirm(verificationCode: string): Promise; +} + +/** + * Completes the password reset process, given a confirmation code and new password. + * + * @param auth - The {@link Auth} instance. + * @param oobCode - A confirmation code sent to the user. + * @param newPassword - The new password. + * + * @public + */ +export declare function confirmPasswordReset(auth: Auth, oobCode: string, newPassword: string): Promise; + +/** + * Changes the {@link Auth} instance to communicate with the Firebase Auth Emulator, instead of production + * Firebase Auth services. + * + * @remarks + * This must be called synchronously immediately following the first call to + * {@link initializeAuth}. Do not use with production credentials as emulator + * traffic is not encrypted. + * + * + * @example + * ```javascript + * connectAuthEmulator(auth, 'http://127.0.0.1:9099', { disableWarnings: true }); + * ``` + * + * @param auth - The {@link Auth} instance. + * @param url - The URL at which the emulator is running (eg, 'http://localhost:9099'). + * @param options - Optional. `options.disableWarnings` defaults to `false`. Set it to + * `true` to disable the warning banner attached to the DOM. + * + * @public + */ +export declare function connectAuthEmulator(auth: Auth, url: string, options?: { + disableWarnings: boolean; +}): void; + +/** + * Creates a new user account associated with the specified email address and password. + * + * @remarks + * On successful creation of the user account, this user will also be signed in to your application. + * + * User account creation can fail if the account already exists or the password is invalid. + * + * This method is not supported on {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * + * Note: The email address acts as a unique identifier for the user and enables an email-based + * password reset. This function will create a new user account and set the initial user password. + * + * @param auth - The {@link Auth} instance. + * @param email - The user's email address. + * @param password - The user's chosen password. + * + * @public + */ +export declare function createUserWithEmailAndPassword(auth: Auth, email: string, password: string): Promise; + +/** + * Map of OAuth Custom Parameters. + * + * @public + */ +export declare type CustomParameters = Record; + +/** + * A verbose error map with detailed descriptions for most error codes. + * + * See discussion at {@link AuthErrorMap} + * + * @public + */ +export declare const debugErrorMap: AuthErrorMap; + +/** + * Deletes and signs out the user. + * + * @remarks + * Important: this is a security-sensitive operation that requires the user to have recently + * signed in. If this requirement isn't met, ask the user to authenticate again and then call + * {@link reauthenticateWithCredential}. + * + * @param user - The user. + * + * @public + */ +export declare function deleteUser(user: User): Promise; + +/** + * The dependencies that can be used to initialize an {@link Auth} instance. + * + * @remarks + * + * The modular SDK enables tree shaking by allowing explicit declarations of + * dependencies. For example, a web app does not need to include code that + * enables Cordova redirect sign in. That functionality is therefore split into + * {@link browserPopupRedirectResolver} and + * {@link cordovaPopupRedirectResolver}. The dependencies object is how Auth is + * configured to reduce bundle sizes. + * + * There are two ways to initialize an {@link Auth} instance: {@link getAuth} and + * {@link initializeAuth}. `getAuth` initializes everything using + * platform-specific configurations, while `initializeAuth` takes a + * `Dependencies` object directly, giving you more control over what is used. + * + * @public + */ +export declare interface Dependencies { + /** + * Which {@link Persistence} to use. If this is an array, the first + * `Persistence` that the device supports is used. The SDK searches for an + * existing account in order and, if one is found in a secondary + * `Persistence`, the account is moved to the primary `Persistence`. + * + * If no persistence is provided, the SDK falls back on + * {@link inMemoryPersistence}. + */ + persistence?: Persistence | Persistence[]; + /** + * The {@link PopupRedirectResolver} to use. This value depends on the + * platform. Options are {@link browserPopupRedirectResolver} and + * {@link cordovaPopupRedirectResolver}. This field is optional if neither + * {@link signInWithPopup} or {@link signInWithRedirect} are being used. + */ + popupRedirectResolver?: PopupRedirectResolver; + /** + * Which {@link AuthErrorMap} to use. + */ + errorMap?: AuthErrorMap; +} + +/** + * Interface that represents the credentials returned by {@link EmailAuthProvider} for + * {@link ProviderId}.PASSWORD + * + * @remarks + * Covers both {@link SignInMethod}.EMAIL_PASSWORD and + * {@link SignInMethod}.EMAIL_LINK. + * + * @public + */ +export declare class EmailAuthCredential extends AuthCredential { + /* Excluded from this release type: _email */ + /* Excluded from this release type: _password */ + /* Excluded from this release type: _tenantId */ + /* Excluded from this release type: __constructor */ + /* Excluded from this release type: _fromEmailAndPassword */ + /* Excluded from this release type: _fromEmailAndCode */ + /** {@inheritdoc AuthCredential.toJSON} */ + toJSON(): object; + /** + * Static method to deserialize a JSON representation of an object into an {@link AuthCredential}. + * + * @param json - Either `object` or the stringified representation of the object. When string is + * provided, `JSON.parse` would be called first. + * + * @returns If the JSON input does not represent an {@link AuthCredential}, null is returned. + */ + static fromJSON(json: object | string): EmailAuthCredential | null; + /* Excluded from this release type: _getIdTokenResponse */ + /* Excluded from this release type: _linkToIdToken */ + /* Excluded from this release type: _getReauthenticationResolver */ +} + +/** + * Provider for generating {@link EmailAuthCredential}. + * + * @public + */ +export declare class EmailAuthProvider implements AuthProvider { + /** + * Always set to {@link ProviderId}.PASSWORD, even for email link. + */ + static readonly PROVIDER_ID: 'password'; + /** + * Always set to {@link SignInMethod}.EMAIL_PASSWORD. + */ + static readonly EMAIL_PASSWORD_SIGN_IN_METHOD: 'password'; + /** + * Always set to {@link SignInMethod}.EMAIL_LINK. + */ + static readonly EMAIL_LINK_SIGN_IN_METHOD: 'emailLink'; + /** + * Always set to {@link ProviderId}.PASSWORD, even for email link. + */ + readonly providerId: "password"; + /** + * Initialize an {@link AuthCredential} using an email and password. + * + * @example + * ```javascript + * const authCredential = EmailAuthProvider.credential(email, password); + * const userCredential = await signInWithCredential(auth, authCredential); + * ``` + * + * @example + * ```javascript + * const userCredential = await signInWithEmailAndPassword(auth, email, password); + * ``` + * + * @param email - Email address. + * @param password - User account password. + * @returns The auth provider credential. + */ + static credential(email: string, password: string): EmailAuthCredential; + /** + * Initialize an {@link AuthCredential} using an email and an email link after a sign in with + * email link operation. + * + * @example + * ```javascript + * const authCredential = EmailAuthProvider.credentialWithLink(auth, email, emailLink); + * const userCredential = await signInWithCredential(auth, authCredential); + * ``` + * + * @example + * ```javascript + * await sendSignInLinkToEmail(auth, email); + * // Obtain emailLink from user. + * const userCredential = await signInWithEmailLink(auth, email, emailLink); + * ``` + * + * @param auth - The {@link Auth} instance used to verify the link. + * @param email - Email address. + * @param emailLink - Sign-in email link. + * @returns - The auth provider credential. + */ + static credentialWithLink(email: string, emailLink: string): EmailAuthCredential; +} + +/** + * Configuration of Firebase Authentication Emulator. + * @public + */ +export declare interface EmulatorConfig { + /** + * The protocol used to communicate with the emulator ("http"/"https"). + */ + readonly protocol: string; + /** + * The hostname of the emulator, which may be a domain ("localhost"), IPv4 address ("127.0.0.1") + * or quoted IPv6 address ("[::1]"). + */ + readonly host: string; + /** + * The port of the emulator, or null if port isn't specified (i.e. protocol default). + */ + readonly port: number | null; + /** + * The emulator-specific options. + */ + readonly options: { + /** + * Whether the warning banner attached to the DOM was disabled. + */ + readonly disableWarnings: boolean; + }; +} + +declare const enum EnforcementState { + ENFORCE = "ENFORCE", + AUDIT = "AUDIT", + OFF = "OFF", + ENFORCEMENT_STATE_UNSPECIFIED = "ENFORCEMENT_STATE_UNSPECIFIED" +} +export { ErrorFn } + +/* Excluded from this release type: EventManager */ + +/** + * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.FACEBOOK. + * + * @example + * ```javascript + * // Sign in using a redirect. + * const provider = new FacebookAuthProvider(); + * // Start a sign in process for an unauthenticated user. + * provider.addScope('user_birthday'); + * await signInWithRedirect(auth, provider); + * // This will trigger a full page redirect away from your app + * + * // After returning from the redirect when your app initializes you can obtain the result + * const result = await getRedirectResult(auth); + * if (result) { + * // This is the signed-in user + * const user = result.user; + * // This gives you a Facebook Access Token. + * const credential = FacebookAuthProvider.credentialFromResult(result); + * const token = credential.accessToken; + * } + * ``` + * + * @example + * ```javascript + * // Sign in using a popup. + * const provider = new FacebookAuthProvider(); + * provider.addScope('user_birthday'); + * const result = await signInWithPopup(auth, provider); + * + * // The signed-in user info. + * const user = result.user; + * // This gives you a Facebook Access Token. + * const credential = FacebookAuthProvider.credentialFromResult(result); + * const token = credential.accessToken; + * ``` + * + * @public + */ +export declare class FacebookAuthProvider extends BaseOAuthProvider { + /** Always set to {@link SignInMethod}.FACEBOOK. */ + static readonly FACEBOOK_SIGN_IN_METHOD: 'facebook.com'; + /** Always set to {@link ProviderId}.FACEBOOK. */ + static readonly PROVIDER_ID: 'facebook.com'; + constructor(); + /** + * Creates a credential for Facebook. + * + * @example + * ```javascript + * // `event` from the Facebook auth.authResponseChange callback. + * const credential = FacebookAuthProvider.credential(event.authResponse.accessToken); + * const result = await signInWithCredential(credential); + * ``` + * + * @param accessToken - Facebook access token. + */ + static credential(accessToken: string): OAuthCredential; + /** + * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}. + * + * @param userCredential - The user credential. + */ + static credentialFromResult(userCredential: UserCredential): OAuthCredential | null; + /** + * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was + * thrown during a sign-in, link, or reauthenticate operation. + * + * @param userCredential - The user credential. + */ + static credentialFromError(error: FirebaseError): OAuthCredential | null; + private static credentialFromTaggedObject; +} + +/** + * An enum of factors that may be used for multifactor authentication. + * + * @public + */ +export declare const FactorId: { + /** Phone as second factor */ + readonly PHONE: "phone"; + readonly TOTP: "totp"; +}; + +/** + * The base class for all Federated providers (OAuth (including OIDC), SAML). + * + * This class is not meant to be instantiated directly. + * + * @public + */ +declare abstract class FederatedAuthProvider implements AuthProvider { + readonly providerId: string; + /* Excluded from this release type: defaultLanguageCode */ + /* Excluded from this release type: customParameters */ + /** + * Constructor for generic OAuth providers. + * + * @param providerId - Provider for which credentials should be generated. + */ + constructor(providerId: string); + /** + * Set the language gode. + * + * @param languageCode - language code + */ + setDefaultLanguage(languageCode: string | null): void; + /** + * Sets the OAuth custom parameters to pass in an OAuth request for popup and redirect sign-in + * operations. + * + * @remarks + * For a detailed list, check the reserved required OAuth 2.0 parameters such as `client_id`, + * `redirect_uri`, `scope`, `response_type`, and `state` are not allowed and will be ignored. + * + * @param customOAuthParameters - The custom OAuth parameters to pass in the OAuth request. + */ + setCustomParameters(customOAuthParameters: CustomParameters): AuthProvider; + /** + * Retrieve the current list of {@link CustomParameters}. + */ + getCustomParameters(): CustomParameters; +} + +/** + * Gets the list of possible sign in methods for the given email address. This method returns an + * empty list when + * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection} + * is enabled, irrespective of the number of authentication methods available for the given email. + * + * @remarks + * This is useful to differentiate methods of sign-in for the same provider, eg. + * {@link EmailAuthProvider} which has 2 methods of sign-in, + * {@link SignInMethod}.EMAIL_PASSWORD and + * {@link SignInMethod}.EMAIL_LINK. + * + * @param auth - The {@link Auth} instance. + * @param email - The user's email address. + * + * Deprecated. Migrating off of this method is recommended as a security best-practice. + * Learn more in the Identity Platform documentation for + * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection}. + * @public + */ +export declare function fetchSignInMethodsForEmail(auth: Auth, email: string): Promise; + +declare interface FinalizeMfaResponse { + idToken: string; + refreshToken: string; +} + +/* Excluded from this release type: GenericAuthErrorParams */ + +/** + * Extracts provider specific {@link AdditionalUserInfo} for the given credential. + * + * @param userCredential - The user credential. + * + * @public + */ +export declare function getAdditionalUserInfo(userCredential: UserCredential): AdditionalUserInfo | null; + +/** + * Returns the Auth instance associated with the provided {@link @firebase/app#FirebaseApp}. + * If no instance exists, initializes an Auth instance with platform-specific default dependencies. + * + * @param app - The Firebase App. + * + * @public + */ +export declare function getAuth(app?: FirebaseApp): Auth; + +/** + * Returns a JSON Web Token (JWT) used to identify the user to a Firebase service. + * + * @remarks + * Returns the current token if it has not expired or if it will not expire in the next five + * minutes. Otherwise, this will refresh the token and return a new one. + * + * @param user - The user. + * @param forceRefresh - Force refresh regardless of token expiration. + * + * @public + */ +export declare function getIdToken(user: User, forceRefresh?: boolean): Promise; + +/** + * Returns a deserialized JSON Web Token (JWT) used to identify the user to a Firebase service. + * + * @remarks + * Returns the current token if it has not expired or if it will not expire in the next five + * minutes. Otherwise, this will refresh the token and return a new one. + * + * @param user - The user. + * @param forceRefresh - Force refresh regardless of token expiration. + * + * @public + */ +export declare function getIdTokenResult(user: User, forceRefresh?: boolean): Promise; + +/** + * Provides a {@link MultiFactorResolver} suitable for completion of a + * multi-factor flow. + * + * @param auth - The {@link Auth} instance. + * @param error - The {@link MultiFactorError} raised during a sign-in, or + * reauthentication operation. + * + * @public + */ +export declare function getMultiFactorResolver(auth: Auth, error: MultiFactorError): MultiFactorResolver; + +declare interface GetRecaptchaConfigResponse { + recaptchaKey: string; + recaptchaEnforcementState: RecaptchaEnforcementProviderState[]; +} + +/** + * Returns a {@link UserCredential} from the redirect-based sign-in flow. + * + * @remarks + * If sign-in succeeded, returns the signed in user. If sign-in was unsuccessful, fails with an + * error. If no redirect operation was called, returns `null`. + * + * This method does not work in a Node.js environment or with {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * + * @example + * ```javascript + * // Sign in using a redirect. + * const provider = new FacebookAuthProvider(); + * // You can add additional scopes to the provider: + * provider.addScope('user_birthday'); + * // Start a sign in process for an unauthenticated user. + * await signInWithRedirect(auth, provider); + * // This will trigger a full page redirect away from your app + * + * // After returning from the redirect when your app initializes you can obtain the result + * const result = await getRedirectResult(auth); + * if (result) { + * // This is the signed-in user + * const user = result.user; + * // This gives you a Facebook Access Token. + * const credential = provider.credentialFromResult(auth, result); + * const token = credential.accessToken; + * } + * // As this API can be used for sign-in, linking and reauthentication, + * // check the operationType to determine what triggered this redirect + * // operation. + * const operationType = result.operationType; + * ``` + * + * @param auth - The {@link Auth} instance. + * @param resolver - An instance of {@link PopupRedirectResolver}, optional + * if already supplied to {@link initializeAuth} or provided by {@link getAuth}. + * + * @public + */ +export declare function getRedirectResult(auth: Auth, resolver?: PopupRedirectResolver): Promise; + +/** + * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.GITHUB. + * + * @remarks + * GitHub requires an OAuth 2.0 redirect, so you can either handle the redirect directly, or use + * the {@link signInWithPopup} handler: + * + * @example + * ```javascript + * // Sign in using a redirect. + * const provider = new GithubAuthProvider(); + * // Start a sign in process for an unauthenticated user. + * provider.addScope('repo'); + * await signInWithRedirect(auth, provider); + * // This will trigger a full page redirect away from your app + * + * // After returning from the redirect when your app initializes you can obtain the result + * const result = await getRedirectResult(auth); + * if (result) { + * // This is the signed-in user + * const user = result.user; + * // This gives you a GitHub Access Token. + * const credential = GithubAuthProvider.credentialFromResult(result); + * const token = credential.accessToken; + * } + * ``` + * + * @example + * ```javascript + * // Sign in using a popup. + * const provider = new GithubAuthProvider(); + * provider.addScope('repo'); + * const result = await signInWithPopup(auth, provider); + * + * // The signed-in user info. + * const user = result.user; + * // This gives you a GitHub Access Token. + * const credential = GithubAuthProvider.credentialFromResult(result); + * const token = credential.accessToken; + * ``` + * @public + */ +export declare class GithubAuthProvider extends BaseOAuthProvider { + /** Always set to {@link SignInMethod}.GITHUB. */ + static readonly GITHUB_SIGN_IN_METHOD: 'github.com'; + /** Always set to {@link ProviderId}.GITHUB. */ + static readonly PROVIDER_ID: 'github.com'; + constructor(); + /** + * Creates a credential for GitHub. + * + * @param accessToken - GitHub access token. + */ + static credential(accessToken: string): OAuthCredential; + /** + * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}. + * + * @param userCredential - The user credential. + */ + static credentialFromResult(userCredential: UserCredential): OAuthCredential | null; + /** + * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was + * thrown during a sign-in, link, or reauthenticate operation. + * + * @param userCredential - The user credential. + */ + static credentialFromError(error: FirebaseError): OAuthCredential | null; + private static credentialFromTaggedObject; +} + +/** + * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.GOOGLE. + * + * @example + * ```javascript + * // Sign in using a redirect. + * const provider = new GoogleAuthProvider(); + * // Start a sign in process for an unauthenticated user. + * provider.addScope('profile'); + * provider.addScope('email'); + * await signInWithRedirect(auth, provider); + * // This will trigger a full page redirect away from your app + * + * // After returning from the redirect when your app initializes you can obtain the result + * const result = await getRedirectResult(auth); + * if (result) { + * // This is the signed-in user + * const user = result.user; + * // This gives you a Google Access Token. + * const credential = GoogleAuthProvider.credentialFromResult(result); + * const token = credential.accessToken; + * } + * ``` + * + * @example + * ```javascript + * // Sign in using a popup. + * const provider = new GoogleAuthProvider(); + * provider.addScope('profile'); + * provider.addScope('email'); + * const result = await signInWithPopup(auth, provider); + * + * // The signed-in user info. + * const user = result.user; + * // This gives you a Google Access Token. + * const credential = GoogleAuthProvider.credentialFromResult(result); + * const token = credential.accessToken; + * ``` + * + * @public + */ +export declare class GoogleAuthProvider extends BaseOAuthProvider { + /** Always set to {@link SignInMethod}.GOOGLE. */ + static readonly GOOGLE_SIGN_IN_METHOD: 'google.com'; + /** Always set to {@link ProviderId}.GOOGLE. */ + static readonly PROVIDER_ID: 'google.com'; + constructor(); + /** + * Creates a credential for Google. At least one of ID token and access token is required. + * + * @example + * ```javascript + * // \`googleUser\` from the onsuccess Google Sign In callback. + * const credential = GoogleAuthProvider.credential(googleUser.getAuthResponse().id_token); + * const result = await signInWithCredential(credential); + * ``` + * + * @param idToken - Google ID token. + * @param accessToken - Google access token. + */ + static credential(idToken?: string | null, accessToken?: string | null): OAuthCredential; + /** + * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}. + * + * @param userCredential - The user credential. + */ + static credentialFromResult(userCredential: UserCredential): OAuthCredential | null; + /** + * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was + * thrown during a sign-in, link, or reauthenticate operation. + * + * @param userCredential - The user credential. + */ + static credentialFromError(error: FirebaseError): OAuthCredential | null; + private static credentialFromTaggedObject; +} + +/** + * Raw encoded JWT + * + */ +declare type IdToken = string; + +/* Excluded from this release type: IdTokenMfaResponse */ + +/* Excluded from this release type: IdTokenResponse */ + +/* Excluded from this release type: IdTokenResponseKind */ + +/** + * Interface representing ID token result obtained from {@link User.getIdTokenResult}. + * + * @remarks + * `IdTokenResult` contains the ID token JWT string and other helper properties for getting different data + * associated with the token as well as all the decoded payload claims. + * + * Note that these claims are not to be trusted as they are parsed client side. Only server side + * verification can guarantee the integrity of the token claims. + * + * @public + */ +export declare interface IdTokenResult { + /** + * The authentication time formatted as a UTC string. + * + * @remarks + * This is the time the user authenticated (signed in) and not the time the token was refreshed. + */ + authTime: string; + /** The ID token expiration time formatted as a UTC string. */ + expirationTime: string; + /** The ID token issuance time formatted as a UTC string. */ + issuedAtTime: string; + /** + * The sign-in provider through which the ID token was obtained (anonymous, custom, phone, + * password, etc). + * + * @remarks + * Note, this does not map to provider IDs. + */ + signInProvider: string | null; + /** + * The type of second factor associated with this session, provided the user was multi-factor + * authenticated (eg. phone, etc). + */ + signInSecondFactor: string | null; + /** The Firebase Auth ID token JWT string. */ + token: string; + /** + * The entire payload claims of the ID token including the standard reserved claims as well as + * the custom claims. + */ + claims: ParsedToken; +} + +/** + * An implementation of {@link Persistence} of type `LOCAL` using `indexedDB` + * for the underlying storage. + * + * @public + */ +export declare const indexedDBLocalPersistence: Persistence; + +/** + * Initializes an {@link Auth} instance with fine-grained control over + * {@link Dependencies}. + * + * @remarks + * + * This function allows more control over the {@link Auth} instance than + * {@link getAuth}. `getAuth` uses platform-specific defaults to supply + * the {@link Dependencies}. In general, `getAuth` is the easiest way to + * initialize Auth and works for most use cases. Use `initializeAuth` if you + * need control over which persistence layer is used, or to minimize bundle + * size if you're not using either `signInWithPopup` or `signInWithRedirect`. + * + * For example, if your app only uses anonymous accounts and you only want + * accounts saved for the current session, initialize `Auth` with: + * + * ```js + * const auth = initializeAuth(app, { + * persistence: browserSessionPersistence, + * popupRedirectResolver: undefined, + * }); + * ``` + * + * @public + */ +export declare function initializeAuth(app: FirebaseApp, deps?: Dependencies): Auth; + +/** + * Loads the reCAPTCHA configuration into the `Auth` instance. + * + * @remarks + * This will load the reCAPTCHA config, which indicates whether the reCAPTCHA + * verification flow should be triggered for each auth provider, into the + * current Auth session. + * + * If initializeRecaptchaConfig() is not invoked, the auth flow will always start + * without reCAPTCHA verification. If the provider is configured to require reCAPTCHA + * verification, the SDK will transparently load the reCAPTCHA config and restart the + * auth flows. + * + * Thus, by calling this optional method, you will reduce the latency of future auth flows. + * Loading the reCAPTCHA config early will also enhance the signal collected by reCAPTCHA. + * + * This method does not work in a Node.js environment. + * + * @example + * ```javascript + * initializeRecaptchaConfig(auth); + * ``` + * + * @param auth - The {@link Auth} instance. + * + * @public + */ +export declare function initializeRecaptchaConfig(auth: Auth): Promise; + +/** + * An implementation of {@link Persistence} of type 'NONE'. + * + * @public + */ +export declare const inMemoryPersistence: Persistence; + +/** + * Checks if an incoming link is a sign-in with email link suitable for {@link signInWithEmailLink}. + * + * @param auth - The {@link Auth} instance. + * @param emailLink - The link sent to the user's email address. + * + * @public + */ +export declare function isSignInWithEmailLink(auth: Auth, emailLink: string): boolean; + +/** + * Links the user account with the given credentials. + * + * @remarks + * An {@link AuthProvider} can be used to generate the credential. + * + * @param user - The user. + * @param credential - The auth credential. + * + * @public + */ +export declare function linkWithCredential(user: User, credential: AuthCredential): Promise; + +/** + * Links the user account with the given phone number. + * + * @remarks + * This method does not work in a Node.js environment. + * + * @param user - The user. + * @param phoneNumber - The user's phone number in E.164 format (e.g. +16505550101). + * @param appVerifier - The {@link ApplicationVerifier}. + * + * @public + */ +export declare function linkWithPhoneNumber(user: User, phoneNumber: string, appVerifier?: ApplicationVerifier): Promise; + +/** + * Links the authenticated provider to the user account using a pop-up based OAuth flow. + * + * @remarks + * If the linking is successful, the returned result will contain the user and the provider's credential. + * + * This method does not work in a Node.js environment. + * + * @example + * ```javascript + * // Sign in using some other provider. + * const result = await signInWithEmailAndPassword(auth, email, password); + * // Link using a popup. + * const provider = new FacebookAuthProvider(); + * await linkWithPopup(result.user, provider); + * ``` + * + * @param user - The user. + * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}. + * Non-OAuth providers like {@link EmailAuthProvider} will throw an error. + * @param resolver - An instance of {@link PopupRedirectResolver}, optional + * if already supplied to {@link initializeAuth} or provided by {@link getAuth}. + * + * @public + */ +export declare function linkWithPopup(user: User, provider: AuthProvider, resolver?: PopupRedirectResolver): Promise; + +/** + * Links the {@link OAuthProvider} to the user account using a full-page redirect flow. + * @remarks + * To handle the results and errors for this operation, refer to {@link getRedirectResult}. + * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices + * | best practices} when using {@link linkWithRedirect}. + * + * This method does not work in a Node.js environment or with {@link Auth} instances + * created with a {@link @firebase/app#FirebaseServerApp}. + * + * @example + * ```javascript + * // Sign in using some other provider. + * const result = await signInWithEmailAndPassword(auth, email, password); + * // Link using a redirect. + * const provider = new FacebookAuthProvider(); + * await linkWithRedirect(result.user, provider); + * // This will trigger a full page redirect away from your app + * + * // After returning from the redirect when your app initializes you can obtain the result + * const result = await getRedirectResult(auth); + * ``` + * + * @param user - The user. + * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}. + * Non-OAuth providers like {@link EmailAuthProvider} will throw an error. + * @param resolver - An instance of {@link PopupRedirectResolver}, optional + * if already supplied to {@link initializeAuth} or provided by {@link getAuth}. + * + * @public + */ +export declare function linkWithRedirect(user: User, provider: AuthProvider, resolver?: PopupRedirectResolver): Promise; + +/** + * MfaEnrollment can be any subtype of BaseMfaEnrollment, currently only PhoneMfaEnrollment and TotpMfaEnrollment are supported. + */ +declare type MfaEnrollment = PhoneMfaEnrollment | TotpMfaEnrollment; + +/** + * The {@link MultiFactorUser} corresponding to the user. + * + * @remarks + * This is used to access all multi-factor properties and operations related to the user. + * + * @param user - The user. + * + * @public + */ +export declare function multiFactor(user: User): MultiFactorUser; + +/** + * The base class for asserting ownership of a second factor. + * + * @remarks + * This is used to facilitate enrollment of a second factor on an existing user or sign-in of a + * user who already verified the first factor. + * + * @public + */ +export declare interface MultiFactorAssertion { + /** The identifier of the second factor. */ + readonly factorId: (typeof FactorId)[keyof typeof FactorId]; +} + +/** + * The error thrown when the user needs to provide a second factor to sign in successfully. + * + * @remarks + * The error code for this error is `auth/multi-factor-auth-required`. + * + * @example + * ```javascript + * let resolver; + * let multiFactorHints; + * + * signInWithEmailAndPassword(auth, email, password) + * .then((result) => { + * // User signed in. No 2nd factor challenge is needed. + * }) + * .catch((error) => { + * if (error.code == 'auth/multi-factor-auth-required') { + * resolver = getMultiFactorResolver(auth, error); + * multiFactorHints = resolver.hints; + * } else { + * // Handle other errors. + * } + * }); + * + * // Obtain a multiFactorAssertion by verifying the second factor. + * + * const userCredential = await resolver.resolveSignIn(multiFactorAssertion); + * ``` + * + * @public + */ +export declare interface MultiFactorError extends AuthError { + /** Details about the MultiFactorError. */ + readonly customData: AuthError['customData'] & { + /** + * The type of operation (sign-in, linking, or re-authentication) that raised the error. + */ + readonly operationType: (typeof OperationType)[keyof typeof OperationType]; + }; +} + +/** + * A structure containing the information of a second factor entity. + * + * @public + */ +export declare interface MultiFactorInfo { + /** The multi-factor enrollment ID. */ + readonly uid: string; + /** The user friendly name of the current second factor. */ + readonly displayName?: string | null; + /** The enrollment date of the second factor formatted as a UTC string. */ + readonly enrollmentTime: string; + /** The identifier of the second factor. */ + readonly factorId: (typeof FactorId)[keyof typeof FactorId]; +} + +/** + * The class used to facilitate recovery from {@link MultiFactorError} when a user needs to + * provide a second factor to sign in. + * + * @example + * ```javascript + * let resolver; + * let multiFactorHints; + * + * signInWithEmailAndPassword(auth, email, password) + * .then((result) => { + * // User signed in. No 2nd factor challenge is needed. + * }) + * .catch((error) => { + * if (error.code == 'auth/multi-factor-auth-required') { + * resolver = getMultiFactorResolver(auth, error); + * // Show UI to let user select second factor. + * multiFactorHints = resolver.hints; + * } else { + * // Handle other errors. + * } + * }); + * + * // The enrolled second factors that can be used to complete + * // sign-in are returned in the `MultiFactorResolver.hints` list. + * // UI needs to be presented to allow the user to select a second factor + * // from that list. + * + * const selectedHint = // ; selected from multiFactorHints + * const phoneAuthProvider = new PhoneAuthProvider(auth); + * const phoneInfoOptions = { + * multiFactorHint: selectedHint, + * session: resolver.session + * }; + * const verificationId = phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, appVerifier); + * // Store `verificationId` and show UI to let user enter verification code. + * + * // UI to enter verification code and continue. + * // Continue button click handler + * const phoneAuthCredential = PhoneAuthProvider.credential(verificationId, verificationCode); + * const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(phoneAuthCredential); + * const userCredential = await resolver.resolveSignIn(multiFactorAssertion); + * ``` + * + * @public + */ +export declare interface MultiFactorResolver { + /** + * The list of hints for the second factors needed to complete the sign-in for the current + * session. + */ + readonly hints: MultiFactorInfo[]; + /** + * The session identifier for the current sign-in flow, which can be used to complete the second + * factor sign-in. + */ + readonly session: MultiFactorSession; + /** + * A helper function to help users complete sign in with a second factor using an + * {@link MultiFactorAssertion} confirming the user successfully completed the second factor + * challenge. + * + * @example + * ```javascript + * const phoneAuthCredential = PhoneAuthProvider.credential(verificationId, verificationCode); + * const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(phoneAuthCredential); + * const userCredential = await resolver.resolveSignIn(multiFactorAssertion); + * ``` + * + * @param assertion - The multi-factor assertion to resolve sign-in with. + * @returns The promise that resolves with the user credential object. + */ + resolveSignIn(assertion: MultiFactorAssertion): Promise; +} + +/** + * An interface defining the multi-factor session object used for enrolling a second factor on a + * user or helping sign in an enrolled user with a second factor. + * + * @public + */ +export declare interface MultiFactorSession { +} + +/** + * An interface that defines the multi-factor related properties and operations pertaining + * to a {@link User}. + * + * @public + */ +export declare interface MultiFactorUser { + /** Returns a list of the user's enrolled second factors. */ + readonly enrolledFactors: MultiFactorInfo[]; + /** + * Returns the session identifier for a second factor enrollment operation. This is used to + * identify the user trying to enroll a second factor. + * + * @example + * ```javascript + * const multiFactorUser = multiFactor(auth.currentUser); + * const multiFactorSession = await multiFactorUser.getSession(); + * + * // Send verification code. + * const phoneAuthProvider = new PhoneAuthProvider(auth); + * const phoneInfoOptions = { + * phoneNumber: phoneNumber, + * session: multiFactorSession + * }; + * const verificationId = await phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, appVerifier); + * + * // Obtain verification code from user. + * const phoneAuthCredential = PhoneAuthProvider.credential(verificationId, verificationCode); + * const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(phoneAuthCredential); + * await multiFactorUser.enroll(multiFactorAssertion); + * ``` + * + * @returns The promise that resolves with the {@link MultiFactorSession}. + */ + getSession(): Promise; + /** + * + * Enrolls a second factor as identified by the {@link MultiFactorAssertion} for the + * user. + * + * @remarks + * On resolution, the user tokens are updated to reflect the change in the JWT payload. + * Accepts an additional display name parameter used to identify the second factor to the end + * user. Recent re-authentication is required for this operation to succeed. On successful + * enrollment, existing Firebase sessions (refresh tokens) are revoked. When a new factor is + * enrolled, an email notification is sent to the user’s email. + * + * @example + * ```javascript + * const multiFactorUser = multiFactor(auth.currentUser); + * const multiFactorSession = await multiFactorUser.getSession(); + * + * // Send verification code. + * const phoneAuthProvider = new PhoneAuthProvider(auth); + * const phoneInfoOptions = { + * phoneNumber: phoneNumber, + * session: multiFactorSession + * }; + * const verificationId = await phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, appVerifier); + * + * // Obtain verification code from user. + * const phoneAuthCredential = PhoneAuthProvider.credential(verificationId, verificationCode); + * const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(phoneAuthCredential); + * await multiFactorUser.enroll(multiFactorAssertion); + * // Second factor enrolled. + * ``` + * + * @param assertion - The multi-factor assertion to enroll with. + * @param displayName - The display name of the second factor. + */ + enroll(assertion: MultiFactorAssertion, displayName?: string | null): Promise; + /** + * Unenrolls the specified second factor. + * + * @remarks + * To specify the factor to remove, pass a {@link MultiFactorInfo} object (retrieved from + * {@link MultiFactorUser.enrolledFactors}) or the + * factor's UID string. Sessions are not revoked when the account is unenrolled. An email + * notification is likely to be sent to the user notifying them of the change. Recent + * re-authentication is required for this operation to succeed. When an existing factor is + * unenrolled, an email notification is sent to the user’s email. + * + * @example + * ```javascript + * const multiFactorUser = multiFactor(auth.currentUser); + * // Present user the option to choose which factor to unenroll. + * await multiFactorUser.unenroll(multiFactorUser.enrolledFactors[i]) + * ``` + * + * @param option - The multi-factor option to unenroll. + * @returns - A `Promise` which resolves when the unenroll operation is complete. + */ + unenroll(option: MultiFactorInfo | string): Promise; +} + +declare type MutableUserInfo = { + -readonly [K in keyof UserInfo]: UserInfo[K]; +}; +export { NextFn } + +/** + * Type definition for an event callback. + * + * @privateRemarks TODO(avolkovi): should we consolidate with Subscribe since we're changing the API anyway? + * + * @public + */ +export declare type NextOrObserver = NextFn | Observer; + +/** + * Represents the OAuth credentials returned by an {@link OAuthProvider}. + * + * @remarks + * Implementations specify the details about each auth provider's credential requirements. + * + * @public + */ +export declare class OAuthCredential extends AuthCredential { + /** + * The OAuth ID token associated with the credential if it belongs to an OIDC provider, + * such as `google.com`. + * @readonly + */ + idToken?: string; + /** + * The OAuth access token associated with the credential if it belongs to an + * {@link OAuthProvider}, such as `facebook.com`, `twitter.com`, etc. + * @readonly + */ + accessToken?: string; + /** + * The OAuth access token secret associated with the credential if it belongs to an OAuth 1.0 + * provider, such as `twitter.com`. + * @readonly + */ + secret?: string; + private nonce?; + private pendingToken; + /* Excluded from this release type: _fromParams */ + /** {@inheritdoc AuthCredential.toJSON} */ + toJSON(): object; + /** + * Static method to deserialize a JSON representation of an object into an + * {@link AuthCredential}. + * + * @param json - Input can be either Object or the stringified representation of the object. + * When string is provided, JSON.parse would be called first. + * + * @returns If the JSON input does not represent an {@link AuthCredential}, null is returned. + */ + static fromJSON(json: string | object): OAuthCredential | null; + /* Excluded from this release type: _getIdTokenResponse */ + /* Excluded from this release type: _linkToIdToken */ + /* Excluded from this release type: _getReauthenticationResolver */ + private buildRequest; +} + +/** + * Defines the options for initializing an {@link OAuthCredential}. + * + * @remarks + * For ID tokens with nonce claim, the raw nonce has to also be provided. + * + * @public + */ +export declare interface OAuthCredentialOptions { + /** + * The OAuth ID token used to initialize the {@link OAuthCredential}. + */ + idToken?: string; + /** + * The OAuth access token used to initialize the {@link OAuthCredential}. + */ + accessToken?: string; + /** + * The raw nonce associated with the ID token. + * + * @remarks + * It is required when an ID token with a nonce field is provided. The SHA-256 hash of the + * raw nonce must match the nonce field in the ID token. + */ + rawNonce?: string; +} + +declare interface OAuthCredentialParams { + idToken?: string | null; + accessToken?: string | null; + oauthToken?: string; + secret?: string; + oauthTokenSecret?: string; + nonce?: string; + pendingToken?: string; + providerId: string; + signInMethod: string; +} + +/** + * Provider for generating generic {@link OAuthCredential}. + * + * @example + * ```javascript + * // Sign in using a redirect. + * const provider = new OAuthProvider('google.com'); + * // Start a sign in process for an unauthenticated user. + * provider.addScope('profile'); + * provider.addScope('email'); + * await signInWithRedirect(auth, provider); + * // This will trigger a full page redirect away from your app + * + * // After returning from the redirect when your app initializes you can obtain the result + * const result = await getRedirectResult(auth); + * if (result) { + * // This is the signed-in user + * const user = result.user; + * // This gives you a OAuth Access Token for the provider. + * const credential = provider.credentialFromResult(auth, result); + * const token = credential.accessToken; + * } + * ``` + * + * @example + * ```javascript + * // Sign in using a popup. + * const provider = new OAuthProvider('google.com'); + * provider.addScope('profile'); + * provider.addScope('email'); + * const result = await signInWithPopup(auth, provider); + * + * // The signed-in user info. + * const user = result.user; + * // This gives you a OAuth Access Token for the provider. + * const credential = provider.credentialFromResult(auth, result); + * const token = credential.accessToken; + * ``` + * @public + */ +export declare class OAuthProvider extends BaseOAuthProvider { + /** + * Creates an {@link OAuthCredential} from a JSON string or a plain object. + * @param json - A plain object or a JSON string + */ + static credentialFromJSON(json: object | string): OAuthCredential; + /** + * Creates a {@link OAuthCredential} from a generic OAuth provider's access token or ID token. + * + * @remarks + * The raw nonce is required when an ID token with a nonce field is provided. The SHA-256 hash of + * the raw nonce must match the nonce field in the ID token. + * + * @example + * ```javascript + * // `googleUser` from the onsuccess Google Sign In callback. + * // Initialize a generate OAuth provider with a `google.com` providerId. + * const provider = new OAuthProvider('google.com'); + * const credential = provider.credential({ + * idToken: googleUser.getAuthResponse().id_token, + * }); + * const result = await signInWithCredential(credential); + * ``` + * + * @param params - Either the options object containing the ID token, access token and raw nonce + * or the ID token string. + */ + credential(params: OAuthCredentialOptions): OAuthCredential; + /** An internal credential method that accepts more permissive options */ + private _credential; + /** + * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}. + * + * @param userCredential - The user credential. + */ + static credentialFromResult(userCredential: UserCredential): OAuthCredential | null; + /** + * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was + * thrown during a sign-in, link, or reauthenticate operation. + * + * @param userCredential - The user credential. + */ + static credentialFromError(error: FirebaseError): OAuthCredential | null; + private static oauthCredentialFromTaggedObject; +} + +/** + * Adds an observer for changes to the user's sign-in state. + * + * @remarks + * To keep the old behavior, see {@link onIdTokenChanged}. + * + * @param auth - The {@link Auth} instance. + * @param nextOrObserver - callback triggered on change. + * @param error - Deprecated. This callback is never triggered. Errors + * on signing in/out can be caught in promises returned from + * sign-in/sign-out functions. + * @param completed - Deprecated. This callback is never triggered. + * + * @public + */ +export declare function onAuthStateChanged(auth: Auth, nextOrObserver: NextOrObserver, error?: ErrorFn, completed?: CompleteFn): Unsubscribe; + +/** + * Adds an observer for changes to the signed-in user's ID token. + * + * @remarks + * This includes sign-in, sign-out, and token refresh events. + * This will not be triggered automatically upon ID token expiration. Use {@link User.getIdToken} to refresh the ID token. + * + * @param auth - The {@link Auth} instance. + * @param nextOrObserver - callback triggered on change. + * @param error - Deprecated. This callback is never triggered. Errors + * on signing in/out can be caught in promises returned from + * sign-in/sign-out functions. + * @param completed - Deprecated. This callback is never triggered. + * + * @public + */ +export declare function onIdTokenChanged(auth: Auth, nextOrObserver: NextOrObserver, error?: ErrorFn, completed?: CompleteFn): Unsubscribe; + +/** + * Enumeration of supported operation types. + * + * @public + */ +export declare const OperationType: { + /** Operation involving linking an additional provider to an already signed-in user. */ + readonly LINK: "link"; + /** Operation involving using a provider to reauthenticate an already signed-in user. */ + readonly REAUTHENTICATE: "reauthenticate"; + /** Operation involving signing in a user. */ + readonly SIGN_IN: "signIn"; +}; + +/** + * Parses the email action link string and returns an {@link ActionCodeURL} if + * the link is valid, otherwise returns null. + * + * @public + */ +export declare function parseActionCodeURL(link: string): ActionCodeURL | null; + +/** + * Interface representing a parsed ID token. + * + * @privateRemarks TODO(avolkovi): consolidate with parsed_token in implementation. + * + * @public + */ +export declare interface ParsedToken { + /** Expiration time of the token. */ + 'exp'?: string; + /** UID of the user. */ + 'sub'?: string; + /** Time at which authentication was performed. */ + 'auth_time'?: string; + /** Issuance time of the token. */ + 'iat'?: string; + /** Firebase specific claims, containing the provider(s) used to authenticate the user. */ + 'firebase'?: { + 'sign_in_provider'?: string; + 'sign_in_second_factor'?: string; + 'identities'?: Record; + }; + /** Map of any additional custom claims. */ + [key: string]: unknown; +} + +/** + * A structure specifying password policy requirements. + * + * @public + */ +export declare interface PasswordPolicy { + /** + * Requirements enforced by this password policy. + */ + readonly customStrengthOptions: { + /** + * Minimum password length, or undefined if not configured. + */ + readonly minPasswordLength?: number; + /** + * Maximum password length, or undefined if not configured. + */ + readonly maxPasswordLength?: number; + /** + * Whether the password should contain a lowercase letter, or undefined if not configured. + */ + readonly containsLowercaseLetter?: boolean; + /** + * Whether the password should contain an uppercase letter, or undefined if not configured. + */ + readonly containsUppercaseLetter?: boolean; + /** + * Whether the password should contain a numeric character, or undefined if not configured. + */ + readonly containsNumericCharacter?: boolean; + /** + * Whether the password should contain a non-alphanumeric character, or undefined if not configured. + */ + readonly containsNonAlphanumericCharacter?: boolean; + }; + /** + * List of characters that are considered non-alphanumeric during validation. + */ + readonly allowedNonAlphanumericCharacters: string; + /** + * The enforcement state of the policy. Can be 'OFF' or 'ENFORCE'. + */ + readonly enforcementState: string; + /** + * Whether existing passwords must meet the policy. + */ + readonly forceUpgradeOnSignin: boolean; +} + +/* Excluded from this release type: PasswordPolicyCustomStrengthOptions */ + +/* Excluded from this release type: PasswordPolicyInternal */ + +/** + * A structure indicating which password policy requirements were met or violated and what the + * requirements are. + * + * @public + */ +export declare interface PasswordValidationStatus { + /** + * Whether the password meets all requirements. + */ + readonly isValid: boolean; + /** + * Whether the password meets the minimum password length, or undefined if not required. + */ + readonly meetsMinPasswordLength?: boolean; + /** + * Whether the password meets the maximum password length, or undefined if not required. + */ + readonly meetsMaxPasswordLength?: boolean; + /** + * Whether the password contains a lowercase letter, or undefined if not required. + */ + readonly containsLowercaseLetter?: boolean; + /** + * Whether the password contains an uppercase letter, or undefined if not required. + */ + readonly containsUppercaseLetter?: boolean; + /** + * Whether the password contains a numeric character, or undefined if not required. + */ + readonly containsNumericCharacter?: boolean; + /** + * Whether the password contains a non-alphanumeric character, or undefined if not required. + */ + readonly containsNonAlphanumericCharacter?: boolean; + /** + * The policy used to validate the password. + */ + readonly passwordPolicy: PasswordPolicy; +} + +declare type PersistedBlob = Record; + +/** + * An interface covering the possible persistence mechanism types. + * + * @public + */ +export declare interface Persistence { + /** + * Type of Persistence. + * - 'SESSION' is used for temporary persistence such as `sessionStorage`. + * - 'LOCAL' is used for long term persistence such as `localStorage` or `IndexedDB`. + * - 'NONE' is used for in-memory, or no persistence. + * - 'COOKIE' is used for cookie persistence, useful for server-side rendering. + */ + readonly type: 'SESSION' | 'LOCAL' | 'NONE' | 'COOKIE'; +} + +declare interface PersistenceInternal extends Persistence { + type: PersistenceType; + _isAvailable(): Promise; + _set(key: string, value: PersistenceValue): Promise; + _get(key: string): Promise; + _remove(key: string): Promise; + _addListener(key: string, listener: StorageEventListener): void; + _removeListener(key: string, listener: StorageEventListener): void; + _shouldAllowMigration?: boolean; +} + +declare const enum PersistenceType { + SESSION = "SESSION", + LOCAL = "LOCAL", + NONE = "NONE", + COOKIE = "COOKIE" +} + +declare type PersistenceValue = PersistedBlob | string; + +/** + * Represents the credentials returned by {@link PhoneAuthProvider}. + * + * @public + */ +export declare class PhoneAuthCredential extends AuthCredential { + private readonly params; + private constructor(); + /* Excluded from this release type: _fromVerification */ + /* Excluded from this release type: _fromTokenResponse */ + /* Excluded from this release type: _getIdTokenResponse */ + /* Excluded from this release type: _linkToIdToken */ + /* Excluded from this release type: _getReauthenticationResolver */ + /* Excluded from this release type: _makeVerificationRequest */ + /** {@inheritdoc AuthCredential.toJSON} */ + toJSON(): object; + /** Generates a phone credential based on a plain object or a JSON string. */ + static fromJSON(json: object | string): PhoneAuthCredential | null; +} + +/** + * Provider for generating an {@link PhoneAuthCredential}. + * + * @remarks + * `PhoneAuthProvider` does not work in a Node.js environment. + * + * @example + * ```javascript + * // 'recaptcha-container' is the ID of an element in the DOM. + * const applicationVerifier = new RecaptchaVerifier('recaptcha-container'); + * const provider = new PhoneAuthProvider(auth); + * const verificationId = await provider.verifyPhoneNumber('+16505550101', applicationVerifier); + * // Obtain the verificationCode from the user. + * const phoneCredential = PhoneAuthProvider.credential(verificationId, verificationCode); + * const userCredential = await signInWithCredential(auth, phoneCredential); + * ``` + * + * @public + */ +export declare class PhoneAuthProvider { + /** Always set to {@link ProviderId}.PHONE. */ + static readonly PROVIDER_ID: 'phone'; + /** Always set to {@link SignInMethod}.PHONE. */ + static readonly PHONE_SIGN_IN_METHOD: 'phone'; + /** Always set to {@link ProviderId}.PHONE. */ + readonly providerId: "phone"; + private readonly auth; + /** + * @param auth - The Firebase {@link Auth} instance in which sign-ins should occur. + * + */ + constructor(auth: Auth); + /** + * + * Starts a phone number authentication flow by sending a verification code to the given phone + * number. + * + * @example + * ```javascript + * const provider = new PhoneAuthProvider(auth); + * const verificationId = await provider.verifyPhoneNumber(phoneNumber, applicationVerifier); + * // Obtain verificationCode from the user. + * const authCredential = PhoneAuthProvider.credential(verificationId, verificationCode); + * const userCredential = await signInWithCredential(auth, authCredential); + * ``` + * + * @example + * An alternative flow is provided using the `signInWithPhoneNumber` method. + * ```javascript + * const confirmationResult = signInWithPhoneNumber(auth, phoneNumber, applicationVerifier); + * // Obtain verificationCode from the user. + * const userCredential = confirmationResult.confirm(verificationCode); + * ``` + * + * @param phoneInfoOptions - The user's {@link PhoneInfoOptions}. The phone number should be in + * E.164 format (e.g. +16505550101). + * @param applicationVerifier - An {@link ApplicationVerifier}, which prevents + * requests from unauthorized clients. This SDK includes an implementation + * based on reCAPTCHA v2, {@link RecaptchaVerifier}. If you've enabled + * reCAPTCHA Enterprise bot protection in Enforce mode, this parameter is + * optional; in all other configurations, the parameter is required. + * + * @returns A Promise for a verification ID that can be passed to + * {@link PhoneAuthProvider.credential} to identify this flow. + */ + verifyPhoneNumber(phoneOptions: PhoneInfoOptions | string, applicationVerifier?: ApplicationVerifier): Promise; + /** + * Creates a phone auth credential, given the verification ID from + * {@link PhoneAuthProvider.verifyPhoneNumber} and the code that was sent to the user's + * mobile device. + * + * @example + * ```javascript + * const provider = new PhoneAuthProvider(auth); + * const verificationId = provider.verifyPhoneNumber(phoneNumber, applicationVerifier); + * // Obtain verificationCode from the user. + * const authCredential = PhoneAuthProvider.credential(verificationId, verificationCode); + * const userCredential = signInWithCredential(auth, authCredential); + * ``` + * + * @example + * An alternative flow is provided using the `signInWithPhoneNumber` method. + * ```javascript + * const confirmationResult = await signInWithPhoneNumber(auth, phoneNumber, applicationVerifier); + * // Obtain verificationCode from the user. + * const userCredential = await confirmationResult.confirm(verificationCode); + * ``` + * + * @param verificationId - The verification ID returned from {@link PhoneAuthProvider.verifyPhoneNumber}. + * @param verificationCode - The verification code sent to the user's mobile device. + * + * @returns The auth provider credential. + */ + static credential(verificationId: string, verificationCode: string): PhoneAuthCredential; + /** + * Generates an {@link AuthCredential} from a {@link UserCredential}. + * @param userCredential - The user credential. + */ + static credentialFromResult(userCredential: UserCredential): AuthCredential | null; + /** + * Returns an {@link AuthCredential} when passed an error. + * + * @remarks + * + * This method works for errors like + * `auth/account-exists-with-different-credentials`. This is useful for + * recovering when attempting to set a user's phone number but the number + * in question is already tied to another account. For example, the following + * code tries to update the current user's phone number, and if that + * fails, links the user with the account associated with that number: + * + * ```js + * const provider = new PhoneAuthProvider(auth); + * const verificationId = await provider.verifyPhoneNumber(number, verifier); + * try { + * const code = ''; // Prompt the user for the verification code + * await updatePhoneNumber( + * auth.currentUser, + * PhoneAuthProvider.credential(verificationId, code)); + * } catch (e) { + * if ((e as FirebaseError)?.code === 'auth/account-exists-with-different-credential') { + * const cred = PhoneAuthProvider.credentialFromError(e); + * await linkWithCredential(auth.currentUser, cred); + * } + * } + * + * // At this point, auth.currentUser.phoneNumber === number. + * ``` + * + * @param error - The error to generate a credential from. + */ + static credentialFromError(error: FirebaseError): AuthCredential | null; + private static credentialFromTaggedObject; +} + +/** + * The information required to verify the ownership of a phone number. + * + * @remarks + * The information that's required depends on whether you are doing single-factor sign-in, + * multi-factor enrollment or multi-factor sign-in. + * + * @public + */ +export declare type PhoneInfoOptions = PhoneSingleFactorInfoOptions | PhoneMultiFactorEnrollInfoOptions | PhoneMultiFactorSignInInfoOptions; + +/** + * An MFA provided by SMS verification. + */ +declare interface PhoneMfaEnrollment extends BaseMfaEnrollment { + phoneInfo: string; +} + +/** + * The class for asserting ownership of a phone second factor. Provided by + * {@link PhoneMultiFactorGenerator.assertion}. + * + * @public + */ +export declare interface PhoneMultiFactorAssertion extends MultiFactorAssertion { +} + +/** + * Options used for enrolling a second factor. + * + * @public + */ +export declare interface PhoneMultiFactorEnrollInfoOptions { + /** Phone number to send a verification code to. */ + phoneNumber: string; + /** The {@link MultiFactorSession} obtained via {@link MultiFactorUser.getSession}. */ + session: MultiFactorSession; +} + +/** + * Provider for generating a {@link PhoneMultiFactorAssertion}. + * + * @public + */ +export declare class PhoneMultiFactorGenerator { + private constructor(); + /** + * Provides a {@link PhoneMultiFactorAssertion} to confirm ownership of the phone second factor. + * + * @remarks + * This method does not work in a Node.js environment. + * + * @param phoneAuthCredential - A credential provided by {@link PhoneAuthProvider.credential}. + * @returns A {@link PhoneMultiFactorAssertion} which can be used with + * {@link MultiFactorResolver.resolveSignIn} + */ + static assertion(credential: PhoneAuthCredential): PhoneMultiFactorAssertion; + /** + * The identifier of the phone second factor: `phone`. + */ + static FACTOR_ID: string; +} + +/** + * The subclass of the {@link MultiFactorInfo} interface for phone number + * second factors. The `factorId` of this second factor is {@link FactorId}.PHONE. + * @public + */ +export declare interface PhoneMultiFactorInfo extends MultiFactorInfo { + /** The phone number associated with the current second factor. */ + readonly phoneNumber: string; +} + +/** + * Options used for signing in with a second factor. + * + * @public + */ +export declare interface PhoneMultiFactorSignInInfoOptions { + /** + * The {@link MultiFactorInfo} obtained via {@link MultiFactorResolver.hints}. + * + * One of `multiFactorHint` or `multiFactorUid` is required. + */ + multiFactorHint?: MultiFactorInfo; + /** + * The uid of the second factor. + * + * One of `multiFactorHint` or `multiFactorUid` is required. + */ + multiFactorUid?: string; + /** The {@link MultiFactorSession} obtained via {@link MultiFactorResolver.session}. */ + session: MultiFactorSession; +} + +/* Excluded from this release type: PhoneOrOauthTokenResponse */ + +/** + * Options used for single-factor sign-in. + * + * @public + */ +export declare interface PhoneSingleFactorInfoOptions { + /** Phone number to send a verification code to. */ + phoneNumber: string; +} + +/** + * A resolver used for handling DOM specific operations like {@link signInWithPopup} + * or {@link signInWithRedirect}. + * + * @public + */ +export declare interface PopupRedirectResolver { +} + +/* Excluded from this release type: PopupRedirectResolverInternal */ + +/** + * A minimal error map with all verbose error messages stripped. + * + * See discussion at {@link AuthErrorMap} + * + * @public + */ +export declare const prodErrorMap: AuthErrorMap; + +/** + * Enumeration of supported providers. + * + * @public + */ +export declare const ProviderId: { + /** Facebook provider ID */ + readonly FACEBOOK: "facebook.com"; + /** GitHub provider ID */ + readonly GITHUB: "github.com"; + /** Google provider ID */ + readonly GOOGLE: "google.com"; + /** Password provider */ + readonly PASSWORD: "password"; + /** Phone provider */ + readonly PHONE: "phone"; + /** Twitter provider ID */ + readonly TWITTER: "twitter.com"; +}; + +/* Excluded from this release type: ProviderId_2 */ + +declare interface ProviderUserInfo { + providerId: string; + rawId?: string; + email?: string; + displayName?: string; + photoUrl?: string; + phoneNumber?: string; +} + +/** + * Interface for a supplied `AsyncStorage`. + * + * @public + */ +export declare interface ReactNativeAsyncStorage { + /** + * Persist an item in storage. + * + * @param key - storage key. + * @param value - storage value. + */ + setItem(key: string, value: string): Promise; + /** + * Retrieve an item from storage. + * + * @param key - storage key. + */ + getItem(key: string): Promise; + /** + * Remove an item from storage. + * + * @param key - storage key. + */ + removeItem(key: string): Promise; +} + +/** + * Re-authenticates a user using a fresh credential. + * + * @remarks + * Use before operations such as {@link updatePassword} that require tokens from recent sign-in + * attempts. This method can be used to recover from a `CREDENTIAL_TOO_OLD_LOGIN_AGAIN` error + * or a `TOKEN_EXPIRED` error. + * + * This method is not supported on any {@link User} signed in by {@link Auth} instances + * created with a {@link @firebase/app#FirebaseServerApp}. + * + * @param user - The user. + * @param credential - The auth credential. + * + * @public + */ +export declare function reauthenticateWithCredential(user: User, credential: AuthCredential): Promise; + +/** + * Re-authenticates a user using a fresh phone credential. + * + * @remarks + * Use before operations such as {@link updatePassword} that require tokens from recent sign-in attempts. + * + * This method does not work in a Node.js environment or on any {@link User} signed in by + * {@link Auth} instances created with a {@link @firebase/app#FirebaseServerApp}. + * + * @param user - The user. + * @param phoneNumber - The user's phone number in E.164 format (e.g. +16505550101). + * @param appVerifier - The {@link ApplicationVerifier}. + * + * @public + */ +export declare function reauthenticateWithPhoneNumber(user: User, phoneNumber: string, appVerifier?: ApplicationVerifier): Promise; + +/** + * Reauthenticates the current user with the specified {@link OAuthProvider} using a pop-up based + * OAuth flow. + * + * @remarks + * If the reauthentication is successful, the returned result will contain the user and the + * provider's credential. + * + * This method does not work in a Node.js environment or on any {@link User} signed in by + * {@link Auth} instances created with a {@link @firebase/app#FirebaseServerApp}. + * + * @example + * ```javascript + * // Sign in using a popup. + * const provider = new FacebookAuthProvider(); + * const result = await signInWithPopup(auth, provider); + * // Reauthenticate using a popup. + * await reauthenticateWithPopup(result.user, provider); + * ``` + * + * @param user - The user. + * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}. + * Non-OAuth providers like {@link EmailAuthProvider} will throw an error. + * @param resolver - An instance of {@link PopupRedirectResolver}, optional + * if already supplied to {@link initializeAuth} or provided by {@link getAuth}. + * + * @public + */ +export declare function reauthenticateWithPopup(user: User, provider: AuthProvider, resolver?: PopupRedirectResolver): Promise; + +/** + * Reauthenticates the current user with the specified {@link OAuthProvider} using a full-page redirect flow. + * @remarks + * To handle the results and errors for this operation, refer to {@link getRedirectResult}. + * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices + * | best practices} when using {@link reauthenticateWithRedirect}. + * + * This method does not work in a Node.js environment or with {@link Auth} instances + * created with a {@link @firebase/app#FirebaseServerApp}. + * + * @example + * ```javascript + * // Sign in using a redirect. + * const provider = new FacebookAuthProvider(); + * const result = await signInWithRedirect(auth, provider); + * // This will trigger a full page redirect away from your app + * + * // After returning from the redirect when your app initializes you can obtain the result + * const result = await getRedirectResult(auth); + * // Reauthenticate using a redirect. + * await reauthenticateWithRedirect(result.user, provider); + * // This will again trigger a full page redirect away from your app + * + * // After returning from the redirect when your app initializes you can obtain the result + * const result = await getRedirectResult(auth); + * ``` + * + * @param user - The user. + * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}. + * Non-OAuth providers like {@link EmailAuthProvider} will throw an error. + * @param resolver - An instance of {@link PopupRedirectResolver}, optional + * if already supplied to {@link initializeAuth} or provided by {@link getAuth}. + * + * @public + */ +export declare function reauthenticateWithRedirect(user: User, provider: AuthProvider, resolver?: PopupRedirectResolver): Promise; + +declare interface Recaptcha { + render: (container: HTMLElement, parameters: RecaptchaParameters) => number; + getResponse: (id: number) => string; + execute: (id: number) => unknown; + reset: (id: number) => unknown; +} + +declare class RecaptchaConfig { + /** + * The reCAPTCHA site key. + */ + siteKey: string; + /** + * The list of providers and their enablement status for reCAPTCHA Enterprise. + */ + recaptchaEnforcementState: RecaptchaEnforcementProviderState[]; + constructor(response: GetRecaptchaConfigResponse); + /** + * Returns the reCAPTCHA Enterprise enforcement state for the given provider. + * + * @param providerStr - The provider whose enforcement state is to be returned. + * @returns The reCAPTCHA Enterprise enforcement state for the given provider. + */ + getProviderEnforcementState(providerStr: string): EnforcementState | null; + /** + * Returns true if the reCAPTCHA Enterprise enforcement state for the provider is set to ENFORCE or AUDIT. + * + * @param providerStr - The provider whose enablement state is to be returned. + * @returns Whether or not reCAPTCHA Enterprise protection is enabled for the given provider. + */ + isProviderEnabled(providerStr: string): boolean; + /** + * Returns true if reCAPTCHA Enterprise protection is enabled in at least one provider, otherwise + * returns false. + * + * @returns Whether or not reCAPTCHA Enterprise protection is enabled for at least one provider. + */ + isAnyProviderEnabled(): boolean; +} + +declare interface RecaptchaEnforcementProviderState { + provider: string; + enforcementState: string; +} + +/* Excluded from this release type: ReCaptchaLoader */ + +/** + * Interface representing reCAPTCHA parameters. + * + * See the {@link https://developers.google.com/recaptcha/docs/display#render_param | reCAPTCHA docs} + * for the list of accepted parameters. All parameters are accepted except for `sitekey`: Firebase Auth + * provisions a reCAPTCHA for each project and will configure the site key upon rendering. + * + * For an invisible reCAPTCHA, set the `size` key to `invisible`. + * + * @public + */ +export declare interface RecaptchaParameters { + [key: string]: any; +} + +/** + * An {@link https://www.google.com/recaptcha/ | reCAPTCHA}-based application verifier. + * + * @remarks + * `RecaptchaVerifier` does not work in a Node.js environment. + * + * @public + */ +export declare class RecaptchaVerifier implements ApplicationVerifierInternal { + private readonly parameters; + /** + * The application verifier type. + * + * @remarks + * For a reCAPTCHA verifier, this is 'recaptcha'. + */ + readonly type = "recaptcha"; + private destroyed; + private widgetId; + private readonly container; + private readonly isInvisible; + private readonly tokenChangeListeners; + private renderPromise; + private readonly auth; + /* Excluded from this release type: _recaptchaLoader */ + private recaptcha; + /** + * @param authExtern - The corresponding Firebase {@link Auth} instance. + * + * @param containerOrId - The reCAPTCHA container parameter. + * + * @remarks + * This has different meaning depending on whether the reCAPTCHA is hidden or visible. For a + * visible reCAPTCHA the container must be empty. If a string is used, it has to correspond to + * an element ID. The corresponding element must also must be in the DOM at the time of + * initialization. + * + * @param parameters - The optional reCAPTCHA parameters. + * + * @remarks + * Check the reCAPTCHA docs for a comprehensive list. All parameters are accepted except for + * the sitekey. Firebase Auth backend provisions a reCAPTCHA for each project and will + * configure this upon rendering. For an invisible reCAPTCHA, a size key must have the value + * 'invisible'. + */ + constructor(authExtern: Auth, containerOrId: HTMLElement | string, parameters?: RecaptchaParameters); + /** + * Waits for the user to solve the reCAPTCHA and resolves with the reCAPTCHA token. + * + * @returns A Promise for the reCAPTCHA token. + */ + verify(): Promise; + /** + * Renders the reCAPTCHA widget on the page. + * + * @returns A Promise that resolves with the reCAPTCHA widget ID. + */ + render(): Promise; + /* Excluded from this release type: _reset */ + /** + * Clears the reCAPTCHA widget from the page and destroys the instance. + */ + clear(): void; + private validateStartingState; + private makeTokenCallback; + private assertNotDestroyed; + private makeRenderPromise; + private init; + private getAssertedRecaptcha; +} + +/** + * Reloads user account data, if signed in. + * + * @param user - The user. + * + * @public + */ +export declare function reload(user: User): Promise; + +/** + * Revokes the given access token. Currently only supports Apple OAuth access tokens. + * + * @param auth - The {@link Auth} instance. + * @param token - The Apple OAuth access token. + * + * @public + */ +export declare function revokeAccessToken(auth: Auth, token: string): Promise; + +/** + * An {@link AuthProvider} for SAML. + * + * @public + */ +export declare class SAMLAuthProvider extends FederatedAuthProvider { + /** + * Constructor. The providerId must start with "saml." + * @param providerId - SAML provider ID. + */ + constructor(providerId: string); + /** + * Generates an {@link AuthCredential} from a {@link UserCredential} after a + * successful SAML flow completes. + * + * @remarks + * + * For example, to get an {@link AuthCredential}, you could write the + * following code: + * + * ```js + * const userCredential = await signInWithPopup(auth, samlProvider); + * const credential = SAMLAuthProvider.credentialFromResult(userCredential); + * ``` + * + * @param userCredential - The user credential. + */ + static credentialFromResult(userCredential: UserCredential): AuthCredential | null; + /** + * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was + * thrown during a sign-in, link, or reauthenticate operation. + * + * @param userCredential - The user credential. + */ + static credentialFromError(error: FirebaseError): AuthCredential | null; + /** + * Creates an {@link AuthCredential} from a JSON string or a plain object. + * @param json - A plain object or a JSON string + */ + static credentialFromJSON(json: string | object): AuthCredential; + private static samlCredentialFromTaggedObject; +} + +/** + * Sends a verification email to a user. + * + * @remarks + * The verification process is completed by calling {@link applyActionCode}. + * + * @example + * ```javascript + * const 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 + * }; + * await sendEmailVerification(user, actionCodeSettings); + * // Obtain code from the user. + * await applyActionCode(auth, code); + * ``` + * + * @param user - The user. + * @param actionCodeSettings - The {@link ActionCodeSettings}. + * + * @public + */ +export declare function sendEmailVerification(user: User, actionCodeSettings?: ActionCodeSettings | null): Promise; + +/** + * Sends a password reset email to the given email address. This method does not throw an error when + * there's no user account with the given email address and + * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection} + * is enabled. + * + * @remarks + * To complete the password reset, call {@link confirmPasswordReset} with the code supplied in + * the email sent to the user, along with the new password specified by the user. + * + * @example + * ```javascript + * const 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 + * }; + * await sendPasswordResetEmail(auth, 'user@example.com', actionCodeSettings); + * // Obtain code from user. + * await confirmPasswordReset('user@example.com', code); + * ``` + * + * @param auth - The {@link Auth} instance. + * @param email - The user's email address. + * @param actionCodeSettings - The {@link ActionCodeSettings}. + * + * @public + */ +export declare function sendPasswordResetEmail(auth: Auth, email: string, actionCodeSettings?: ActionCodeSettings): Promise; + +/** + * Sends a sign-in email link to the user with the specified email. + * + * @remarks + * The sign-in operation has to always be completed in the app unlike other out of band email + * actions (password reset and email verifications). This is because, at the end of the flow, + * the user is expected to be signed in and their Auth state persisted within the app. + * + * To complete sign in with the email link, call {@link signInWithEmailLink} with the email + * address and the email link supplied in the email sent to the user. + * + * @example + * ```javascript + * const 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 + * }; + * await sendSignInLinkToEmail(auth, 'user@example.com', actionCodeSettings); + * // Obtain emailLink from the user. + * if(isSignInWithEmailLink(auth, emailLink)) { + * await signInWithEmailLink(auth, 'user@example.com', emailLink); + * } + * ``` + * + * @param authInternal - The {@link Auth} instance. + * @param email - The user's email address. + * @param actionCodeSettings - The {@link ActionCodeSettings}. + * + * @public + */ +export declare function sendSignInLinkToEmail(auth: Auth, email: string, actionCodeSettings: ActionCodeSettings): Promise; + +/** + * Changes the type of persistence on the {@link Auth} instance for the currently saved + * `Auth` session and applies this type of persistence for future sign-in requests, including + * sign-in with redirect requests. + * + * @remarks + * This makes it easy for a user signing in to specify whether their session should be + * remembered or not. It also makes it easier to never persist the `Auth` state for applications + * that are shared by other users or have sensitive data. + * + * This method does not work in a Node.js environment or with {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * + * @example + * ```javascript + * setPersistence(auth, browserSessionPersistence); + * ``` + * + * @param auth - The {@link Auth} instance. + * @param persistence - The {@link Persistence} to use. + * @returns A `Promise` that resolves once the persistence change has completed + * + * @public + */ +export declare function setPersistence(auth: Auth, persistence: Persistence): Promise; + +/** + * Asynchronously signs in as an anonymous user. + * + * @remarks + * If there is already an anonymous user signed in, that user will be returned; otherwise, a + * new anonymous user identity will be created and returned. + * + * This method is not supported by {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * + * @param auth - The {@link Auth} instance. + * + * @public + */ +export declare function signInAnonymously(auth: Auth): Promise; + +/** + * Enumeration of supported sign-in methods. + * + * @public + */ +export declare const SignInMethod: { + /** Email link sign in method */ + readonly EMAIL_LINK: "emailLink"; + /** Email/password sign in method */ + readonly EMAIL_PASSWORD: "password"; + /** Facebook sign in method */ + readonly FACEBOOK: "facebook.com"; + /** GitHub sign in method */ + readonly GITHUB: "github.com"; + /** Google sign in method */ + readonly GOOGLE: "google.com"; + /** Phone sign in method */ + readonly PHONE: "phone"; + /** Twitter sign in method */ + readonly TWITTER: "twitter.com"; +}; + +/** + * Asynchronously signs in with the given credentials. + * + * @remarks + * An {@link AuthProvider} can be used to generate the credential. + * + * This method is not supported by {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * + * @param auth - The {@link Auth} instance. + * @param credential - The auth credential. + * + * @public + */ +export declare function signInWithCredential(auth: Auth, credential: AuthCredential): Promise; + +/** + * Asynchronously signs in using a custom token. + * + * @remarks + * Custom tokens are used to integrate Firebase Auth with existing auth systems, and must + * be generated by an auth backend using the + * {@link https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#createcustomtoken | createCustomToken} + * method in the {@link https://firebase.google.com/docs/auth/admin | Admin SDK} . + * + * Fails with an error if the token is invalid, expired, or not accepted by the Firebase Auth service. + * + * This method is not supported by {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * + * @param auth - The {@link Auth} instance. + * @param customToken - The custom token to sign in with. + * + * @public + */ +export declare function signInWithCustomToken(auth: Auth, customToken: string): Promise; + +/** + * Asynchronously signs in using an email and password. + * + * @remarks + * Fails with an error if the email address and password do not match. When + * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection} + * is enabled, this method fails with "auth/invalid-credential" in case of an invalid + * email/password. + * + * This method is not supported on {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * + * Note: The user's password is NOT the password used to access the user's email account. The + * email address serves as a unique identifier for the user, and the password is used to access + * the user's account in your Firebase project. See also: {@link createUserWithEmailAndPassword}. + * + * + * @param auth - The {@link Auth} instance. + * @param email - The users email address. + * @param password - The users password. + * + * @public + */ +export declare function signInWithEmailAndPassword(auth: Auth, email: string, password: string): Promise; + +/** + * Asynchronously signs in using an email and sign-in email link. + * + * @remarks + * If no link is passed, the link is inferred from the current URL. + * + * Fails with an error if the email address is invalid or OTP in email link expires. + * + * This method is not supported by {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * + * Note: Confirm the link is a sign-in email link before calling this method firebase.auth.Auth.isSignInWithEmailLink. + * + * @example + * ```javascript + * const 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 + * }; + * await sendSignInLinkToEmail(auth, 'user@example.com', actionCodeSettings); + * // Obtain emailLink from the user. + * if(isSignInWithEmailLink(auth, emailLink)) { + * await signInWithEmailLink(auth, 'user@example.com', emailLink); + * } + * ``` + * + * + * @param auth - The {@link Auth} instance. + * @param email - The user's email address. + * @param emailLink - The link sent to the user's email address. + * + * @public + */ +export declare function signInWithEmailLink(auth: Auth, email: string, emailLink?: string): Promise; + +/* Excluded from this release type: SignInWithIdpResponse */ + +/** + * Asynchronously signs in using a phone number. + * + * @remarks + * This method sends a code via SMS to the given + * phone number, and returns a {@link ConfirmationResult}. After the user + * provides the code sent to their phone, call {@link ConfirmationResult.confirm} + * with the code to sign the user in. + * + * For abuse prevention, this method requires a {@link ApplicationVerifier}. + * This SDK includes an implementation based on reCAPTCHA v2, {@link RecaptchaVerifier}. + * This function can work on other platforms that do not support the + * {@link RecaptchaVerifier} (like React Native), but you need to use a + * third-party {@link ApplicationVerifier} implementation. + * + * If you've enabled project-level reCAPTCHA Enterprise bot protection in + * Enforce mode, you can omit the {@link ApplicationVerifier}. + * + * This method does not work in a Node.js environment or with {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * + * @example + * ```javascript + * // 'recaptcha-container' is the ID of an element in the DOM. + * const applicationVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container'); + * const confirmationResult = await signInWithPhoneNumber(auth, phoneNumber, applicationVerifier); + * // Obtain a verificationCode from the user. + * const credential = await confirmationResult.confirm(verificationCode); + * ``` + * + * @param auth - The {@link Auth} instance. + * @param phoneNumber - The user's phone number in E.164 format (e.g. +16505550101). + * @param appVerifier - The {@link ApplicationVerifier}. + * + * @public + */ +export declare function signInWithPhoneNumber(auth: Auth, phoneNumber: string, appVerifier?: ApplicationVerifier): Promise; + +/* Excluded from this release type: SignInWithPhoneNumberRequest */ + +/* Excluded from this release type: SignInWithPhoneNumberResponse */ + +/** + * Authenticates a Firebase client using a popup-based OAuth authentication flow. + * + * @remarks + * If succeeds, returns the signed in user along with the provider's credential. If sign in was + * unsuccessful, returns an error object containing additional information about the error. + * + * This method does not work in a Node.js environment or with {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * + * @example + * ```javascript + * // Sign in using a popup. + * const provider = new FacebookAuthProvider(); + * const result = await signInWithPopup(auth, provider); + * + * // The signed-in user info. + * const user = result.user; + * // This gives you a Facebook Access Token. + * const credential = provider.credentialFromResult(auth, result); + * const token = credential.accessToken; + * ``` + * + * @param auth - The {@link Auth} instance. + * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}. + * Non-OAuth providers like {@link EmailAuthProvider} will throw an error. + * @param resolver - An instance of {@link PopupRedirectResolver}, optional + * if already supplied to {@link initializeAuth} or provided by {@link getAuth}. + * + * @public + */ +export declare function signInWithPopup(auth: Auth, provider: AuthProvider, resolver?: PopupRedirectResolver): Promise; + +/** + * Authenticates a Firebase client using a full-page redirect flow. + * + * @remarks + * To handle the results and errors for this operation, refer to {@link getRedirectResult}. + * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices + * | best practices} when using {@link signInWithRedirect}. + * + * This method does not work in a Node.js environment or with {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * + * @example + * ```javascript + * // Sign in using a redirect. + * const provider = new FacebookAuthProvider(); + * // You can add additional scopes to the provider: + * provider.addScope('user_birthday'); + * // Start a sign in process for an unauthenticated user. + * await signInWithRedirect(auth, provider); + * // This will trigger a full page redirect away from your app + * + * // After returning from the redirect when your app initializes you can obtain the result + * const result = await getRedirectResult(auth); + * if (result) { + * // This is the signed-in user + * const user = result.user; + * // This gives you a Facebook Access Token. + * const credential = provider.credentialFromResult(auth, result); + * const token = credential.accessToken; + * } + * // As this API can be used for sign-in, linking and reauthentication, + * // check the operationType to determine what triggered this redirect + * // operation. + * const operationType = result.operationType; + * ``` + * + * @param auth - The {@link Auth} instance. + * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}. + * Non-OAuth providers like {@link EmailAuthProvider} will throw an error. + * @param resolver - An instance of {@link PopupRedirectResolver}, optional + * if already supplied to {@link initializeAuth} or provided by {@link getAuth}. + * + * @public + */ +export declare function signInWithRedirect(auth: Auth, provider: AuthProvider, resolver?: PopupRedirectResolver): Promise; + +/** + * Signs out the current user. + * + * @remarks + * This method is not supported by {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * + * @param auth - The {@link Auth} instance. + * + * @public + */ +export declare function signOut(auth: Auth): Promise; + +declare interface StartTotpMfaEnrollmentResponse { + totpSessionInfo: { + sharedSecretKey: string; + verificationCodeLength: number; + hashingAlgorithm: string; + periodSec: number; + sessionInfo: string; + finalizeEnrollmentTime: number; + }; +} + +declare interface StorageEventListener { + (value: PersistenceValue | null): void; +} + +/* Excluded from this release type: StsTokenManager */ + +/* Excluded from this release type: TaggedWithTokenResponse */ + +/** + * An MFA provided by TOTP (Time-based One Time Password). + */ +declare interface TotpMfaEnrollment extends BaseMfaEnrollment { +} + +/** + * The class for asserting ownership of a TOTP second factor. Provided by + * {@link TotpMultiFactorGenerator.assertionForEnrollment} and + * {@link TotpMultiFactorGenerator.assertionForSignIn}. + * + * @public + */ +export declare interface TotpMultiFactorAssertion extends MultiFactorAssertion { +} + +/** + * Provider for generating a {@link TotpMultiFactorAssertion}. + * + * @public + */ +export declare class TotpMultiFactorGenerator { + /** + * Provides a {@link TotpMultiFactorAssertion} to confirm ownership of + * the TOTP (time-based one-time password) second factor. + * This assertion is used to complete enrollment in TOTP second factor. + * + * @param secret A {@link TotpSecret} containing the shared secret key and other TOTP parameters. + * @param oneTimePassword One-time password from TOTP App. + * @returns A {@link TotpMultiFactorAssertion} which can be used with + * {@link MultiFactorUser.enroll}. + */ + static assertionForEnrollment(secret: TotpSecret, oneTimePassword: string): TotpMultiFactorAssertion; + /** + * Provides a {@link TotpMultiFactorAssertion} to confirm ownership of the TOTP second factor. + * This assertion is used to complete signIn with TOTP as the second factor. + * + * @param enrollmentId identifies the enrolled TOTP second factor. + * @param oneTimePassword One-time password from TOTP App. + * @returns A {@link TotpMultiFactorAssertion} which can be used with + * {@link MultiFactorResolver.resolveSignIn}. + */ + static assertionForSignIn(enrollmentId: string, oneTimePassword: string): TotpMultiFactorAssertion; + /** + * Returns a promise to {@link TotpSecret} which contains the TOTP shared secret key and other parameters. + * Creates a TOTP secret as part of enrolling a TOTP second factor. + * Used for generating a QR code URL or inputting into a TOTP app. + * This method uses the auth instance corresponding to the user in the multiFactorSession. + * + * @param session The {@link MultiFactorSession} that the user is part of. + * @returns A promise to {@link TotpSecret}. + */ + static generateSecret(session: MultiFactorSession): Promise; + /** + * The identifier of the TOTP second factor: `totp`. + */ + static FACTOR_ID: 'totp'; +} + +/** + * The subclass of the {@link MultiFactorInfo} interface for TOTP + * second factors. The `factorId` of this second factor is {@link FactorId}.TOTP. + * @public + */ +export declare interface TotpMultiFactorInfo extends MultiFactorInfo { +} + +/** + * Provider for generating a {@link TotpMultiFactorAssertion}. + * + * Stores the shared secret key and other parameters to generate time-based OTPs. + * Implements methods to retrieve the shared secret key and generate a QR code URL. + * @public + */ +export declare class TotpSecret { + private readonly sessionInfo; + private readonly auth; + /** + * Shared secret key/seed used for enrolling in TOTP MFA and generating OTPs. + */ + readonly secretKey: string; + /** + * Hashing algorithm used. + */ + readonly hashingAlgorithm: string; + /** + * Length of the one-time passwords to be generated. + */ + readonly codeLength: number; + /** + * The interval (in seconds) when the OTP codes should change. + */ + readonly codeIntervalSeconds: number; + /** + * The timestamp (UTC string) by which TOTP enrollment should be completed. + */ + readonly enrollmentCompletionDeadline: string; + private constructor(); + /* Excluded from this release type: _fromStartTotpMfaEnrollmentResponse */ + /* Excluded from this release type: _makeTotpVerificationInfo */ + /** + * Returns a QR code URL as described in + * https://github.com/google/google-authenticator/wiki/Key-Uri-Format + * This can be displayed to the user as a QR code to be scanned into a TOTP app like Google Authenticator. + * If the optional parameters are unspecified, an accountName of and issuer of are used. + * + * @param accountName the name of the account/app along with a user identifier. + * @param issuer issuer of the TOTP (likely the app name). + * @returns A QR code URL string. + */ + generateQrCodeUrl(accountName?: string, issuer?: string): string; +} + +declare interface TotpVerificationInfo { + sessionInfo: string; + verificationCode: string; +} + +/** + * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.TWITTER. + * + * @example + * ```javascript + * // Sign in using a redirect. + * const provider = new TwitterAuthProvider(); + * // Start a sign in process for an unauthenticated user. + * await signInWithRedirect(auth, provider); + * // This will trigger a full page redirect away from your app + * + * // After returning from the redirect when your app initializes you can obtain the result + * const result = await getRedirectResult(auth); + * if (result) { + * // This is the signed-in user + * const user = result.user; + * // This gives you a Twitter Access Token and Secret. + * const credential = TwitterAuthProvider.credentialFromResult(result); + * const token = credential.accessToken; + * const secret = credential.secret; + * } + * ``` + * + * @example + * ```javascript + * // Sign in using a popup. + * const provider = new TwitterAuthProvider(); + * const result = await signInWithPopup(auth, provider); + * + * // The signed-in user info. + * const user = result.user; + * // This gives you a Twitter Access Token and Secret. + * const credential = TwitterAuthProvider.credentialFromResult(result); + * const token = credential.accessToken; + * const secret = credential.secret; + * ``` + * + * @public + */ +export declare class TwitterAuthProvider extends BaseOAuthProvider { + /** Always set to {@link SignInMethod}.TWITTER. */ + static readonly TWITTER_SIGN_IN_METHOD: 'twitter.com'; + /** Always set to {@link ProviderId}.TWITTER. */ + static readonly PROVIDER_ID: 'twitter.com'; + constructor(); + /** + * Creates a credential for Twitter. + * + * @param token - Twitter access token. + * @param secret - Twitter secret. + */ + static credential(token: string, secret: string): OAuthCredential; + /** + * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}. + * + * @param userCredential - The user credential. + */ + static credentialFromResult(userCredential: UserCredential): OAuthCredential | null; + /** + * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was + * thrown during a sign-in, link, or reauthenticate operation. + * + * @param userCredential - The user credential. + */ + static credentialFromError(error: FirebaseError): OAuthCredential | null; + private static credentialFromTaggedObject; +} + +/** + * Unlinks a provider from a user account. + * + * @param user - The user. + * @param providerId - The provider to unlink. + * + * @public + */ +export declare function unlink(user: User, providerId: string): Promise; +export { Unsubscribe } + +/** + * Asynchronously sets the provided user as {@link Auth.currentUser} on the + * {@link Auth} instance. + * + * @remarks + * A new instance copy of the user provided will be made and set as currentUser. + * + * This will trigger {@link onAuthStateChanged} and {@link onIdTokenChanged} listeners + * like other sign in methods. + * + * The operation fails with an error if the user to be updated belongs to a different Firebase + * project. + * + * This method is not supported by {@link Auth} instances created with a + * {@link @firebase/app#FirebaseServerApp}. + * + * @param auth - The {@link Auth} instance. + * @param user - The new {@link User}. + * + * @public + */ +export declare function updateCurrentUser(auth: Auth, user: User | null): Promise; + +/** + * Updates the user's email address. + * + * @remarks + * An email will be sent to the original email address (if it was set) that allows to revoke the + * email address change, in order to protect them from account hijacking. + * + * This method is not supported on any {@link User} signed in by {@link Auth} instances + * created with a {@link @firebase/app#FirebaseServerApp}. + * + * Important: this is a security sensitive operation that requires the user to have recently signed + * in. If this requirement isn't met, ask the user to authenticate again and then call + * {@link reauthenticateWithCredential}. + * + * @param user - The user. + * @param newEmail - The new email address. + * + * Throws "auth/operation-not-allowed" error when + * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection} + * is enabled. + * Deprecated - Use {@link verifyBeforeUpdateEmail} instead. + * + * @public + */ +export declare function updateEmail(user: User, newEmail: string): Promise; + +/** + * Updates the user's password. + * + * @remarks + * Important: this is a security sensitive operation that requires the user to have recently signed + * in. If this requirement isn't met, ask the user to authenticate again and then call + * {@link reauthenticateWithCredential}. + * + * @param user - The user. + * @param newPassword - The new password. + * + * @public + */ +export declare function updatePassword(user: User, newPassword: string): Promise; + +/** + * Updates the user's phone number. + * + * @remarks + * This method does not work in a Node.js environment or on any {@link User} signed in by + * {@link Auth} instances created with a {@link @firebase/app#FirebaseServerApp}. + * + * @example + * ``` + * // 'recaptcha-container' is the ID of an element in the DOM. + * const applicationVerifier = new RecaptchaVerifier('recaptcha-container'); + * const provider = new PhoneAuthProvider(auth); + * const verificationId = await provider.verifyPhoneNumber('+16505550101', applicationVerifier); + * // Obtain the verificationCode from the user. + * const phoneCredential = PhoneAuthProvider.credential(verificationId, verificationCode); + * await updatePhoneNumber(user, phoneCredential); + * ``` + * + * @param user - The user. + * @param credential - A credential authenticating the new phone number. + * + * @public + */ +export declare function updatePhoneNumber(user: User, credential: PhoneAuthCredential): Promise; + +/** + * Updates a user's profile data. + * + * @param user - The user. + * @param profile - The profile's `displayName` and `photoURL` to update. + * + * @public + */ +export declare function updateProfile(user: User, { displayName, photoURL: photoUrl }: { + displayName?: string | null; + photoURL?: string | null; +}): Promise; + +/** + * Sets the current language to the default device/browser preference. + * + * @param auth - The {@link Auth} instance. + * + * @public + */ +export declare function useDeviceLanguage(auth: Auth): void; + +/** + * A user account. + * + * @public + */ +export declare interface User extends UserInfo { + /** + * Whether the email has been verified with {@link sendEmailVerification} and + * {@link applyActionCode}. + */ + readonly emailVerified: boolean; + /** + * Whether the user is authenticated using the {@link ProviderId}.ANONYMOUS provider. + */ + readonly isAnonymous: boolean; + /** + * Additional metadata around user creation and sign-in times. + */ + readonly metadata: UserMetadata; + /** + * Additional per provider such as displayName and profile information. + */ + readonly providerData: UserInfo[]; + /** + * Refresh token used to reauthenticate the user. Avoid using this directly and prefer + * {@link User.getIdToken} to refresh the ID token instead. + */ + readonly refreshToken: string; + /** + * The user's tenant ID. + * + * @remarks + * This is a read-only property, which indicates the tenant ID + * used to sign in the user. This is null if the user is signed in from the parent + * project. + * + * @example + * ```javascript + * // Set the tenant ID on Auth instance. + * auth.tenantId = 'TENANT_PROJECT_ID'; + * + * // All future sign-in request now include tenant ID. + * const result = await signInWithEmailAndPassword(auth, email, password); + * // result.user.tenantId should be 'TENANT_PROJECT_ID'. + * ``` + */ + readonly tenantId: string | null; + /** + * Deletes and signs out the user. + * + * @remarks + * Important: this is a security-sensitive operation that requires the user to have recently + * signed in. If this requirement isn't met, ask the user to authenticate again and then call + * one of the reauthentication methods like {@link reauthenticateWithCredential}. + * + * This method is not supported on any {@link User} signed in by {@link Auth} instances + * created with a {@link @firebase/app#FirebaseServerApp}. + */ + delete(): Promise; + /** + * Returns a JSON Web Token (JWT) used to identify the user to a Firebase service. + * + * @remarks + * Returns the current token if it has not expired or if it will not expire in the next five + * minutes. Otherwise, this will refresh the token and return a new one. + * + * @param forceRefresh - Force refresh regardless of token expiration. + */ + getIdToken(forceRefresh?: boolean): Promise; + /** + * Returns a deserialized JSON Web Token (JWT) used to identify the user to a Firebase service. + * + * @remarks + * Returns the current token if it has not expired or if it will not expire in the next five + * minutes. Otherwise, this will refresh the token and return a new one. + * + * @param forceRefresh - Force refresh regardless of token expiration. + */ + getIdTokenResult(forceRefresh?: boolean): Promise; + /** + * Refreshes the user, if signed in. + */ + reload(): Promise; + /** + * Returns a JSON-serializable representation of this object. + * + * @returns A JSON-serializable representation of this object. + */ + toJSON(): object; +} + +/** + * A structure containing a {@link User}, the {@link OperationType}, and the provider ID. + * + * @remarks + * `operationType` could be {@link OperationType}.SIGN_IN for a sign-in operation, + * {@link OperationType}.LINK for a linking operation and {@link OperationType}.REAUTHENTICATE for + * a reauthentication operation. + * + * @public + */ +export declare interface UserCredential { + /** + * The user authenticated by this credential. + */ + user: User; + /** + * The provider which was used to authenticate the user. + */ + providerId: string | null; + /** + * The type of operation which was used to authenticate the user (such as sign-in or link). + */ + operationType: (typeof OperationType)[keyof typeof OperationType]; +} + +/* Excluded from this release type: UserCredentialInternal */ + +/** + * User profile information, visible only to the Firebase project's apps. + * + * @public + */ +export declare interface UserInfo { + /** + * The display name of the user. + */ + readonly displayName: string | null; + /** + * The email of the user. + */ + readonly email: string | null; + /** + * The phone number normalized based on the E.164 standard (e.g. +16505550101) for the + * user. + * + * @remarks + * This is null if the user has no phone credential linked to the account. + */ + readonly phoneNumber: string | null; + /** + * The profile photo URL of the user. + */ + readonly photoURL: string | null; + /** + * The provider used to authenticate the user. + */ + readonly providerId: string; + /** + * The user's unique ID, scoped to the project. + */ + readonly uid: string; +} + +/* Excluded from this release type: UserInternal */ + +/** + * Interface representing a user's metadata. + * + * @public + */ +export declare interface UserMetadata { + /** Time the user was created. */ + readonly creationTime?: string; + /** Time the user last signed in. */ + readonly lastSignInTime?: string; +} + +declare class UserMetadata_2 implements UserMetadata { + private createdAt?; + private lastLoginAt?; + creationTime?: string; + lastSignInTime?: string; + constructor(createdAt?: (string | number) | undefined, lastLoginAt?: (string | number) | undefined); + private _initializeTime; + _copy(metadata: UserMetadata_2): void; + toJSON(): object; +} + +/** + * User profile used in {@link AdditionalUserInfo}. + * + * @public + */ +export declare type UserProfile = Record; + +/** + * Validates the password against the password policy configured for the project or tenant. + * + * @remarks + * If no tenant ID is set on the `Auth` instance, then this method will use the password + * policy configured for the project. Otherwise, this method will use the policy configured + * for the tenant. If a password policy has not been configured, then the default policy + * configured for all projects will be used. + * + * If an auth flow fails because a submitted password does not meet the password policy + * requirements and this method has previously been called, then this method will use the + * most recent policy available when called again. + * + * @example + * ```javascript + * validatePassword(auth, 'some-password'); + * ``` + * + * @param auth The {@link Auth} instance. + * @param password The password to validate. + * + * @public + */ +export declare function validatePassword(auth: Auth, password: string): Promise; + +/** + * Sends a verification email to a new email address. + * + * @remarks + * The user's email will be updated to the new one after being verified. + * + * If you have a custom email action handler, you can complete the verification process by calling + * {@link applyActionCode}. + * + * @example + * ```javascript + * const 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 + * }; + * await verifyBeforeUpdateEmail(user, 'newemail@example.com', actionCodeSettings); + * // Obtain code from the user. + * await applyActionCode(auth, code); + * ``` + * + * @param user - The user. + * @param newEmail - The new email address to be verified before update. + * @param actionCodeSettings - The {@link ActionCodeSettings}. + * + * @public + */ +export declare function verifyBeforeUpdateEmail(user: User, newEmail: string, actionCodeSettings?: ActionCodeSettings | null): Promise; + +/** + * Checks a password reset code sent to the user by email or other out-of-band mechanism. + * + * @returns the user's email address if valid. + * + * @param auth - The {@link Auth} instance. + * @param code - A verification code sent to the user. + * + * @public + */ +export declare function verifyPasswordResetCode(auth: Auth, code: string): Promise; + +export { } From 314545a44f1cb98245854a98c0ca501e33bd234a Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Tue, 21 Apr 2026 13:29:02 +0100 Subject: [PATCH 06/45] test(auth): add type coverage and compare-types wiring --- .../compare-types/packages/auth/config.ts | 499 ++++++++++++++++++ .github/scripts/compare-types/src/registry.ts | 79 +-- packages/auth/type-test.ts | 492 ++++++++--------- tsconfig.json | 4 +- 4 files changed, 765 insertions(+), 309 deletions(-) create mode 100644 .github/scripts/compare-types/packages/auth/config.ts diff --git a/.github/scripts/compare-types/packages/auth/config.ts b/.github/scripts/compare-types/packages/auth/config.ts new file mode 100644 index 0000000000..e5f5f91bdb --- /dev/null +++ b/.github/scripts/compare-types/packages/auth/config.ts @@ -0,0 +1,499 @@ +/** + * Known differences between the firebase-js-sdk @firebase/auth public + * API and the @react-native-firebase/auth modular API. + * + * Each entry must have a `name` (the export name) and a `reason` explaining + * why the difference exists. Any difference NOT listed here will cause CI to + * fail so that new drift is caught and deliberately acknowledged. + */ + +import type { PackageConfig } from '../../src/types'; + +const config: PackageConfig = { + nameMapping: {}, + + missingInRN: [ + { + name: 'initializeRecaptchaConfig', + reason: + 'Web-only reCAPTCHA bootstrap helper from the firebase-js-sdk. RN Firebase does not expose browser reCAPTCHA initialization because native SDKs own the phone-auth verification flow.', + }, + { + name: 'ActionCodeOperation', + reason: + 'Not yet exported as a standalone modular enum map. RN Firebase currently exposes action-code operations through older auth result shapes instead of the firebase-js-sdk public enum export.', + }, + { + name: 'AuthError', + reason: + 'RN Firebase surfaces auth failures as `NativeFirebaseAuthError` / native bridge errors rather than exporting the firebase-js-sdk `AuthError` interface directly.', + }, + { + name: 'AuthErrorCodes', + reason: + 'Not yet exported as the firebase-js-sdk `AuthErrorCodes` constant map. RN Firebase still relies on native error code strings.', + }, + { + name: 'browserCookiePersistence', + reason: + 'Browser-only persistence implementation from the firebase-js-sdk. Not applicable to React Native native-auth persistence.', + }, + { + name: 'browserLocalPersistence', + reason: + 'Browser-only localStorage persistence implementation from the firebase-js-sdk. Not applicable to React Native native-auth persistence.', + }, + { + name: 'browserPopupRedirectResolver', + reason: + 'Browser-only popup/redirect resolver from the firebase-js-sdk. Native provider flows do not use the browser popup resolver stack.', + }, + { + name: 'browserSessionPersistence', + reason: + 'Browser-only sessionStorage persistence implementation from the firebase-js-sdk. Not applicable to React Native native-auth persistence.', + }, + { + name: 'CompleteFn', + reason: + 'Not yet surfaced as a first-class auth export in the compare-types modular surface. Listener completion callbacks are typed through RN Firebase helper types instead.', + }, + { + name: 'CustomParameters', + reason: + 'Not yet exported as the firebase-js-sdk standalone custom-parameters interface. Provider parameter bags are still modeled through the legacy RNFB auth provider types.', + }, + { + name: 'debugErrorMap', + reason: + 'firebase-js-sdk web error-map helper. RN Firebase does not expose the SDK error-map selection API.', + }, + { + name: 'EmailAuthCredential', + reason: + 'Not yet exported as a standalone modular credential type. Email credentials are created and consumed through `EmailAuthProvider` and legacy auth credential shapes.', + }, + { + name: 'EmulatorConfig', + reason: + 'Not yet exported as the firebase-js-sdk `EmulatorConfig` interface. RN Firebase connects to the emulator but does not currently surface the web SDK emulator config object.', + }, + { + name: 'ErrorFn', + reason: + 'Not yet surfaced as a first-class auth export in the compare-types modular surface. Listener error callbacks are typed through RN Firebase helper types instead.', + }, + { + name: 'FacebookAuthProvider', + reason: + 'Not yet surfaced as a direct modular/public auth export in the split TS surface. It remains available through the legacy namespaced export path.', + }, + { + name: 'GithubAuthProvider', + reason: + 'Not yet surfaced as a direct modular/public auth export in the split TS surface. It remains available through the legacy namespaced export path.', + }, + { + name: 'GoogleAuthProvider', + reason: + 'Not yet surfaced as a direct modular/public auth export in the split TS surface. It remains available through the legacy namespaced export path.', + }, + { + name: 'indexedDBLocalPersistence', + reason: + 'IndexedDB persistence is web-only and not applicable to React Native native-auth persistence.', + }, + { + name: 'inMemoryPersistence', + reason: + 'The firebase-js-sdk persistence object is not currently exported from RN Firebase. Native SDK state is managed by the underlying platform auth implementation.', + }, + { + name: 'NextFn', + reason: + 'Not yet surfaced as a first-class auth export in the compare-types modular surface. Listener callback types are still routed through RN Firebase helper exports.', + }, + { + name: 'NextOrObserver', + reason: + 'Not yet exported as the firebase-js-sdk standalone listener helper alias. RN Firebase currently uses its own package-local observer helper in the modular wrapper.', + }, + { + name: 'OAuthCredential', + reason: + 'Not yet exported as a standalone modular credential type. OAuth credentials are still represented through the legacy RNFB auth credential surface.', + }, + { + name: 'OAuthCredentialOptions', + reason: + 'Not yet exported as the firebase-js-sdk standalone OAuth credential options interface.', + }, + { + name: 'OperationType', + reason: + 'Not yet exported as the firebase-js-sdk operation-type enum map. RN Firebase still models operation types through the legacy namespaced auth surface.', + }, + { + name: 'ParsedToken', + reason: + 'Not yet exported as the firebase-js-sdk standalone parsed-token interface. RN Firebase exposes token claims through `IdTokenResult` only.', + }, + { + name: 'PhoneAuthCredential', + reason: + 'Not yet exported as a standalone modular credential type. Phone credentials are created through `PhoneAuthProvider.credential()` and consumed through the legacy auth credential surface.', + }, + { + name: 'PhoneAuthProvider', + reason: + 'Not yet surfaced as a direct modular/public auth export in the split TS surface. It remains available through the legacy namespaced export path.', + }, + { + name: 'PhoneInfoOptions', + reason: + 'Not yet exported as the firebase-js-sdk standalone phone-info options interface. RN Firebase still uses older package-specific MFA phone option types.', + }, + { + name: 'PhoneMultiFactorAssertion', + reason: + 'Not yet exported as the firebase-js-sdk standalone phone multi-factor assertion type.', + }, + { + name: 'PhoneSingleFactorInfoOptions', + reason: + 'Not yet exported as the firebase-js-sdk standalone phone single-factor info options interface.', + }, + { + name: 'prodErrorMap', + reason: + 'firebase-js-sdk web error-map helper. RN Firebase does not expose the SDK error-map selection API.', + }, + { + name: 'ProviderId', + reason: + 'Not yet exported as the firebase-js-sdk provider-id enum map. RN Firebase still relies on provider ID strings and legacy provider classes.', + }, + { + name: 'ReactNativeAsyncStorage', + reason: + 'The firebase-js-sdk React Native persistence helper type is not exported by RN Firebase because persistence is delegated to the native iOS/Android SDKs rather than configured through `initializeAuth()`.', + }, + { + name: 'RecaptchaParameters', + reason: 'Browser reCAPTCHA configuration is not part of the RN Firebase native auth surface.', + }, + { + name: 'RecaptchaVerifier', + reason: + 'Browser reCAPTCHA verifier implementation is not available in RN Firebase because native SDKs own application verification.', + }, + { + name: 'SAMLAuthProvider', + reason: + 'SAMLAuthProvider is not yet surfaced on the RN Firebase modular/public auth surface.', + }, + { + name: 'SignInMethod', + reason: + 'Not yet exported as the firebase-js-sdk sign-in-method enum map. RN Firebase still uses provider ID strings and legacy provider helpers.', + }, + { + name: 'TotpMultiFactorAssertion', + reason: + 'Not yet exported as the firebase-js-sdk standalone TOTP multi-factor assertion type.', + }, + { + name: 'TwitterAuthProvider', + reason: + 'Not yet surfaced as a direct modular/public auth export in the split TS surface. It remains available through the legacy namespaced export path.', + }, + { + name: 'Unsubscribe', + reason: + 'Not yet surfaced as a first-class auth export in the compare-types modular surface. Unsubscribe functions are currently emitted through package-local callback typing.', + }, + { + name: 'UserProfile', + reason: + 'Not yet exported as the firebase-js-sdk standalone `UserProfile` alias. RN Firebase still models profile payloads through `UpdateProfile` and the legacy user surface.', + }, + ], + + extraInRN: [ + { + name: 'FirebaseApp', + reason: + 'RN Firebase-specific re-export of `ReactNativeFirebase.FirebaseApp` from `@react-native-firebase/app`. Not part of the firebase-js-sdk auth public API.', + }, + { + name: 'NativeFirebaseAuthError', + reason: + 'RN Firebase-specific native bridge auth error type used in place of the firebase-js-sdk `AuthError` export.', + }, + { + name: 'OIDCProvider', + reason: + 'RN Firebase-specific OIDC provider class export retained for compatibility with the existing package surface.', + }, + { + name: 'PhoneAuthState', + reason: 'RN Firebase-specific enum-like object describing native phone-auth listener states.', + }, + { + name: 'MultiFactorInfoCommon', + reason: 'RN Firebase-specific compatibility type used by the legacy namespaced MFA surface.', + }, + { + name: 'MultiFactor', + reason: + 'RN Firebase-specific extra public type retained from the existing namespaced-compatible auth surface.', + }, + { + name: 'UpdateProfile', + reason: + 'RN Firebase-specific named type export for the user profile update payload. The firebase-js-sdk inlines this object shape instead of exporting it separately.', + }, + { + name: 'ActionCodeSettingsAndroid', + reason: + 'RN Firebase-specific split helper type for the Android portion of `ActionCodeSettings`.', + }, + { + name: 'ActionCodeInfoData', + reason: 'RN Firebase-specific split helper type for the `ActionCodeInfo.data` payload.', + }, + { + name: 'ActionCodeSettingsIos', + reason: 'RN Firebase-specific split helper type for the iOS portion of `ActionCodeSettings`.', + }, + { + name: 'AuthListenerCallback', + reason: + 'RN Firebase-specific named callback alias retained from the existing auth package surface.', + }, + { + name: 'PhoneAuthSnapshot', + reason: + 'RN Firebase-specific phone verification snapshot type used by native phone-auth listeners.', + }, + { + name: 'PhoneAuthError', + reason: + 'RN Firebase-specific phone verification error snapshot type used by native phone-auth listeners.', + }, + { + name: 'PhoneAuthListener', + reason: 'RN Firebase-specific listener object returned by `verifyPhoneNumber()`.', + }, + { + name: 'verifyPhoneNumber', + reason: + 'RN Firebase-specific helper exposing the native phone verification listener flow; the firebase-js-sdk does not export this helper.', + }, + { + name: 'setLanguageCode', + reason: + 'RN Firebase-specific modular helper function mirroring the existing native package surface; the firebase-js-sdk uses the writable `auth.languageCode` property instead.', + }, + { + name: 'useUserAccessGroup', + reason: + 'RN Firebase-specific iOS keychain sharing helper with no firebase-js-sdk equivalent.', + }, + { + name: 'getCustomAuthDomain', + reason: + 'RN Firebase-specific helper that exposes the configured native auth domain; no firebase-js-sdk equivalent exists.', + }, + ], + + differentShape: [ + { + name: 'beforeAuthStateChanged', + reason: + 'RN Firebase exposes the helper as unsupported and returns a plain unsubscribe function type `() => void` rather than the firebase-js-sdk `Unsubscribe` alias.', + }, + { + name: 'connectAuthEmulator', + reason: + 'The optional `disableWarnings` property is modeled as optional in RN Firebase, while the firebase-js-sdk public type text shows a required boolean property.', + }, + { + name: 'getMultiFactorResolver', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.getMultiFactorResolver` alias instead of a firebase-js-sdk-aligned direct modular function type.', + }, + { + name: 'isSignInWithEmailLink', + reason: + 'RN Firebase resolves this check asynchronously through the native bridge and returns `Promise`, whereas the firebase-js-sdk returns a synchronous `boolean`.', + }, + { + name: 'linkWithRedirect', + reason: + 'Native provider flows resolve immediately with a `UserCredential` instead of following the browser redirect contract used by the firebase-js-sdk.', + }, + { + name: 'multiFactor', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.multiFactor` alias instead of a firebase-js-sdk-aligned direct modular function type.', + }, + { + name: 'onAuthStateChanged', + reason: + 'RN Firebase uses its package-local observer helper type and returns a plain `() => void` unsubscribe function instead of the firebase-js-sdk `Unsubscribe` alias text.', + }, + { + name: 'onIdTokenChanged', + reason: + 'RN Firebase uses its package-local observer helper type and returns a plain `() => void` unsubscribe function instead of the firebase-js-sdk `Unsubscribe` alias text.', + }, + { + name: 'reauthenticateWithRedirect', + reason: + 'Native provider flows do not follow the browser redirect contract. RN Firebase models this as `Promise` rather than the firebase-js-sdk `Promise` redirect signature.', + }, + { + name: 'sendEmailVerification', + reason: + 'RN Firebase models the optional action code settings as `ActionCodeSettings | undefined`, while the firebase-js-sdk public type uses `ActionCodeSettings | null`.', + }, + { + name: 'signInWithRedirect', + reason: + 'Native provider flows resolve immediately with a `UserCredential` instead of following the browser redirect contract used by the firebase-js-sdk.', + }, + { + name: 'updatePhoneNumber', + reason: + 'RN Firebase accepts the broader `AuthCredential` surface, while the firebase-js-sdk narrows this parameter to `PhoneAuthCredential`.', + }, + { + name: 'updateProfile', + reason: + 'RN Firebase exports and reuses the named `UpdateProfile` type alias rather than the firebase-js-sdk inline object type text.', + }, + { + name: 'verifyBeforeUpdateEmail', + reason: + 'RN Firebase models the optional action code settings as `ActionCodeSettings | undefined`, while the firebase-js-sdk public type uses `ActionCodeSettings | null`.', + }, + { + name: 'ActionCodeInfo', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.ActionCodeInfo` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'ActionCodeSettings', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.ActionCodeSettings` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'AdditionalUserInfo', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.AdditionalUserInfo` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'Auth', + reason: + 'The modular `Auth` type still aliases `FirebaseAuthTypes.Module`, so compare-types sees the older namespaced-compatible auth surface rather than a firebase-js-sdk-aligned modular interface.', + }, + { + name: 'AuthProvider', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.AuthProvider` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'ConfirmationResult', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.ConfirmationResult` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'FactorId', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.FactorId` alias instead of a firebase-js-sdk-aligned direct enum-map declaration.', + }, + { + name: 'IdTokenResult', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.IdTokenResult` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'MultiFactorAssertion', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.MultiFactorAssertion` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'MultiFactorError', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.MultiFactorError` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'MultiFactorInfo', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.MultiFactorInfo` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'MultiFactorResolver', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.MultiFactorResolver` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'MultiFactorSession', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.MultiFactorSession` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'MultiFactorUser', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.MultiFactorUser` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'Persistence', + reason: + 'RN Firebase exports `Persistence` as a readonly object type alias, while the firebase-js-sdk declares it as an interface.', + }, + { + name: 'PhoneMultiFactorEnrollInfoOptions', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.PhoneMultiFactorEnrollInfoOptions` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'PhoneMultiFactorInfo', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.PhoneMultiFactorInfo` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'PhoneMultiFactorSignInInfoOptions', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.PhoneMultiFactorSignInInfoOptions` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'TotpMultiFactorInfo', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.TotpMultiFactorInfo` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'User', + reason: + 'The modular `User` type still aliases the legacy `FirebaseAuthTypes.User` surface, so compare-types sees the older namespaced-compatible user shape.', + }, + { + name: 'UserCredential', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.UserCredential` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'UserInfo', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.UserInfo` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + { + name: 'UserMetadata', + reason: + 'Still re-exported through the legacy `FirebaseAuthTypes.UserMetadata` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + }, + ], +}; + +export default config; diff --git a/.github/scripts/compare-types/src/registry.ts b/.github/scripts/compare-types/src/registry.ts index 3d31390a07..f1e92fd777 100644 --- a/.github/scripts/compare-types/src/registry.ts +++ b/.github/scripts/compare-types/src/registry.ts @@ -15,6 +15,7 @@ import type { PackageConfig } from './types'; import storageConfig from '../packages/storage/config'; import aiConfig from '../packages/ai/config'; +import authConfig from '../packages/auth/config'; import firestoreConfig from '../packages/firestore/config'; import firestorePipelinesConfig from '../packages/firestore-pipelines/config'; @@ -45,17 +46,44 @@ export interface PackageEntry { } function rnDist(packageName: string): string { - return path.join( - REPO_ROOT, - 'packages', - packageName, - 'dist', - 'typescript', - 'lib', - ); + return path.join(REPO_ROOT, 'packages', packageName, 'dist', 'typescript', 'lib'); } export const packages: PackageEntry[] = [ + { + name: 'auth', + firebaseSdkTypesPaths: [path.join(SCRIPT_DIR, 'packages', 'auth', 'auth-js-sdk.d.ts')], + rnFirebaseModularFiles: [ + path.join(rnDist('auth'), 'types', 'auth.d.ts'), + path.join(rnDist('auth'), 'modular.d.ts'), + ], + rnFirebaseSupportFiles: [ + path.join(rnDist('auth'), 'index.d.ts'), + path.join(rnDist('auth'), 'namespaced.d.ts'), + path.join(rnDist('auth'), 'types', 'namespaced.d.ts'), + path.join(rnDist('auth'), 'types', 'internal.d.ts'), + path.join(rnDist('auth'), 'ConfirmationResult.d.ts'), + path.join(rnDist('auth'), 'MultiFactorResolver.d.ts'), + path.join(rnDist('auth'), 'PhoneAuthListener.d.ts'), + path.join(rnDist('auth'), 'PhoneMultiFactorGenerator.d.ts'), + path.join(rnDist('auth'), 'Settings.d.ts'), + path.join(rnDist('auth'), 'TotpMultiFactorGenerator.d.ts'), + path.join(rnDist('auth'), 'TotpSecret.d.ts'), + path.join(rnDist('auth'), 'User.d.ts'), + path.join(rnDist('auth'), 'getMultiFactorResolver.d.ts'), + path.join(rnDist('auth'), 'multiFactor.d.ts'), + path.join(rnDist('auth'), 'providers', 'AppleAuthProvider.d.ts'), + path.join(rnDist('auth'), 'providers', 'EmailAuthProvider.d.ts'), + path.join(rnDist('auth'), 'providers', 'FacebookAuthProvider.d.ts'), + path.join(rnDist('auth'), 'providers', 'GithubAuthProvider.d.ts'), + path.join(rnDist('auth'), 'providers', 'GoogleAuthProvider.d.ts'), + path.join(rnDist('auth'), 'providers', 'OAuthProvider.d.ts'), + path.join(rnDist('auth'), 'providers', 'OIDCAuthProvider.d.ts'), + path.join(rnDist('auth'), 'providers', 'PhoneAuthProvider.d.ts'), + path.join(rnDist('auth'), 'providers', 'TwitterAuthProvider.d.ts'), + ], + config: authConfig, + }, // { // name: 'remote-config', // firebaseSdkTypesPaths: [ @@ -74,12 +102,7 @@ export const packages: PackageEntry[] = [ // }, { name: 'storage', - firebaseSdkTypesPaths: [path.join( - SCRIPT_DIR, - 'packages', - 'storage', - 'storage-js-sdk.d.ts', - )], + firebaseSdkTypesPaths: [path.join(SCRIPT_DIR, 'packages', 'storage', 'storage-js-sdk.d.ts')], rnFirebaseModularFiles: [ path.join(rnDist('storage'), 'types', 'storage.d.ts'), path.join(rnDist('storage'), 'modular.d.ts'), @@ -93,12 +116,8 @@ export const packages: PackageEntry[] = [ }, { name: 'ai', - firebaseSdkTypesPaths: [ - path.join(SCRIPT_DIR, 'packages', 'ai', 'ai-sdk.d.ts'), - ], - rnFirebaseModularFiles: [ - path.join(rnDist('ai'), 'index.d.ts'), - ], + firebaseSdkTypesPaths: [path.join(SCRIPT_DIR, 'packages', 'ai', 'ai-sdk.d.ts')], + rnFirebaseModularFiles: [path.join(rnDist('ai'), 'index.d.ts')], rnFirebaseSupportFiles: [ path.join(rnDist('ai'), 'backend.d.ts'), path.join(rnDist('ai'), 'errors.d.ts'), @@ -132,12 +151,7 @@ export const packages: PackageEntry[] = [ { name: 'firestore', firebaseSdkTypesPaths: [ - path.join( - SCRIPT_DIR, - 'packages', - 'firestore', - 'firestore-js-sdk.d.ts', - ), + path.join(SCRIPT_DIR, 'packages', 'firestore', 'firestore-js-sdk.d.ts'), ], rnFirebaseModularFiles: [ path.join(rnDist('firestore'), 'types', 'firestore.d.ts'), @@ -174,16 +188,9 @@ export const packages: PackageEntry[] = [ { name: 'firestore-pipelines', firebaseSdkTypesPaths: [ - path.join( - SCRIPT_DIR, - 'packages', - 'firestore-pipelines', - 'pipelines.d.ts', - ), - ], - rnFirebaseModularFiles: [ - path.join(rnDist('firestore'), 'pipelines', 'index.d.ts'), + path.join(SCRIPT_DIR, 'packages', 'firestore-pipelines', 'pipelines.d.ts'), ], + rnFirebaseModularFiles: [path.join(rnDist('firestore'), 'pipelines', 'index.d.ts')], rnFirebaseSupportFiles: [ path.join(rnDist('firestore'), 'pipelines', 'expressions.d.ts'), path.join(rnDist('firestore'), 'pipelines', 'pipeline.d.ts'), @@ -197,5 +204,3 @@ export const packages: PackageEntry[] = [ config: firestorePipelinesConfig, }, ]; - - diff --git a/packages/auth/type-test.ts b/packages/auth/type-test.ts index ab298449fa..32199be75c 100644 --- a/packages/auth/type-test.ts +++ b/packages/auth/type-test.ts @@ -1,311 +1,265 @@ +/* + * Consumer-facing API type tests for @react-native-firebase/auth. + * Part 1: namespaced API (firebase.auth(), default auth()). + * Part 2: modular API (getAuth, signInWithEmailAndPassword, etc. from lib/modular.ts). + */ + import auth, { firebase, - FirebaseAuthTypes, + applyActionCode, + beforeAuthStateChanged, + checkActionCode, + confirmPasswordReset, + connectAuthEmulator, + createUserWithEmailAndPassword, + EmailAuthProvider, + fetchSignInMethodsForEmail, + getAdditionalUserInfo, getAuth, + getCustomAuthDomain, + getMultiFactorResolver, + getRedirectResult, initializeAuth, + isSignInWithEmailLink, + multiFactor, onAuthStateChanged, onIdTokenChanged, + parseActionCodeURL, + PhoneAuthProvider, + sendPasswordResetEmail, + sendSignInLinkToEmail, + setLanguageCode, signInAnonymously, - signInWithEmailAndPassword, signInWithCredential, signInWithCustomToken, + signInWithEmailAndPassword, signInWithEmailLink, signInWithPhoneNumber, + signInWithPopup, + signInWithRedirect, signOut, - createUserWithEmailAndPassword, - sendPasswordResetEmail, - confirmPasswordReset, - verifyPasswordResetCode, - sendSignInLinkToEmail, - isSignInWithEmailLink, - fetchSignInMethodsForEmail, + updateCurrentUser, useDeviceLanguage, - setLanguageCode, - connectAuthEmulator, - getMultiFactorResolver, - multiFactor, - EmailAuthProvider, + useUserAccessGroup, + validatePassword, + verifyPasswordResetCode, + type ActionCodeInfo, + type ActionCodeSettings, + type ApplicationVerifier, + type Auth, + type AuthCredential, + type AuthProvider, + type AuthSettings, + type Config, + type ConfirmationResult, + type Dependencies, + type IdTokenResult, + type MultiFactorError, + type PasswordPolicy, + type PasswordValidationStatus, + type Persistence, + type PopupRedirectResolver, + type Unsubscribe, + type User, + type UserCredential, } from '.'; -console.log(auth().app); - -// checks module exists at root -console.log(firebase.auth().app.name); -console.log(firebase.auth().currentUser); +const authModule = auth(); +const namespacedAuth = firebase.auth(); +const authFromApp = firebase.app().auth(); +const authFromAppArg = auth(firebase.app()); -// checks module exists at app level -console.log(firebase.app().auth().app.name); -console.log(firebase.app().auth().currentUser); - -// checks statics exist +console.log(authModule.app.name); +console.log(namespacedAuth.currentUser); +console.log(authFromApp.app.name); +console.log(authFromAppArg.app.name); console.log(firebase.auth.SDK_VERSION); - -// checks statics exist on defaultExport console.log(auth.firebase.SDK_VERSION); - -// checks root exists console.log(firebase.SDK_VERSION); -// checks multi-app support exists -console.log(firebase.auth(firebase.app()).app.name); - -// checks default export supports app arg -console.log(auth(firebase.app()).app.name); - -// checks statics - providers -console.log(firebase.auth.EmailAuthProvider.PROVIDER_ID); -console.log(firebase.auth.PhoneAuthProvider.PROVIDER_ID); -console.log(firebase.auth.GoogleAuthProvider.PROVIDER_ID); -console.log(firebase.auth.GithubAuthProvider.PROVIDER_ID); -console.log(firebase.auth.TwitterAuthProvider.PROVIDER_ID); -console.log(firebase.auth.FacebookAuthProvider.PROVIDER_ID); -console.log(firebase.auth.AppleAuthProvider.PROVIDER_ID); -console.log(firebase.auth.OAuthProvider); -console.log(firebase.auth.OIDCAuthProvider); -console.log(firebase.auth.PhoneAuthState.CODE_SENT); -console.log(firebase.auth.PhoneMultiFactorGenerator); -console.log(firebase.auth.getMultiFactorResolver); -console.log(firebase.auth.multiFactor); - -// checks Module instance APIs -const authInstance = firebase.auth(); -console.log(authInstance.currentUser); -console.log(authInstance.tenantId); -console.log(authInstance.languageCode); -console.log(authInstance.settings); - -authInstance.setTenantId('tenant-123').then(() => { - console.log('Tenant set'); -}); - -authInstance.setLanguageCode('fr').then(() => { - console.log('Language set'); -}); - -authInstance.useEmulator('http://localhost:9099'); - -const unsubscribe1 = authInstance.onAuthStateChanged((user: FirebaseAuthTypes.User | null) => { - if (user) { - console.log(user.email); - console.log(user.displayName); - console.log(user.uid); - } -}); - -const unsubscribe2 = authInstance.onIdTokenChanged((user: FirebaseAuthTypes.User | null) => { - if (user) { - console.log(user.email); - } -}); - -unsubscribe1(); -unsubscribe2(); +const actionCodeSettings: ActionCodeSettings = { + url: 'https://example.com/auth', + handleCodeInApp: true, + android: { packageName: 'io.invertase.demo', installApp: true }, + iOS: { bundleId: 'io.invertase.demo' }, +}; + +const appVerifier: ApplicationVerifier = { + type: 'recaptcha', + verify: async () => 'token', +}; + +const popupRedirectResolver: PopupRedirectResolver = {}; +const redirectProvider: AuthProvider = { + PROVIDER_ID: 'oidc.test', + credential: (token: string | null, secret?: string) => + ({ token, secret, providerId: 'oidc.test' }) as AuthCredential, +}; +const authSettings: AuthSettings = { appVerificationDisabledForTesting: true }; +const persistence: Persistence = { type: 'NONE' }; +const authConfig: Config = { + apiKey: 'api-key', + apiHost: 'identitytoolkit.googleapis.com', + apiScheme: 'https', + tokenApiHost: 'securetoken.googleapis.com', + sdkClientVersion: 'web/0.0.0', +}; +const dependencies: Dependencies = { + persistence, + popupRedirectResolver, +}; +const passwordPolicy: PasswordPolicy = { + customStrengthOptions: { minPasswordLength: 6 }, + allowedNonAlphanumericCharacters: '!@#', + enforcementState: 'OFF', + forceUpgradeOnSignin: false, +}; +const passwordValidationStatus: PasswordValidationStatus = { + isValid: true, + passwordPolicy, +}; + +console.log(authSettings.appVerificationDisabledForTesting); +console.log(authConfig.apiHost); +console.log(dependencies.persistence); +console.log(passwordValidationStatus.passwordPolicy.enforcementState); + +const modularAuth: Auth = getAuth(); +const modularAuthFromApp: Auth = getAuth(firebase.app()); +const initializedAuth: Auth = initializeAuth(firebase.app(), dependencies); +console.log(modularAuth.app.name, modularAuthFromApp.app.name, initializedAuth.app.name); + +namespacedAuth.setTenantId('tenant-123'); +namespacedAuth.setLanguageCode('en'); +namespacedAuth.useEmulator('http://localhost:9099'); +namespacedAuth.sendPasswordResetEmail('test@example.com'); +namespacedAuth.sendSignInLinkToEmail('test@example.com', actionCodeSettings); +namespacedAuth.verifyPasswordResetCode('oob-code').then((email: string) => console.log(email)); +namespacedAuth + .checkActionCode('oob-code') + .then((info: ActionCodeInfo) => console.log(info.operation)); +namespacedAuth.getCustomAuthDomain().then((domain: string) => console.log(domain)); + +const namespacedUnsubscribe: Unsubscribe = namespacedAuth.onAuthStateChanged( + (user: User | null) => { + console.log(user?.uid); + }, +); +namespacedUnsubscribe(); -authInstance.signInAnonymously().then((credential: FirebaseAuthTypes.UserCredential) => { - console.log(credential.user.uid); +namespacedAuth.onIdTokenChanged((user: User | null) => { + console.log(user?.email); }); -authInstance +namespacedAuth + .signInAnonymously() + .then((credential: UserCredential) => console.log(credential.user.uid)); +namespacedAuth + .createUserWithEmailAndPassword('new@example.com', 'password123') + .then((credential: UserCredential) => console.log(credential.user.email)); +namespacedAuth .signInWithEmailAndPassword('test@example.com', 'password123') - .then((credential: FirebaseAuthTypes.UserCredential) => { - console.log(credential.user.email); - }); - -authInstance + .then((credential: UserCredential) => console.log(credential.user.email)); +namespacedAuth .signInWithCustomToken('custom-token') - .then((credential: FirebaseAuthTypes.UserCredential) => { - console.log(credential.user.uid); - }); - -authInstance + .then((credential: UserCredential) => console.log(credential.user.uid)); +namespacedAuth .signInWithEmailLink('test@example.com', 'email-link') - .then((credential: FirebaseAuthTypes.UserCredential) => { - console.log(credential.user.email); - }); - -authInstance + .then((credential: UserCredential) => console.log(credential.user.email)); +namespacedAuth .signInWithPhoneNumber('+1234567890') - .then((result: FirebaseAuthTypes.ConfirmationResult) => { - console.log(result.verificationId); - }); - -authInstance.signOut().then(() => { - console.log('Signed out'); -}); + .then((result: ConfirmationResult) => console.log(result.verificationId)); +namespacedAuth.signOut(); -authInstance - .createUserWithEmailAndPassword('new@example.com', 'password123') - .then((credential: FirebaseAuthTypes.UserCredential) => { - console.log(credential.user.email); - }); +const emailCredential = EmailAuthProvider.credential('test@example.com', 'password123'); +const phoneCredential = PhoneAuthProvider.credential('verification-id', '123456'); +console.log(emailCredential.providerId, phoneCredential.providerId); -authInstance.sendPasswordResetEmail('test@example.com').then(() => { - console.log('Password reset email sent'); -}); - -authInstance.confirmPasswordReset('code', 'newPassword').then(() => { - console.log('Password reset confirmed'); -}); - -authInstance.verifyPasswordResetCode('code').then((email: string) => { - console.log(email); -}); - -authInstance.sendSignInLinkToEmail('test@example.com').then(() => { - console.log('Sign in link sent'); -}); - -authInstance.isSignInWithEmailLink('email-link').then((isLink: boolean) => { - console.log(isLink); -}); - -authInstance.fetchSignInMethodsForEmail('test@example.com').then((methods: string[]) => { - console.log(methods); -}); - -const resolver = authInstance.getMultiFactorResolver({} as FirebaseAuthTypes.MultiFactorError); -console.log(resolver); - -authInstance.getCustomAuthDomain().then((domain: string) => { - console.log(domain); -}); - -// checks modular API functions -const authModular1 = getAuth(); -console.log(authModular1.app.name); - -const authModular2 = getAuth(firebase.app()); -console.log(authModular2.app.name); - -const authModular3 = initializeAuth(firebase.app()); -console.log(authModular3.app.name); - -onAuthStateChanged(authInstance, (user: FirebaseAuthTypes.User | null) => { - console.log(user?.email); -}); - -onIdTokenChanged(authInstance, (user: FirebaseAuthTypes.User | null) => { - console.log(user?.email); -}); - -signInAnonymously(authInstance).then((credential: FirebaseAuthTypes.UserCredential) => { - console.log(credential.user.uid); -}); - -signInWithEmailAndPassword(authInstance, 'test@example.com', 'password123').then( - (credential: FirebaseAuthTypes.UserCredential) => { - console.log(credential.user.email); - }, +applyActionCode(modularAuth, 'oob-code'); +checkActionCode(modularAuth, 'oob-code').then((info: ActionCodeInfo) => + console.log(info.data.email), ); - -const emailCredential = EmailAuthProvider.credential('test@example.com', 'password'); -signInWithCredential(authInstance, emailCredential).then( - (credential: FirebaseAuthTypes.UserCredential) => { - console.log(credential.user.email); - }, +confirmPasswordReset(modularAuth, 'oob-code', 'new-password'); +connectAuthEmulator(modularAuth, 'http://localhost:9099', { disableWarnings: false }); +createUserWithEmailAndPassword(modularAuth, 'new@example.com', 'password123').then( + (credential: UserCredential) => console.log(credential.user.uid), ); - -signInWithCustomToken(authInstance, 'custom-token').then( - (credential: FirebaseAuthTypes.UserCredential) => { - console.log(credential.user.uid); - }, +fetchSignInMethodsForEmail(modularAuth, 'test@example.com').then((methods: string[]) => + console.log(methods), ); +getMultiFactorResolver(modularAuth, {} as MultiFactorError); +getRedirectResult(modularAuth, popupRedirectResolver).then(result => console.log(result?.user.uid)); +isSignInWithEmailLink(modularAuth, 'email-link').then((valid: boolean) => console.log(valid)); -signInWithEmailLink(authInstance, 'test@example.com', 'email-link').then( - (credential: FirebaseAuthTypes.UserCredential) => { - console.log(credential.user.email); - }, +const modularUnsubscribe: Unsubscribe = onAuthStateChanged(modularAuth, (user: User | null) => + console.log(user?.email), ); +modularUnsubscribe(); -signInWithPhoneNumber(authInstance, '+1234567890').then( - (result: FirebaseAuthTypes.ConfirmationResult) => { - console.log(result.verificationId); - }, +onIdTokenChanged(modularAuth, (user: User | null) => console.log(user?.uid)); +signInAnonymously(modularAuth).then((credential: UserCredential) => + console.log(credential.user.uid), ); - -signOut(authInstance).then(() => { - console.log('Signed out'); -}); - -createUserWithEmailAndPassword(authInstance, 'new@example.com', 'password123').then( - (credential: FirebaseAuthTypes.UserCredential) => { - console.log(credential.user.email); - }, +signInWithCredential(modularAuth, emailCredential).then((credential: UserCredential) => + console.log(credential.user.email), +); +signInWithCustomToken(modularAuth, 'custom-token').then((credential: UserCredential) => + console.log(credential.user.uid), +); +signInWithEmailAndPassword(modularAuth, 'test@example.com', 'password123').then( + (credential: UserCredential) => console.log(credential.user.email), +); +signInWithEmailLink(modularAuth, 'test@example.com', 'email-link').then( + (credential: UserCredential) => console.log(credential.user.email), +); +signInWithPhoneNumber(modularAuth, '+1234567890', appVerifier).then((result: ConfirmationResult) => + console.log(result.verificationId), +); +signInWithPopup(modularAuth, redirectProvider, popupRedirectResolver).then(result => + console.log(result.user.uid), +); +signInWithRedirect(modularAuth, redirectProvider, popupRedirectResolver).then(result => + console.log(result.user.uid), +); +signOut(modularAuth); +sendPasswordResetEmail(modularAuth, 'test@example.com', actionCodeSettings); +sendSignInLinkToEmail(modularAuth, 'test@example.com', actionCodeSettings); +setLanguageCode(modularAuth, 'fr'); +useUserAccessGroup(modularAuth, 'group.example'); +verifyPasswordResetCode(modularAuth, 'oob-code').then((email: string) => console.log(email)); +getCustomAuthDomain(modularAuth).then((domain: string) => console.log(domain)); +validatePassword(modularAuth, 'password123').then((status: PasswordValidationStatus) => + console.log(status.isValid), ); -sendPasswordResetEmail(authInstance, 'test@example.com').then(() => { - console.log('Password reset email sent'); -}); - -confirmPasswordReset(authInstance, 'code', 'newPassword').then(() => { - console.log('Password reset confirmed'); -}); - -verifyPasswordResetCode(authInstance, 'code').then((email: string) => { - console.log(email); -}); - -sendSignInLinkToEmail(authInstance, 'test@example.com').then(() => { - console.log('Sign in link sent'); -}); - -isSignInWithEmailLink(authInstance, 'email-link').then((isLink: boolean) => { - console.log(isLink); -}); - -fetchSignInMethodsForEmail(authInstance, 'test@example.com').then((methods: string[]) => { - console.log(methods); -}); - -useDeviceLanguage(authInstance); - -setLanguageCode(authInstance, 'fr').then(() => { - console.log('Language set'); +beforeAuthStateChanged(modularAuth, async (user: User | null) => { + console.log(user?.uid); }); +updateCurrentUser(modularAuth, null); +useDeviceLanguage(modularAuth); -connectAuthEmulator(authInstance, 'http://localhost:9099', { disableWarnings: false }); - -const modularResolver = getMultiFactorResolver( - authInstance, - {} as FirebaseAuthTypes.MultiFactorError, +const parsedActionCode = parseActionCodeURL( + 'https://example.com/auth?mode=verifyEmail&oobCode=abc', ); -console.log(modularResolver); - -// Test User methods if currentUser exists -const currentUser = authInstance.currentUser; -if (currentUser) { - currentUser.reload().then(() => { - console.log('User reloaded'); - }); - - currentUser.getIdToken().then((token: string) => { - console.log(token); - }); - - currentUser.getIdToken(true).then((token: string) => { - console.log(token); - }); - - currentUser.getIdTokenResult().then((result: FirebaseAuthTypes.IdTokenResult) => { - console.log(result.token); - }); - - currentUser.sendEmailVerification().then(() => { - console.log('Verification email sent'); - }); - - currentUser.updateEmail('new@example.com').then(() => { - console.log('Email updated'); - }); - - currentUser.updatePassword('newPassword').then(() => { - console.log('Password updated'); - }); - - currentUser.updateProfile({ displayName: 'New Name' }).then(() => { - console.log('Profile updated'); - }); - - const multiFactorUser = multiFactor(currentUser); - console.log(multiFactorUser); +console.log(parsedActionCode?.code); + +const additionalUserInfo = getAdditionalUserInfo({ + additionalUserInfo: null, + user: {} as User, +} as unknown as UserCredential); +console.log(additionalUserInfo); + +const maybeUser = namespacedAuth.currentUser; +if (maybeUser) { + maybeUser.reload(); + maybeUser.getIdToken().then((token: string) => console.log(token)); + maybeUser.getIdTokenResult().then((result: IdTokenResult) => console.log(result.claims)); + maybeUser.sendEmailVerification(actionCodeSettings); + maybeUser.updateEmail('new@example.com'); + maybeUser.updatePassword('new-password'); + maybeUser.updatePhoneNumber(phoneCredential); + maybeUser.updateProfile({ displayName: 'New Name', photoURL: 'https://example.com/photo.png' }); + + const mfaUser = multiFactor(maybeUser); + mfaUser.getSession(); } diff --git a/tsconfig.json b/tsconfig.json index dfc05c3a7b..c63c97dff8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,8 +3,6 @@ "packages/ai/lib/types/polyfills.d.ts", "packages/app/lib/internal/global.d.ts", "packages/app/lib/internal/web/memidb/index.d.ts", - "packages/auth/lib/index.d.ts", - "packages/auth/lib/modular/index.d.ts", "packages/database/lib/index.d.ts", "packages/database/lib/modular/index.d.ts", "packages/database/lib/modular/query.d.ts", @@ -76,7 +74,7 @@ ], "@react-native-firebase/firestore/pipelines": [ "./packages/firestore/dist/typescript/lib/pipelines/index.d.ts" - ], + ] } }, "exclude": ["node_modules", "**/*.spec.ts", "packages/**/dist"] From 9395382a179436d1d002c8276a4509eb6c277228 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Tue, 21 Apr 2026 14:30:18 +0100 Subject: [PATCH 07/45] refactor(auth): reduce compare-types drift from firebase-js-sdk --- .../compare-types/packages/auth/config.ts | 331 ++--------------- packages/auth/lib/index.ts | 45 ++- packages/auth/lib/modular.ts | 349 ++++++++++++++---- packages/auth/lib/types/auth.ts | 313 +++++++++++++--- packages/auth/type-test.ts | 17 +- 5 files changed, 621 insertions(+), 434 deletions(-) diff --git a/.github/scripts/compare-types/packages/auth/config.ts b/.github/scripts/compare-types/packages/auth/config.ts index e5f5f91bdb..6a17cf4153 100644 --- a/.github/scripts/compare-types/packages/auth/config.ts +++ b/.github/scripts/compare-types/packages/auth/config.ts @@ -2,9 +2,8 @@ * Known differences between the firebase-js-sdk @firebase/auth public * API and the @react-native-firebase/auth modular API. * - * Each entry must have a `name` (the export name) and a `reason` explaining - * why the difference exists. Any difference NOT listed here will cause CI to - * fail so that new drift is caught and deliberately acknowledged. + * Each entry must have a `name` and a `reason`. Any undocumented + * difference or stale entry will fail `yarn compare:types`. */ import type { PackageConfig } from '../../src/types'; @@ -18,20 +17,10 @@ const config: PackageConfig = { reason: 'Web-only reCAPTCHA bootstrap helper from the firebase-js-sdk. RN Firebase does not expose browser reCAPTCHA initialization because native SDKs own the phone-auth verification flow.', }, - { - name: 'ActionCodeOperation', - reason: - 'Not yet exported as a standalone modular enum map. RN Firebase currently exposes action-code operations through older auth result shapes instead of the firebase-js-sdk public enum export.', - }, - { - name: 'AuthError', - reason: - 'RN Firebase surfaces auth failures as `NativeFirebaseAuthError` / native bridge errors rather than exporting the firebase-js-sdk `AuthError` interface directly.', - }, { name: 'AuthErrorCodes', reason: - 'Not yet exported as the firebase-js-sdk `AuthErrorCodes` constant map. RN Firebase still relies on native error code strings.', + 'RN Firebase still relies on native auth error code strings and does not export the firebase-js-sdk AuthErrorCodes constant map.', }, { name: 'browserCookiePersistence', @@ -53,16 +42,6 @@ const config: PackageConfig = { reason: 'Browser-only sessionStorage persistence implementation from the firebase-js-sdk. Not applicable to React Native native-auth persistence.', }, - { - name: 'CompleteFn', - reason: - 'Not yet surfaced as a first-class auth export in the compare-types modular surface. Listener completion callbacks are typed through RN Firebase helper types instead.', - }, - { - name: 'CustomParameters', - reason: - 'Not yet exported as the firebase-js-sdk standalone custom-parameters interface. Provider parameter bags are still modeled through the legacy RNFB auth provider types.', - }, { name: 'debugErrorMap', reason: @@ -71,32 +50,22 @@ const config: PackageConfig = { { name: 'EmailAuthCredential', reason: - 'Not yet exported as a standalone modular credential type. Email credentials are created and consumed through `EmailAuthProvider` and legacy auth credential shapes.', - }, - { - name: 'EmulatorConfig', - reason: - 'Not yet exported as the firebase-js-sdk `EmulatorConfig` interface. RN Firebase connects to the emulator but does not currently surface the web SDK emulator config object.', - }, - { - name: 'ErrorFn', - reason: - 'Not yet surfaced as a first-class auth export in the compare-types modular surface. Listener error callbacks are typed through RN Firebase helper types instead.', + 'RN Firebase does not yet expose the firebase-js-sdk EmailAuthCredential class as part of the modular public surface.', }, { name: 'FacebookAuthProvider', reason: - 'Not yet surfaced as a direct modular/public auth export in the split TS surface. It remains available through the legacy namespaced export path.', + 'This provider class is still only reachable through the legacy namespaced export path, not the modular compare-types surface.', }, { name: 'GithubAuthProvider', reason: - 'Not yet surfaced as a direct modular/public auth export in the split TS surface. It remains available through the legacy namespaced export path.', + 'This provider class is still only reachable through the legacy namespaced export path, not the modular compare-types surface.', }, { name: 'GoogleAuthProvider', reason: - 'Not yet surfaced as a direct modular/public auth export in the split TS surface. It remains available through the legacy namespaced export path.', + 'This provider class is still only reachable through the legacy namespaced export path, not the modular compare-types surface.', }, { name: 'indexedDBLocalPersistence', @@ -106,77 +75,37 @@ const config: PackageConfig = { { name: 'inMemoryPersistence', reason: - 'The firebase-js-sdk persistence object is not currently exported from RN Firebase. Native SDK state is managed by the underlying platform auth implementation.', - }, - { - name: 'NextFn', - reason: - 'Not yet surfaced as a first-class auth export in the compare-types modular surface. Listener callback types are still routed through RN Firebase helper exports.', - }, - { - name: 'NextOrObserver', - reason: - 'Not yet exported as the firebase-js-sdk standalone listener helper alias. RN Firebase currently uses its own package-local observer helper in the modular wrapper.', + 'The firebase-js-sdk persistence object is not exported by RN Firebase because auth state is managed by the underlying native SDKs.', }, { name: 'OAuthCredential', reason: - 'Not yet exported as a standalone modular credential type. OAuth credentials are still represented through the legacy RNFB auth credential surface.', + 'RN Firebase does not yet expose the firebase-js-sdk OAuthCredential class as part of the modular public surface.', }, { name: 'OAuthCredentialOptions', reason: - 'Not yet exported as the firebase-js-sdk standalone OAuth credential options interface.', - }, - { - name: 'OperationType', - reason: - 'Not yet exported as the firebase-js-sdk operation-type enum map. RN Firebase still models operation types through the legacy namespaced auth surface.', - }, - { - name: 'ParsedToken', - reason: - 'Not yet exported as the firebase-js-sdk standalone parsed-token interface. RN Firebase exposes token claims through `IdTokenResult` only.', + 'RN Firebase does not yet export the firebase-js-sdk OAuthCredentialOptions interface.', }, { name: 'PhoneAuthCredential', reason: - 'Not yet exported as a standalone modular credential type. Phone credentials are created through `PhoneAuthProvider.credential()` and consumed through the legacy auth credential surface.', + 'RN Firebase does not yet expose the firebase-js-sdk PhoneAuthCredential class as part of the modular public surface.', }, { name: 'PhoneAuthProvider', reason: - 'Not yet surfaced as a direct modular/public auth export in the split TS surface. It remains available through the legacy namespaced export path.', - }, - { - name: 'PhoneInfoOptions', - reason: - 'Not yet exported as the firebase-js-sdk standalone phone-info options interface. RN Firebase still uses older package-specific MFA phone option types.', - }, - { - name: 'PhoneMultiFactorAssertion', - reason: - 'Not yet exported as the firebase-js-sdk standalone phone multi-factor assertion type.', - }, - { - name: 'PhoneSingleFactorInfoOptions', - reason: - 'Not yet exported as the firebase-js-sdk standalone phone single-factor info options interface.', + 'This provider class is still only reachable through the legacy namespaced export path, not the modular compare-types surface.', }, { name: 'prodErrorMap', reason: 'firebase-js-sdk web error-map helper. RN Firebase does not expose the SDK error-map selection API.', }, - { - name: 'ProviderId', - reason: - 'Not yet exported as the firebase-js-sdk provider-id enum map. RN Firebase still relies on provider ID strings and legacy provider classes.', - }, { name: 'ReactNativeAsyncStorage', reason: - 'The firebase-js-sdk React Native persistence helper type is not exported by RN Firebase because persistence is delegated to the native iOS/Android SDKs rather than configured through `initializeAuth()`.', + 'The firebase-js-sdk React Native persistence helper type is not exported by RN Firebase because persistence is delegated to the native iOS/Android SDKs rather than configured through initializeAuth().', }, { name: 'RecaptchaParameters', @@ -192,43 +121,18 @@ const config: PackageConfig = { reason: 'SAMLAuthProvider is not yet surfaced on the RN Firebase modular/public auth surface.', }, - { - name: 'SignInMethod', - reason: - 'Not yet exported as the firebase-js-sdk sign-in-method enum map. RN Firebase still uses provider ID strings and legacy provider helpers.', - }, - { - name: 'TotpMultiFactorAssertion', - reason: - 'Not yet exported as the firebase-js-sdk standalone TOTP multi-factor assertion type.', - }, { name: 'TwitterAuthProvider', reason: - 'Not yet surfaced as a direct modular/public auth export in the split TS surface. It remains available through the legacy namespaced export path.', - }, - { - name: 'Unsubscribe', - reason: - 'Not yet surfaced as a first-class auth export in the compare-types modular surface. Unsubscribe functions are currently emitted through package-local callback typing.', - }, - { - name: 'UserProfile', - reason: - 'Not yet exported as the firebase-js-sdk standalone `UserProfile` alias. RN Firebase still models profile payloads through `UpdateProfile` and the legacy user surface.', + 'This provider class is still only reachable through the legacy namespaced export path, not the modular compare-types surface.', }, ], extraInRN: [ - { - name: 'FirebaseApp', - reason: - 'RN Firebase-specific re-export of `ReactNativeFirebase.FirebaseApp` from `@react-native-firebase/app`. Not part of the firebase-js-sdk auth public API.', - }, { name: 'NativeFirebaseAuthError', reason: - 'RN Firebase-specific native bridge auth error type used in place of the firebase-js-sdk `AuthError` export.', + 'RN Firebase-specific native bridge auth error type used in place of the firebase-js-sdk AuthError export.', }, { name: 'OIDCProvider', @@ -240,51 +144,19 @@ const config: PackageConfig = { reason: 'RN Firebase-specific enum-like object describing native phone-auth listener states.', }, { - name: 'MultiFactorInfoCommon', - reason: 'RN Firebase-specific compatibility type used by the legacy namespaced MFA surface.', - }, - { - name: 'MultiFactor', - reason: - 'RN Firebase-specific extra public type retained from the existing namespaced-compatible auth surface.', - }, - { - name: 'UpdateProfile', - reason: - 'RN Firebase-specific named type export for the user profile update payload. The firebase-js-sdk inlines this object shape instead of exporting it separately.', - }, - { - name: 'ActionCodeSettingsAndroid', - reason: - 'RN Firebase-specific split helper type for the Android portion of `ActionCodeSettings`.', - }, - { - name: 'ActionCodeInfoData', - reason: 'RN Firebase-specific split helper type for the `ActionCodeInfo.data` payload.', - }, - { - name: 'ActionCodeSettingsIos', - reason: 'RN Firebase-specific split helper type for the iOS portion of `ActionCodeSettings`.', + name: 'PhoneAuthListener', + reason: 'RN Firebase-specific listener object returned by verifyPhoneNumber().', }, { - name: 'AuthListenerCallback', + name: 'PhoneAuthError', reason: - 'RN Firebase-specific named callback alias retained from the existing auth package surface.', + 'RN Firebase-specific phone verification error snapshot type used by native phone-auth listeners.', }, { name: 'PhoneAuthSnapshot', reason: 'RN Firebase-specific phone verification snapshot type used by native phone-auth listeners.', }, - { - name: 'PhoneAuthError', - reason: - 'RN Firebase-specific phone verification error snapshot type used by native phone-auth listeners.', - }, - { - name: 'PhoneAuthListener', - reason: 'RN Firebase-specific listener object returned by `verifyPhoneNumber()`.', - }, { name: 'verifyPhoneNumber', reason: @@ -293,7 +165,7 @@ const config: PackageConfig = { { name: 'setLanguageCode', reason: - 'RN Firebase-specific modular helper function mirroring the existing native package surface; the firebase-js-sdk uses the writable `auth.languageCode` property instead.', + 'RN Firebase keeps a modular helper for setting auth.languageCode, while the firebase-js-sdk only exposes the writable property.', }, { name: 'useUserAccessGroup', @@ -308,190 +180,45 @@ const config: PackageConfig = { ], differentShape: [ - { - name: 'beforeAuthStateChanged', - reason: - 'RN Firebase exposes the helper as unsupported and returns a plain unsubscribe function type `() => void` rather than the firebase-js-sdk `Unsubscribe` alias.', - }, { name: 'connectAuthEmulator', reason: - 'The optional `disableWarnings` property is modeled as optional in RN Firebase, while the firebase-js-sdk public type text shows a required boolean property.', - }, - { - name: 'getMultiFactorResolver', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.getMultiFactorResolver` alias instead of a firebase-js-sdk-aligned direct modular function type.', + 'RN Firebase models disableWarnings as an optional property, while the firebase-js-sdk emitted type text shows a required boolean property.', }, { name: 'isSignInWithEmailLink', reason: - 'RN Firebase resolves this check asynchronously through the native bridge and returns `Promise`, whereas the firebase-js-sdk returns a synchronous `boolean`.', + 'RN Firebase resolves this check asynchronously through the native bridge and returns Promise, whereas the firebase-js-sdk returns a synchronous boolean.', }, { name: 'linkWithRedirect', reason: - 'Native provider flows resolve immediately with a `UserCredential` instead of following the browser redirect contract used by the firebase-js-sdk.', - }, - { - name: 'multiFactor', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.multiFactor` alias instead of a firebase-js-sdk-aligned direct modular function type.', - }, - { - name: 'onAuthStateChanged', - reason: - 'RN Firebase uses its package-local observer helper type and returns a plain `() => void` unsubscribe function instead of the firebase-js-sdk `Unsubscribe` alias text.', - }, - { - name: 'onIdTokenChanged', - reason: - 'RN Firebase uses its package-local observer helper type and returns a plain `() => void` unsubscribe function instead of the firebase-js-sdk `Unsubscribe` alias text.', + 'Native provider flows resolve immediately with a UserCredential instead of following the browser redirect contract used by the firebase-js-sdk.', }, { name: 'reauthenticateWithRedirect', reason: - 'Native provider flows do not follow the browser redirect contract. RN Firebase models this as `Promise` rather than the firebase-js-sdk `Promise` redirect signature.', - }, - { - name: 'sendEmailVerification', - reason: - 'RN Firebase models the optional action code settings as `ActionCodeSettings | undefined`, while the firebase-js-sdk public type uses `ActionCodeSettings | null`.', + 'Native provider flows do not follow the browser redirect contract. RN Firebase models this as Promise rather than the firebase-js-sdk Promise signature.', }, { name: 'signInWithRedirect', reason: - 'Native provider flows resolve immediately with a `UserCredential` instead of following the browser redirect contract used by the firebase-js-sdk.', + 'Native provider flows resolve immediately with a UserCredential instead of following the browser redirect contract used by the firebase-js-sdk.', }, { name: 'updatePhoneNumber', reason: - 'RN Firebase accepts the broader `AuthCredential` surface, while the firebase-js-sdk narrows this parameter to `PhoneAuthCredential`.', - }, - { - name: 'updateProfile', - reason: - 'RN Firebase exports and reuses the named `UpdateProfile` type alias rather than the firebase-js-sdk inline object type text.', - }, - { - name: 'verifyBeforeUpdateEmail', - reason: - 'RN Firebase models the optional action code settings as `ActionCodeSettings | undefined`, while the firebase-js-sdk public type uses `ActionCodeSettings | null`.', - }, - { - name: 'ActionCodeInfo', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.ActionCodeInfo` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', - }, - { - name: 'ActionCodeSettings', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.ActionCodeSettings` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', - }, - { - name: 'AdditionalUserInfo', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.AdditionalUserInfo` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + 'RN Firebase accepts the broader AuthCredential surface, while the firebase-js-sdk narrows this parameter to PhoneAuthCredential.', }, { name: 'Auth', reason: - 'The modular `Auth` type still aliases `FirebaseAuthTypes.Module`, so compare-types sees the older namespaced-compatible auth surface rather than a firebase-js-sdk-aligned modular interface.', - }, - { - name: 'AuthProvider', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.AuthProvider` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + 'The public Auth surface now matches structurally, but the emitted declaration text still differs from the firebase-js-sdk because RN Firebase uses its local FirebaseApp and NextOrObserver spellings in the generated interface.', }, { - name: 'ConfirmationResult', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.ConfirmationResult` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', - }, - { - name: 'FactorId', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.FactorId` alias instead of a firebase-js-sdk-aligned direct enum-map declaration.', - }, - { - name: 'IdTokenResult', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.IdTokenResult` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', - }, - { - name: 'MultiFactorAssertion', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.MultiFactorAssertion` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', - }, - { - name: 'MultiFactorError', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.MultiFactorError` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', - }, - { - name: 'MultiFactorInfo', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.MultiFactorInfo` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', - }, - { - name: 'MultiFactorResolver', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.MultiFactorResolver` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', - }, - { - name: 'MultiFactorSession', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.MultiFactorSession` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', - }, - { - name: 'MultiFactorUser', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.MultiFactorUser` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', - }, - { - name: 'Persistence', - reason: - 'RN Firebase exports `Persistence` as a readonly object type alias, while the firebase-js-sdk declares it as an interface.', - }, - { - name: 'PhoneMultiFactorEnrollInfoOptions', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.PhoneMultiFactorEnrollInfoOptions` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', - }, - { - name: 'PhoneMultiFactorInfo', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.PhoneMultiFactorInfo` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', - }, - { - name: 'PhoneMultiFactorSignInInfoOptions', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.PhoneMultiFactorSignInInfoOptions` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', - }, - { - name: 'TotpMultiFactorInfo', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.TotpMultiFactorInfo` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', - }, - { - name: 'User', - reason: - 'The modular `User` type still aliases the legacy `FirebaseAuthTypes.User` surface, so compare-types sees the older namespaced-compatible user shape.', - }, - { - name: 'UserCredential', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.UserCredential` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', - }, - { - name: 'UserInfo', - reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.UserInfo` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', - }, - { - name: 'UserMetadata', + name: 'ParsedToken', reason: - 'Still re-exported through the legacy `FirebaseAuthTypes.UserMetadata` alias instead of a firebase-js-sdk-aligned direct modular interface declaration.', + 'TypeScript emits the parsed-token property keys without quotes in the generated declaration file, so compare-types reports a text-only difference even though the property set matches the firebase-js-sdk surface.', }, ], }; diff --git a/packages/auth/lib/index.ts b/packages/auth/lib/index.ts index 84404c72f2..f32f9659d6 100644 --- a/packages/auth/lib/index.ts +++ b/packages/auth/lib/index.ts @@ -15,57 +15,82 @@ * */ +export type FirebaseApp = import('@react-native-firebase/app').ReactNativeFirebase.FirebaseApp; +export type Observer = { + next?: ((value: T) => void) | null; + error?: ((error: Error) => void) | null; + complete?: (() => void) | null; +}; +export type ActionCodeInfoData = import('./types/namespaced').FirebaseAuthTypes.ActionCodeInfoData; +export type ActionCodeSettingsAndroid = + import('./types/namespaced').FirebaseAuthTypes.ActionCodeSettingsAndroid; +export type ActionCodeSettingsIos = + import('./types/namespaced').FirebaseAuthTypes.ActionCodeSettingsIos; +export type AuthListenerCallback = + import('./types/namespaced').FirebaseAuthTypes.AuthListenerCallback; +export type MultiFactor = import('./types/namespaced').FirebaseAuthTypes.MultiFactor; +export type MultiFactorInfoCommon = + import('./types/namespaced').FirebaseAuthTypes.MultiFactorInfoCommon; +export type UpdateProfile = import('./types/namespaced').FirebaseAuthTypes.UpdateProfile; + +export { + ActionCodeOperation, + FactorId, + OperationType, + ProviderId, + SignInMethod, +} from './types/auth'; + export type { ActionCodeInfo, - ActionCodeInfoData, ActionCodeSettings, - ActionCodeSettingsAndroid, - ActionCodeSettingsIos, ActionCodeURL, AdditionalUserInfo, ApplicationVerifier, Auth, + AuthError, AuthErrorMap, AuthCredential, - AuthListenerCallback, AuthProvider, AuthSettings, CompleteFn, Config, ConfirmationResult, Dependencies, + EmulatorConfig, ErrorFn, - FactorId, - FirebaseApp, IdTokenResult, - MultiFactor, MultiFactorAssertion, MultiFactorError, MultiFactorInfo, - MultiFactorInfoCommon, MultiFactorResolver, MultiFactorSession, MultiFactorUser, NativeFirebaseAuthError, + NextOrObserver, NextFn, OIDCProvider, - Observer, + ParsedToken, PasswordPolicy, PasswordValidationStatus, Persistence, PhoneAuthError, + PhoneInfoOptions, PhoneAuthListener, PhoneAuthSnapshot, + PhoneMultiFactorAssertion, PhoneMultiFactorEnrollInfoOptions, PhoneMultiFactorInfo, PhoneMultiFactorSignInInfoOptions, + PhoneSingleFactorInfoOptions, PopupRedirectResolver, + TotpMultiFactorAssertion, TotpMultiFactorInfo, - UpdateProfile, User, UserCredential, UserInfo, UserMetadata, + UserProfile, Unsubscribe, } from './types/auth'; export * from './types/namespaced'; diff --git a/packages/auth/lib/modular.ts b/packages/auth/lib/modular.ts index 18ac58f8a1..2f39f657cf 100644 --- a/packages/auth/lib/modular.ts +++ b/packages/auth/lib/modular.ts @@ -16,7 +16,7 @@ import { getApp } from '@react-native-firebase/app'; import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/dist/module/common'; -import { MultiFactorUser } from './multiFactor'; +import { MultiFactorUser as MultiFactorUserModule } from './multiFactor'; import type { FirebaseApp } from '@react-native-firebase/app'; import type { ActionCodeInfo, @@ -34,17 +34,17 @@ import type { IdTokenResult, MultiFactorError, MultiFactorResolver, - MultiFactorUser as MultiFactorUserType, - NextFn, - Observer, + MultiFactorUser, + NextOrObserver, PasswordValidationStatus, Persistence, PhoneAuthListener, PopupRedirectResolver, - UpdateProfile, + Unsubscribe, User, UserCredential, } from './types/auth'; +import type { FirebaseAuthTypes } from './types/namespaced'; import type { UserInternal } from './types/internal'; type AnyFn = (...args: any[]) => any; @@ -53,14 +53,68 @@ type WithModularDeprecationArg = ( ...args: [...Parameters, typeof MODULAR_DEPRECATION_ARG] ) => ReturnType; -type AuthWithPasswordValidationInternal = Auth & { +type AuthModuleInternal = FirebaseAuthTypes.Module & { validatePassword(password: string): Promise; + getCustomAuthDomain(): Promise; }; -type NextOrObserverInternal = NextFn | Observer; +type UserModuleInternal = UserInternal; + +type AuthProviderWithObjectInternal = FirebaseAuthTypes.AuthProvider & { + toObject(): Record; +}; + +function getAuthInternal(auth: Auth): AuthModuleInternal { + return auth as unknown as AuthModuleInternal; +} + +function getUserInternal(user: User): UserModuleInternal { + return user as unknown as UserModuleInternal; +} + +function asAuth(auth: FirebaseAuthTypes.Module): Auth { + return auth as unknown as Auth; +} + +function asActionCodeInfo( + promise: Promise, +): Promise { + return promise as unknown as Promise; +} + +function asUserCredential( + promise: Promise, +): Promise { + return promise as unknown as Promise; +} + +function asIdTokenResult( + promise: Promise, +): Promise { + return promise as unknown as Promise; +} + +function asUser(promise: Promise): Promise { + return promise as unknown as Promise; +} + +function normalizeAuthListener( + nextOrObserver: NextOrObserver, +): FirebaseAuthTypes.AuthListenerCallback | { next: FirebaseAuthTypes.AuthListenerCallback } { + if (typeof nextOrObserver === 'function') { + return nextOrObserver as unknown as FirebaseAuthTypes.AuthListenerCallback; + } + + return { + next: + typeof nextOrObserver.next === 'function' + ? (nextOrObserver.next as unknown as FirebaseAuthTypes.AuthListenerCallback) + : () => {}, + }; +} function callAuthMethod( - auth: Auth, + auth: AuthModuleInternal, method: F, ...args: Parameters ): ReturnType { @@ -72,7 +126,7 @@ function callAuthMethod( } function callUserMethod( - user: User, + user: UserModuleInternal, method: F, ...args: Parameters ): ReturnType { @@ -88,33 +142,35 @@ function callUserMethod( */ export function getAuth(app?: FirebaseApp): Auth { if (app) { - return getApp(app.name).auth(); + return asAuth(getApp(app.name).auth()); } - return getApp().auth(); + return asAuth(getApp().auth()); } /** * This function allows more control over the Auth instance than getAuth(). */ export function initializeAuth(app: FirebaseApp, _deps?: Dependencies): Auth { - return getApp(app.name).auth(); + return asAuth(getApp(app.name).auth()); } export function applyActionCode(auth: Auth, oobCode: string): Promise { - return callAuthMethod(auth, auth.applyActionCode, oobCode); + const authInternal = getAuthInternal(auth); + return callAuthMethod(authInternal, authInternal.applyActionCode, oobCode); } export function beforeAuthStateChanged( _auth: Auth, _callback: (user: User | null) => void | Promise, _onAbort?: () => void, -): () => void { +): Unsubscribe { throw new Error('beforeAuthStateChanged is unsupported by the native Firebase SDKs'); } export function checkActionCode(auth: Auth, oobCode: string): Promise { - return callAuthMethod(auth, auth.checkActionCode, oobCode); + const authInternal = getAuthInternal(auth); + return asActionCodeInfo(callAuthMethod(authInternal, authInternal.checkActionCode, oobCode)); } export function confirmPasswordReset( @@ -122,7 +178,8 @@ export function confirmPasswordReset( oobCode: string, newPassword: string, ): Promise { - return callAuthMethod(auth, auth.confirmPasswordReset, oobCode, newPassword); + const authInternal = getAuthInternal(auth); + return callAuthMethod(authInternal, authInternal.confirmPasswordReset, oobCode, newPassword); } export function connectAuthEmulator( @@ -130,7 +187,8 @@ export function connectAuthEmulator( url: string, _options?: { disableWarnings?: boolean }, ): void { - callAuthMethod(auth, auth.useEmulator, url); + const authInternal = getAuthInternal(auth); + callAuthMethod(authInternal, authInternal.useEmulator, url); } export function createUserWithEmailAndPassword( @@ -138,15 +196,26 @@ export function createUserWithEmailAndPassword( email: string, password: string, ): Promise { - return callAuthMethod(auth, auth.createUserWithEmailAndPassword, email, password); + const authInternal = getAuthInternal(auth); + return asUserCredential( + callAuthMethod(authInternal, authInternal.createUserWithEmailAndPassword, email, password), + ); } export function fetchSignInMethodsForEmail(auth: Auth, email: string): Promise { - return callAuthMethod(auth, auth.fetchSignInMethodsForEmail, email); + const authInternal = getAuthInternal(auth); + return callAuthMethod(authInternal, authInternal.fetchSignInMethodsForEmail, email); } export function getMultiFactorResolver(auth: Auth, error: MultiFactorError): MultiFactorResolver { - return callAuthMethod(auth, auth.getMultiFactorResolver, error); + const authInternal = getAuthInternal(auth); + return callAuthMethod( + authInternal, + authInternal.getMultiFactorResolver as unknown as ( + error: MultiFactorError, + ) => FirebaseAuthTypes.MultiFactorResolver, + error, + ) as unknown as MultiFactorResolver; } export function getRedirectResult( @@ -157,29 +226,48 @@ export function getRedirectResult( } export function isSignInWithEmailLink(auth: Auth, emailLink: string): Promise { - return callAuthMethod(auth, auth.isSignInWithEmailLink, emailLink); + const authInternal = getAuthInternal(auth); + return callAuthMethod(authInternal, authInternal.isSignInWithEmailLink, emailLink); } export function onAuthStateChanged( auth: Auth, - nextOrObserver: NextOrObserverInternal, + nextOrObserver: NextOrObserver, _error?: ErrorFn, _completed?: CompleteFn, -): () => void { +): Unsubscribe { // The legacy callback overload exists for JS SDK compatibility, but native auth listeners // never invoke separate error/completed callbacks. - return callAuthMethod(auth, auth.onAuthStateChanged, nextOrObserver); + const authInternal = getAuthInternal(auth); + return callAuthMethod( + authInternal, + authInternal.onAuthStateChanged as unknown as ( + nextOrObserver: + | FirebaseAuthTypes.AuthListenerCallback + | { next: FirebaseAuthTypes.AuthListenerCallback }, + ) => Unsubscribe, + normalizeAuthListener(nextOrObserver), + ); } export function onIdTokenChanged( auth: Auth, - nextOrObserver: NextOrObserverInternal, + nextOrObserver: NextOrObserver, _error?: ErrorFn, _completed?: CompleteFn, -): () => void { +): Unsubscribe { // The legacy callback overload exists for JS SDK compatibility, but native auth listeners // never invoke separate error/completed callbacks. - return callAuthMethod(auth, auth.onIdTokenChanged, nextOrObserver); + const authInternal = getAuthInternal(auth); + return callAuthMethod( + authInternal, + authInternal.onIdTokenChanged as unknown as ( + nextOrObserver: + | FirebaseAuthTypes.AuthListenerCallback + | { next: FirebaseAuthTypes.AuthListenerCallback }, + ) => Unsubscribe, + normalizeAuthListener(nextOrObserver), + ); } export function revokeAccessToken(_auth: Auth, _token: string): Promise { @@ -191,7 +279,13 @@ export function sendPasswordResetEmail( email: string, actionCodeSettings?: ActionCodeSettings, ): Promise { - return callAuthMethod(auth, auth.sendPasswordResetEmail, email, actionCodeSettings); + const authInternal = getAuthInternal(auth); + return callAuthMethod( + authInternal, + authInternal.sendPasswordResetEmail, + email, + actionCodeSettings, + ); } export function sendSignInLinkToEmail( @@ -199,7 +293,13 @@ export function sendSignInLinkToEmail( email: string, actionCodeSettings: ActionCodeSettings, ): Promise { - return callAuthMethod(auth, auth.sendSignInLinkToEmail, email, actionCodeSettings); + const authInternal = getAuthInternal(auth); + return callAuthMethod( + authInternal, + authInternal.sendSignInLinkToEmail, + email, + actionCodeSettings, + ); } export function setPersistence(_auth: Auth, _persistence: Persistence): Promise { @@ -207,18 +307,25 @@ export function setPersistence(_auth: Auth, _persistence: Persistence): Promise< } export function signInAnonymously(auth: Auth): Promise { - return callAuthMethod(auth, auth.signInAnonymously); + const authInternal = getAuthInternal(auth); + return asUserCredential(callAuthMethod(authInternal, authInternal.signInAnonymously)); } export function signInWithCredential( auth: Auth, credential: AuthCredential, ): Promise { - return callAuthMethod(auth, auth.signInWithCredential, credential); + const authInternal = getAuthInternal(auth); + return asUserCredential( + callAuthMethod(authInternal, authInternal.signInWithCredential, credential), + ); } export function signInWithCustomToken(auth: Auth, customToken: string): Promise { - return callAuthMethod(auth, auth.signInWithCustomToken, customToken); + const authInternal = getAuthInternal(auth); + return asUserCredential( + callAuthMethod(authInternal, authInternal.signInWithCustomToken, customToken), + ); } export function signInWithEmailAndPassword( @@ -226,7 +333,10 @@ export function signInWithEmailAndPassword( email: string, password: string, ): Promise { - return callAuthMethod(auth, auth.signInWithEmailAndPassword, email, password); + const authInternal = getAuthInternal(auth); + return asUserCredential( + callAuthMethod(authInternal, authInternal.signInWithEmailAndPassword, email, password), + ); } export function signInWithEmailLink( @@ -234,7 +344,10 @@ export function signInWithEmailLink( email: string, emailLink: string, ): Promise { - return callAuthMethod(auth, auth.signInWithEmailLink, email, emailLink); + const authInternal = getAuthInternal(auth); + return asUserCredential( + callAuthMethod(authInternal, authInternal.signInWithEmailLink, email, emailLink), + ); } export function signInWithPhoneNumber( @@ -244,11 +357,12 @@ export function signInWithPhoneNumber( ): Promise { // Native SDKs own the verification flow, so the modular wrapper intentionally ignores the // JS SDK's optional ApplicationVerifier and forwards only the phone number. - const signInWithPhoneNumberInternal = auth.signInWithPhoneNumber as unknown as ( + const authInternal = getAuthInternal(auth); + const signInWithPhoneNumberInternal = authInternal.signInWithPhoneNumber as unknown as ( phoneNumber: string, ) => Promise; - return callAuthMethod(auth, signInWithPhoneNumberInternal, phoneNumber); + return callAuthMethod(authInternal, signInWithPhoneNumberInternal, phoneNumber); } export function verifyPhoneNumber( @@ -257,15 +371,22 @@ export function verifyPhoneNumber( autoVerifyTimeoutOrForceResend?: number | boolean, forceResend?: boolean, ): PhoneAuthListener { + const authInternal = getAuthInternal(auth); return ( - auth.verifyPhoneNumber as unknown as WithModularDeprecationArg< + authInternal.verifyPhoneNumber as unknown as WithModularDeprecationArg< ( phoneNumber: string, autoVerifyTimeoutOrForceResend?: number | boolean, forceResend?: boolean, ) => PhoneAuthListener > - ).call(auth, phoneNumber, autoVerifyTimeoutOrForceResend, forceResend, MODULAR_DEPRECATION_ARG); + ).call( + authInternal, + phoneNumber, + autoVerifyTimeoutOrForceResend, + forceResend, + MODULAR_DEPRECATION_ARG, + ); } export function signInWithPopup( @@ -273,7 +394,14 @@ export function signInWithPopup( provider: AuthProvider, _resolver?: PopupRedirectResolver, ): Promise { - return callAuthMethod(auth, auth.signInWithPopup, provider); + const authInternal = getAuthInternal(auth); + return asUserCredential( + callAuthMethod( + authInternal, + authInternal.signInWithPopup, + provider as unknown as AuthProviderWithObjectInternal, + ), + ); } export function signInWithRedirect( @@ -283,11 +411,19 @@ export function signInWithRedirect( ): Promise { // Native provider flows complete immediately and return a credential instead of following the // browser redirect contract from the Firebase JS SDK. - return callAuthMethod(auth, auth.signInWithRedirect, provider); + const authInternal = getAuthInternal(auth); + return asUserCredential( + callAuthMethod( + authInternal, + authInternal.signInWithRedirect, + provider as unknown as AuthProviderWithObjectInternal, + ), + ); } export function signOut(auth: Auth): Promise { - return callAuthMethod(auth, auth.signOut); + const authInternal = getAuthInternal(auth); + return callAuthMethod(authInternal, authInternal.signOut); } export function updateCurrentUser(_auth: Auth, _user: User | null): Promise { @@ -299,15 +435,20 @@ export function useDeviceLanguage(_auth: Auth): void { } export function setLanguageCode(auth: Auth, languageCode: string | null): Promise { - return callAuthMethod(auth, auth.setLanguageCode, languageCode); + const authInternal = getAuthInternal(auth); + return callAuthMethod(authInternal, authInternal.setLanguageCode, languageCode); } export function useUserAccessGroup(auth: Auth, userAccessGroup: string): Promise { - return callAuthMethod(auth, auth.useUserAccessGroup, userAccessGroup).then(() => undefined); + const authInternal = getAuthInternal(auth); + return callAuthMethod(authInternal, authInternal.useUserAccessGroup, userAccessGroup).then( + () => undefined, + ); } export function verifyPasswordResetCode(auth: Auth, code: string): Promise { - return callAuthMethod(auth, auth.verifyPasswordResetCode, code); + const authInternal = getAuthInternal(auth); + return callAuthMethod(authInternal, authInternal.verifyPasswordResetCode, code); } export function parseActionCodeURL(_link: string): ActionCodeURL | null { @@ -315,22 +456,28 @@ export function parseActionCodeURL(_link: string): ActionCodeURL | null { } export function deleteUser(user: User): Promise { - return callUserMethod(user, user.delete); + const userInternal = getUserInternal(user); + return callUserMethod(userInternal, userInternal.delete); } export function getIdToken(user: User, forceRefresh?: boolean): Promise { - return callUserMethod(user, user.getIdToken, forceRefresh); + const userInternal = getUserInternal(user); + return callUserMethod(userInternal, userInternal.getIdToken, forceRefresh); } export function getIdTokenResult(user: User, forceRefresh?: boolean): Promise { - return callUserMethod(user, user.getIdTokenResult, forceRefresh); + const userInternal = getUserInternal(user); + return asIdTokenResult(callUserMethod(userInternal, userInternal.getIdTokenResult, forceRefresh)); } export function linkWithCredential( user: User, credential: AuthCredential, ): Promise { - return callUserMethod(user, user.linkWithCredential, credential); + const userInternal = getUserInternal(user); + return asUserCredential( + callUserMethod(userInternal, userInternal.linkWithCredential, credential), + ); } export function linkWithPhoneNumber( @@ -346,7 +493,14 @@ export function linkWithPopup( provider: AuthProvider, _resolver?: PopupRedirectResolver, ): Promise { - return callUserMethod(user, user.linkWithPopup, provider); + const userInternal = getUserInternal(user); + return asUserCredential( + callUserMethod( + userInternal, + userInternal.linkWithPopup, + provider as unknown as AuthProviderWithObjectInternal, + ), + ); } export function linkWithRedirect( @@ -356,21 +510,31 @@ export function linkWithRedirect( ): Promise { // Native provider flows complete immediately and return a credential instead of following the // browser redirect contract from the Firebase JS SDK. - return callUserMethod(user, user.linkWithRedirect, provider); + const userInternal = getUserInternal(user); + return asUserCredential( + callUserMethod( + userInternal, + userInternal.linkWithRedirect, + provider as unknown as AuthProviderWithObjectInternal, + ), + ); } -export function multiFactor(user: User): MultiFactorUserType { - return new MultiFactorUser( - (user as UserInternal)._auth || getAuth(), +export function multiFactor(user: User): MultiFactorUser { + return new MultiFactorUserModule( + (user as unknown as UserInternal)._auth || getAuth(), user, - ) as MultiFactorUserType; + ) as MultiFactorUser; } export function reauthenticateWithCredential( user: User, credential: AuthCredential, ): Promise { - return callUserMethod(user, user.reauthenticateWithCredential, credential); + const userInternal = getUserInternal(user); + return asUserCredential( + callUserMethod(userInternal, userInternal.reauthenticateWithCredential, credential), + ); } export function reauthenticateWithPhoneNumber( @@ -386,7 +550,14 @@ export function reauthenticateWithPopup( provider: AuthProvider, _resolver?: PopupRedirectResolver, ): Promise { - return callUserMethod(user, user.reauthenticateWithPopup, provider); + const userInternal = getUserInternal(user); + return asUserCredential( + callUserMethod( + userInternal, + userInternal.reauthenticateWithPopup, + provider as unknown as AuthProviderWithObjectInternal, + ), + ); } export function reauthenticateWithRedirect( @@ -394,38 +565,57 @@ export function reauthenticateWithRedirect( provider: AuthProvider, _resolver?: PopupRedirectResolver, ): Promise { - return callUserMethod(user, user.reauthenticateWithRedirect, provider); + const userInternal = getUserInternal(user); + return callUserMethod( + userInternal, + userInternal.reauthenticateWithRedirect, + provider as unknown as AuthProviderWithObjectInternal, + ); } export function reload(user: User): Promise { - return callUserMethod(user, user.reload); + const userInternal = getUserInternal(user); + return callUserMethod(userInternal, userInternal.reload); } export function sendEmailVerification( user: User, - actionCodeSettings?: ActionCodeSettings, + actionCodeSettings?: ActionCodeSettings | null, ): Promise { - return callUserMethod(user, user.sendEmailVerification, actionCodeSettings); + const userInternal = getUserInternal(user); + return callUserMethod( + userInternal, + userInternal.sendEmailVerification, + actionCodeSettings ?? undefined, + ); } export function unlink(user: User, providerId: string): Promise { - return callUserMethod(user, user.unlink, providerId); + const userInternal = getUserInternal(user); + return asUser(callUserMethod(userInternal, userInternal.unlink, providerId)); } export function updateEmail(user: User, newEmail: string): Promise { - return callUserMethod(user, user.updateEmail, newEmail); + const userInternal = getUserInternal(user); + return callUserMethod(userInternal, userInternal.updateEmail, newEmail); } export function updatePassword(user: User, newPassword: string): Promise { - return callUserMethod(user, user.updatePassword, newPassword); + const userInternal = getUserInternal(user); + return callUserMethod(userInternal, userInternal.updatePassword, newPassword); } export function updatePhoneNumber(user: User, credential: AuthCredential): Promise { - return callUserMethod(user, user.updatePhoneNumber, credential); + const userInternal = getUserInternal(user); + return callUserMethod(userInternal, userInternal.updatePhoneNumber, credential); } -export function updateProfile(user: User, profile: UpdateProfile): Promise { - return callUserMethod(user, user.updateProfile, { +export function updateProfile( + user: User, + profile: { displayName?: string | null; photoURL?: string | null }, +): Promise { + const userInternal = getUserInternal(user); + return callUserMethod(userInternal, userInternal.updateProfile, { displayName: profile.displayName, photoURL: profile.photoURL, }); @@ -434,17 +624,34 @@ export function updateProfile(user: User, profile: UpdateProfile): Promise export function verifyBeforeUpdateEmail( user: User, newEmail: string, - actionCodeSettings?: ActionCodeSettings, + actionCodeSettings?: ActionCodeSettings | null, ): Promise { - return callUserMethod(user, user.verifyBeforeUpdateEmail, newEmail, actionCodeSettings); + const userInternal = getUserInternal(user); + return callUserMethod( + userInternal, + userInternal.verifyBeforeUpdateEmail, + newEmail, + actionCodeSettings ?? undefined, + ); } export function getAdditionalUserInfo(userCredential: UserCredential): AdditionalUserInfo | null { - return userCredential.additionalUserInfo ?? null; + const info = (userCredential as unknown as FirebaseAuthTypes.UserCredential).additionalUserInfo; + if (!info) { + return null; + } + + return { + isNewUser: info.isNewUser, + profile: info.profile ?? null, + providerId: info.providerId ?? null, + username: info.username ?? null, + }; } export function getCustomAuthDomain(auth: Auth): Promise { - return callAuthMethod(auth, auth.getCustomAuthDomain); + const authInternal = getAuthInternal(auth); + return callAuthMethod(authInternal, authInternal.getCustomAuthDomain); } export function validatePassword(auth: Auth, password: string): Promise { @@ -460,7 +667,7 @@ export function validatePassword(auth: Auth, password: string): Promise void; +export type ErrorFn = (error: Error) => void; +export type NextFn = (value: T) => void; +export type Unsubscribe = () => void; + +interface Observer { + next?: NextFn | null; + error?: ErrorFn | null; + complete?: CompleteFn | null; +} + +type FirebaseApp = ReactNativeFirebase.FirebaseApp; + +export const ActionCodeOperation = { + EMAIL_SIGNIN: 'EMAIL_SIGNIN', + PASSWORD_RESET: 'PASSWORD_RESET', + RECOVER_EMAIL: 'RECOVER_EMAIL', + REVERT_SECOND_FACTOR_ADDITION: 'REVERT_SECOND_FACTOR_ADDITION', + VERIFY_AND_CHANGE_EMAIL: 'VERIFY_AND_CHANGE_EMAIL', + VERIFY_EMAIL: 'VERIFY_EMAIL', +} as const; + +export const FactorId = { + PHONE: 'phone', + TOTP: 'totp', +} as const; + +export const OperationType = { + LINK: 'link', + REAUTHENTICATE: 'reauthenticate', + SIGN_IN: 'signIn', +} as const; + +export const ProviderId = { + FACEBOOK: 'facebook.com', + GITHUB: 'github.com', + GOOGLE: 'google.com', + PASSWORD: 'password', + PHONE: 'phone', + TWITTER: 'twitter.com', +} as const; + +export const SignInMethod = { + EMAIL_LINK: 'emailLink', + EMAIL_PASSWORD: 'password', + FACEBOOK: 'facebook.com', + GITHUB: 'github.com', + GOOGLE: 'google.com', + PHONE: 'phone', + TWITTER: 'twitter.com', +} as const; + +export type Auth = { + readonly app: FirebaseApp; + readonly name: string; + readonly config: Config; + setPersistence(persistence: Persistence): Promise; + languageCode: string | null; + tenantId: string | null; + readonly settings: AuthSettings; + onAuthStateChanged( + nextOrObserver: NextOrObserver, + error?: ErrorFn, + completed?: CompleteFn, + ): Unsubscribe; + beforeAuthStateChanged( + callback: (user: User | null) => void | Promise, + onAbort?: () => void, + ): Unsubscribe; + onIdTokenChanged( + nextOrObserver: NextOrObserver, + error?: ErrorFn, + completed?: CompleteFn, + ): Unsubscribe; + authStateReady?: () => Promise; + readonly currentUser: User | null; + readonly emulatorConfig?: EmulatorConfig | null; + updateCurrentUser(user: User | null): Promise; + useDeviceLanguage(): void; + signOut(): Promise; +}; + +export interface AuthError extends ReactNativeFirebase.NativeFirebaseError { + readonly customData: { + readonly appName: string; + readonly email?: string; + readonly phoneNumber?: string; + readonly tenantId?: string; + }; +} -export type FirebaseApp = ReactNativeFirebase.FirebaseApp; -export type Auth = FirebaseAuthTypes.Module; export type NativeFirebaseAuthError = FirebaseAuthTypes.NativeFirebaseAuthError; export type AuthCredential = FirebaseAuthTypes.AuthCredential; -export type AuthProvider = FirebaseAuthTypes.AuthProvider; export type OAuthProvider = FirebaseAuthTypes.OAuthProvider; export type OIDCProvider = FirebaseAuthTypes.OIDCProvider; export type EmailAuthProvider = FirebaseAuthTypes.EmailAuthProvider; export type PhoneAuthState = FirebaseAuthTypes.PhoneAuthState; -export type MultiFactorSession = FirebaseAuthTypes.MultiFactorSession; export type PhoneMultiFactorGenerator = FirebaseAuthTypes.PhoneMultiFactorGenerator; export type TotpSecret = FirebaseAuthTypes.TotpSecret; export type TotpMultiFactorGenerator = FirebaseAuthTypes.TotpMultiFactorGenerator; -export type MultiFactorError = FirebaseAuthTypes.MultiFactorError; -export type AdditionalUserInfo = FirebaseAuthTypes.AdditionalUserInfo; -export type UserCredential = FirebaseAuthTypes.UserCredential; -export type UserMetadata = FirebaseAuthTypes.UserMetadata; -export type FactorId = FirebaseAuthTypes.FactorId; -export type MultiFactorInfo = FirebaseAuthTypes.MultiFactorInfo; -export type PhoneMultiFactorInfo = FirebaseAuthTypes.PhoneMultiFactorInfo; -export type TotpMultiFactorInfo = FirebaseAuthTypes.TotpMultiFactorInfo; -export type MultiFactorInfoCommon = FirebaseAuthTypes.MultiFactorInfoCommon; -export type MultiFactorAssertion = FirebaseAuthTypes.MultiFactorAssertion; -export type PhoneMultiFactorEnrollInfoOptions = FirebaseAuthTypes.PhoneMultiFactorEnrollInfoOptions; -export type PhoneMultiFactorSignInInfoOptions = FirebaseAuthTypes.PhoneMultiFactorSignInInfoOptions; -export type MultiFactorResolver = FirebaseAuthTypes.MultiFactorResolver; -export type MultiFactorUser = FirebaseAuthTypes.MultiFactorUser; -export type MultiFactor = FirebaseAuthTypes.MultiFactor; -export type UserInfo = FirebaseAuthTypes.UserInfo; -export type IdTokenResult = FirebaseAuthTypes.IdTokenResult; -export type UpdateProfile = FirebaseAuthTypes.UpdateProfile; -export type ConfirmationResult = FirebaseAuthTypes.ConfirmationResult; -export type ActionCodeSettingsAndroid = FirebaseAuthTypes.ActionCodeSettingsAndroid; -export type ActionCodeInfoData = FirebaseAuthTypes.ActionCodeInfoData; -export type ActionCodeInfo = FirebaseAuthTypes.ActionCodeInfo; -export type ActionCodeSettingsIos = FirebaseAuthTypes.ActionCodeSettingsIos; -export type ActionCodeSettings = FirebaseAuthTypes.ActionCodeSettings; -export type AuthListenerCallback = FirebaseAuthTypes.AuthListenerCallback; -export type PhoneAuthSnapshot = FirebaseAuthTypes.PhoneAuthSnapshot; -export type PhoneAuthError = FirebaseAuthTypes.PhoneAuthError; +export interface MultiFactorError extends AuthError { + readonly customData: AuthError['customData'] & { + readonly operationType: (typeof OperationType)[keyof typeof OperationType]; + }; +} export type PhoneAuthListener = FirebaseAuthTypes.PhoneAuthListener; -export type User = FirebaseAuthTypes.User; +export type PhoneAuthError = FirebaseAuthTypes.PhoneAuthError; +export type PhoneAuthSnapshot = FirebaseAuthTypes.PhoneAuthSnapshot; export type ActionCodeURL = FirebaseAuthTypes.ActionCodeURL; -export type getMultiFactorResolver = FirebaseAuthTypes.getMultiFactorResolver; -export type multiFactor = FirebaseAuthTypes.multiFactor; export interface Config { apiKey: string; @@ -97,14 +152,25 @@ export interface ApplicationVerifier { verify(): Promise; } -export type Persistence = { - readonly type: 'SESSION' | 'LOCAL' | 'NONE' | 'COOKIE'; -}; +export type CustomParameters = Record; + +export interface AuthProvider { + readonly providerId: string; +} export interface AuthSettings { appVerificationDisabledForTesting: boolean; } +export interface EmulatorConfig { + readonly protocol: string; + readonly host: string; + readonly port: number | null; + readonly options: { + readonly disableWarnings: boolean; + }; +} + export interface PasswordPolicy { readonly customStrengthOptions: { readonly minPasswordLength?: number; @@ -129,3 +195,160 @@ export interface PasswordValidationStatus { readonly containsNonAlphanumericCharacter?: boolean; readonly passwordPolicy: PasswordPolicy; } + +export interface Persistence { + readonly type: 'SESSION' | 'LOCAL' | 'NONE' | 'COOKIE'; +} + +export type NextOrObserver = NextFn | Observer; + +export interface ParsedToken { + exp?: string; + sub?: string; + auth_time?: string; + iat?: string; + firebase?: { + sign_in_provider?: string; + sign_in_second_factor?: string; + identities?: Record; + }; + [key: string]: unknown; +} + +export type UserProfile = Record; + +export interface AdditionalUserInfo { + readonly isNewUser: boolean; + readonly profile: Record | null; + readonly providerId: string | null; + readonly username?: string | null; +} + +export interface UserInfo { + readonly displayName: string | null; + readonly email: string | null; + readonly phoneNumber: string | null; + readonly photoURL: string | null; + readonly providerId: string; + readonly uid: string; +} + +export interface UserMetadata { + readonly creationTime?: string; + readonly lastSignInTime?: string; +} + +export interface IdTokenResult { + authTime: string; + expirationTime: string; + issuedAtTime: string; + signInProvider: string | null; + signInSecondFactor: string | null; + token: string; + claims: ParsedToken; +} + +export interface User extends UserInfo { + readonly emailVerified: boolean; + readonly isAnonymous: boolean; + readonly metadata: UserMetadata; + readonly providerData: UserInfo[]; + readonly refreshToken: string; + readonly tenantId: string | null; + delete(): Promise; + getIdToken(forceRefresh?: boolean): Promise; + getIdTokenResult(forceRefresh?: boolean): Promise; + reload(): Promise; + toJSON(): object; +} + +export interface UserCredential { + user: User; + providerId: string | null; + operationType: (typeof OperationType)[keyof typeof OperationType]; +} + +export interface ConfirmationResult { + readonly verificationId: string; + confirm(verificationCode: string): Promise; +} + +export interface ActionCodeSettings { + android?: { + installApp?: boolean; + minimumVersion?: string; + packageName: string; + }; + handleCodeInApp?: boolean; + iOS?: { + bundleId: string; + }; + url: string; + dynamicLinkDomain?: string; + linkDomain?: string; +} + +export interface ActionCodeInfo { + data: { + email?: string | null; + multiFactorInfo?: MultiFactorInfo | null; + previousEmail?: string | null; + }; + operation: (typeof ActionCodeOperation)[keyof typeof ActionCodeOperation]; +} + +export interface MultiFactorAssertion { + readonly factorId: (typeof FactorId)[keyof typeof FactorId]; +} + +export interface MultiFactorInfo { + readonly uid: string; + readonly displayName?: string | null; + readonly enrollmentTime: string; + readonly factorId: (typeof FactorId)[keyof typeof FactorId]; +} + +export interface MultiFactorSession {} + +export interface MultiFactorResolver { + readonly hints: MultiFactorInfo[]; + readonly session: MultiFactorSession; + resolveSignIn(assertion: MultiFactorAssertion): Promise; +} + +export interface MultiFactorUser { + readonly enrolledFactors: MultiFactorInfo[]; + getSession(): Promise; + enroll(assertion: MultiFactorAssertion, displayName?: string | null): Promise; + unenroll(option: MultiFactorInfo | string): Promise; +} + +export interface PhoneMultiFactorAssertion extends MultiFactorAssertion {} + +export interface PhoneMultiFactorEnrollInfoOptions { + phoneNumber: string; + session: MultiFactorSession; +} + +export interface PhoneMultiFactorInfo extends MultiFactorInfo { + readonly phoneNumber: string; +} + +export interface PhoneMultiFactorSignInInfoOptions { + multiFactorHint?: MultiFactorInfo; + multiFactorUid?: string; + session: MultiFactorSession; +} + +export interface PhoneSingleFactorInfoOptions { + phoneNumber: string; +} + +export type PhoneInfoOptions = + | PhoneSingleFactorInfoOptions + | PhoneMultiFactorEnrollInfoOptions + | PhoneMultiFactorSignInInfoOptions; + +export interface TotpMultiFactorAssertion extends MultiFactorAssertion {} + +export interface TotpMultiFactorInfo extends MultiFactorInfo {} diff --git a/packages/auth/type-test.ts b/packages/auth/type-test.ts index 32199be75c..1cad47cb8a 100644 --- a/packages/auth/type-test.ts +++ b/packages/auth/type-test.ts @@ -7,6 +7,7 @@ import auth, { firebase, applyActionCode, + ActionCodeOperation, beforeAuthStateChanged, checkActionCode, confirmPasswordReset, @@ -14,6 +15,7 @@ import auth, { createUserWithEmailAndPassword, EmailAuthProvider, fetchSignInMethodsForEmail, + FactorId, getAdditionalUserInfo, getAuth, getCustomAuthDomain, @@ -24,6 +26,7 @@ import auth, { multiFactor, onAuthStateChanged, onIdTokenChanged, + OperationType, parseActionCodeURL, PhoneAuthProvider, sendPasswordResetEmail, @@ -38,6 +41,7 @@ import auth, { signInWithPopup, signInWithRedirect, signOut, + SignInMethod, updateCurrentUser, useDeviceLanguage, useUserAccessGroup, @@ -47,7 +51,6 @@ import auth, { type ActionCodeSettings, type ApplicationVerifier, type Auth, - type AuthCredential, type AuthProvider, type AuthSettings, type Config, @@ -90,11 +93,7 @@ const appVerifier: ApplicationVerifier = { }; const popupRedirectResolver: PopupRedirectResolver = {}; -const redirectProvider: AuthProvider = { - PROVIDER_ID: 'oidc.test', - credential: (token: string | null, secret?: string) => - ({ token, secret, providerId: 'oidc.test' }) as AuthCredential, -}; +const redirectProvider = { providerId: 'oidc.test' } as AuthProvider; const authSettings: AuthSettings = { appVerificationDisabledForTesting: true }; const persistence: Persistence = { type: 'NONE' }; const authConfig: Config = { @@ -123,6 +122,12 @@ console.log(authSettings.appVerificationDisabledForTesting); console.log(authConfig.apiHost); console.log(dependencies.persistence); console.log(passwordValidationStatus.passwordPolicy.enforcementState); +console.log( + ActionCodeOperation.VERIFY_EMAIL, + FactorId.PHONE, + OperationType.SIGN_IN, + SignInMethod.EMAIL_LINK, +); const modularAuth: Auth = getAuth(); const modularAuthFromApp: Auth = getAuth(firebase.app()); From 4c2efa4c014e566a36c1f8ddd4fd777ea6b38bd7 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 23 Apr 2026 15:23:21 +0100 Subject: [PATCH 08/45] chore: remove unneeded modular/index.ts --- packages/auth/lib/modular/index.ts | 1 - 1 file changed, 1 deletion(-) delete mode 100644 packages/auth/lib/modular/index.ts diff --git a/packages/auth/lib/modular/index.ts b/packages/auth/lib/modular/index.ts deleted file mode 100644 index a5749ac7cf..0000000000 --- a/packages/auth/lib/modular/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from '../modular'; From d68dadcb520c84856924d711c61eeb60fbeff858 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 23 Apr 2026 16:39:24 +0100 Subject: [PATCH 09/45] refactor: some runtimes moved to modular, fixed up compare script --- .../compare-types/packages/auth/config.ts | 60 +++++++++++-------- packages/auth/lib/PhoneAuthState.ts | 22 +++++++ packages/auth/lib/index.ts | 55 +---------------- packages/auth/lib/modular.ts | 29 +++++++++ packages/auth/lib/namespaced.ts | 23 +------ 5 files changed, 89 insertions(+), 100 deletions(-) create mode 100644 packages/auth/lib/PhoneAuthState.ts diff --git a/.github/scripts/compare-types/packages/auth/config.ts b/.github/scripts/compare-types/packages/auth/config.ts index 6a17cf4153..df89feb97c 100644 --- a/.github/scripts/compare-types/packages/auth/config.ts +++ b/.github/scripts/compare-types/packages/auth/config.ts @@ -52,21 +52,6 @@ const config: PackageConfig = { reason: 'RN Firebase does not yet expose the firebase-js-sdk EmailAuthCredential class as part of the modular public surface.', }, - { - name: 'FacebookAuthProvider', - reason: - 'This provider class is still only reachable through the legacy namespaced export path, not the modular compare-types surface.', - }, - { - name: 'GithubAuthProvider', - reason: - 'This provider class is still only reachable through the legacy namespaced export path, not the modular compare-types surface.', - }, - { - name: 'GoogleAuthProvider', - reason: - 'This provider class is still only reachable through the legacy namespaced export path, not the modular compare-types surface.', - }, { name: 'indexedDBLocalPersistence', reason: @@ -92,11 +77,6 @@ const config: PackageConfig = { reason: 'RN Firebase does not yet expose the firebase-js-sdk PhoneAuthCredential class as part of the modular public surface.', }, - { - name: 'PhoneAuthProvider', - reason: - 'This provider class is still only reachable through the legacy namespaced export path, not the modular compare-types surface.', - }, { name: 'prodErrorMap', reason: @@ -121,19 +101,24 @@ const config: PackageConfig = { reason: 'SAMLAuthProvider is not yet surfaced on the RN Firebase modular/public auth surface.', }, - { - name: 'TwitterAuthProvider', - reason: - 'This provider class is still only reachable through the legacy namespaced export path, not the modular compare-types surface.', - }, ], extraInRN: [ + { + name: 'AppleAuthProvider', + reason: + 'RN Firebase-specific Apple auth provider helper exposed for native Sign in with Apple flows; the firebase-js-sdk does not export a separate AppleAuthProvider class.', + }, { name: 'NativeFirebaseAuthError', reason: 'RN Firebase-specific native bridge auth error type used in place of the firebase-js-sdk AuthError export.', }, + { + name: 'OIDCAuthProvider', + reason: + 'RN Firebase-specific OIDC auth provider class retained for compatibility with the existing public package surface; the firebase-js-sdk exposes OAuthProvider instead of a separate OIDCAuthProvider class.', + }, { name: 'OIDCProvider', reason: @@ -215,11 +200,36 @@ const config: PackageConfig = { reason: 'The public Auth surface now matches structurally, but the emitted declaration text still differs from the firebase-js-sdk because RN Firebase uses its local FirebaseApp and NextOrObserver spellings in the generated interface.', }, + { + name: 'FacebookAuthProvider', + reason: + 'RN Firebase now exports FacebookAuthProvider from the modular surface, but its native helper class only exposes the credential factory used by RNFB and does not yet mirror the firebase-js-sdk static fields and credentialFromResult/credentialFromError helpers.', + }, + { + name: 'GithubAuthProvider', + reason: + 'RN Firebase now exports GithubAuthProvider from the modular surface, but its native helper class only exposes the credential factory used by RNFB and does not yet mirror the firebase-js-sdk static fields and credentialFromResult/credentialFromError helpers.', + }, + { + name: 'GoogleAuthProvider', + reason: + 'RN Firebase now exports GoogleAuthProvider from the modular surface, but its native helper class only exposes the credential factory used by RNFB and does not yet mirror the firebase-js-sdk static fields and credentialFromResult/credentialFromError helpers.', + }, { name: 'ParsedToken', reason: 'TypeScript emits the parsed-token property keys without quotes in the generated declaration file, so compare-types reports a text-only difference even though the property set matches the firebase-js-sdk surface.', }, + { + name: 'PhoneAuthProvider', + reason: + 'RN Firebase now exports PhoneAuthProvider from the modular surface, but the native helper class still exposes a reduced static API and looser signatures than the firebase-js-sdk PhoneAuthProvider class.', + }, + { + name: 'TwitterAuthProvider', + reason: + 'RN Firebase now exports TwitterAuthProvider from the modular surface, but its native helper class only exposes the credential factory used by RNFB and does not yet mirror the firebase-js-sdk static fields and credentialFromResult/credentialFromError helpers.', + }, ], }; diff --git a/packages/auth/lib/PhoneAuthState.ts b/packages/auth/lib/PhoneAuthState.ts new file mode 100644 index 0000000000..9e06b8c3e6 --- /dev/null +++ b/packages/auth/lib/PhoneAuthState.ts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2016-present Invertase Limited & Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this library 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 const PhoneAuthState = { + CODE_SENT: 'sent', + AUTO_VERIFY_TIMEOUT: 'timeout', + AUTO_VERIFIED: 'verified', + ERROR: 'error', +} as const; diff --git a/packages/auth/lib/index.ts b/packages/auth/lib/index.ts index f32f9659d6..9d8a4d6410 100644 --- a/packages/auth/lib/index.ts +++ b/packages/auth/lib/index.ts @@ -41,59 +41,8 @@ export { SignInMethod, } from './types/auth'; -export type { - ActionCodeInfo, - ActionCodeSettings, - ActionCodeURL, - AdditionalUserInfo, - ApplicationVerifier, - Auth, - AuthError, - AuthErrorMap, - AuthCredential, - AuthProvider, - AuthSettings, - CompleteFn, - Config, - ConfirmationResult, - Dependencies, - EmulatorConfig, - ErrorFn, - IdTokenResult, - MultiFactorAssertion, - MultiFactorError, - MultiFactorInfo, - MultiFactorResolver, - MultiFactorSession, - MultiFactorUser, - NativeFirebaseAuthError, - NextOrObserver, - NextFn, - OIDCProvider, - ParsedToken, - PasswordPolicy, - PasswordValidationStatus, - Persistence, - PhoneAuthError, - PhoneInfoOptions, - PhoneAuthListener, - PhoneAuthSnapshot, - PhoneMultiFactorAssertion, - PhoneMultiFactorEnrollInfoOptions, - PhoneMultiFactorInfo, - PhoneMultiFactorSignInInfoOptions, - PhoneSingleFactorInfoOptions, - PopupRedirectResolver, - TotpMultiFactorAssertion, - TotpMultiFactorInfo, - User, - UserCredential, - UserInfo, - UserMetadata, - UserProfile, - Unsubscribe, -} from './types/auth'; +export type * from './types/auth'; export * from './types/namespaced'; export * from './modular'; -export * from './namespaced'; +export { SDK_VERSION, firebase } from './namespaced'; export { default } from './namespaced'; diff --git a/packages/auth/lib/modular.ts b/packages/auth/lib/modular.ts index 2f39f657cf..ce859b4f76 100644 --- a/packages/auth/lib/modular.ts +++ b/packages/auth/lib/modular.ts @@ -16,7 +16,20 @@ import { getApp } from '@react-native-firebase/app'; import { MODULAR_DEPRECATION_ARG } from '@react-native-firebase/app/dist/module/common'; +import PhoneMultiFactorGenerator from './PhoneMultiFactorGenerator'; +import { PhoneAuthState } from './PhoneAuthState'; +import TotpMultiFactorGenerator from './TotpMultiFactorGenerator'; +import { TotpSecret } from './TotpSecret'; import { MultiFactorUser as MultiFactorUserModule } from './multiFactor'; +import AppleAuthProvider from './providers/AppleAuthProvider'; +import EmailAuthProvider from './providers/EmailAuthProvider'; +import FacebookAuthProvider from './providers/FacebookAuthProvider'; +import GithubAuthProvider from './providers/GithubAuthProvider'; +import GoogleAuthProvider from './providers/GoogleAuthProvider'; +import OAuthProvider from './providers/OAuthProvider'; +import OIDCAuthProvider from './providers/OIDCAuthProvider'; +import PhoneAuthProvider from './providers/PhoneAuthProvider'; +import TwitterAuthProvider from './providers/TwitterAuthProvider'; import type { FirebaseApp } from '@react-native-firebase/app'; import type { ActionCodeInfo, @@ -98,6 +111,22 @@ function asUser(promise: Promise): Promise { return promise as unknown as Promise; } +export { + AppleAuthProvider, + EmailAuthProvider, + FacebookAuthProvider, + GithubAuthProvider, + GoogleAuthProvider, + OAuthProvider, + OIDCAuthProvider, + PhoneAuthProvider, + PhoneAuthState, + PhoneMultiFactorGenerator, + TotpMultiFactorGenerator, + TotpSecret, + TwitterAuthProvider, +}; + function normalizeAuthListener( nextOrObserver: NextOrObserver, ): FirebaseAuthTypes.AuthListenerCallback | { next: FirebaseAuthTypes.AuthListenerCallback } { diff --git a/packages/auth/lib/namespaced.ts b/packages/auth/lib/namespaced.ts index c3a9544574..2776035c7f 100644 --- a/packages/auth/lib/namespaced.ts +++ b/packages/auth/lib/namespaced.ts @@ -34,6 +34,7 @@ import { type ModuleConfig, } from '@react-native-firebase/app/dist/module/internal'; import ConfirmationResult from './ConfirmationResult'; +import { PhoneAuthState } from './PhoneAuthState'; import PhoneAuthListener from './PhoneAuthListener'; import PhoneMultiFactorGenerator from './PhoneMultiFactorGenerator'; import TotpMultiFactorGenerator from './TotpMultiFactorGenerator'; @@ -75,30 +76,8 @@ type AuthErrorWithCodeInternal = Error & { code?: string; }; -const PhoneAuthState = { - CODE_SENT: 'sent', - AUTO_VERIFY_TIMEOUT: 'timeout', - AUTO_VERIFIED: 'verified', - ERROR: 'error', -} as const; - const nativeEvents = ['auth_state_changed', 'auth_id_token_changed', 'phone_auth_state_changed']; -export { - AppleAuthProvider, - EmailAuthProvider, - PhoneAuthProvider, - GoogleAuthProvider, - GithubAuthProvider, - TwitterAuthProvider, - FacebookAuthProvider, - PhoneMultiFactorGenerator, - TotpMultiFactorGenerator, - TotpSecret, - OAuthProvider, - OIDCAuthProvider, - PhoneAuthState, -}; const statics = { AppleAuthProvider, From abc34479096b85e58055604b1542277b3afe9b9a Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 24 Apr 2026 11:00:28 +0100 Subject: [PATCH 10/45] fix: remove duplicate type aliases --- .../compare-types/packages/auth/config.ts | 25 +++++++++++++++++++ packages/auth/lib/namespaced.ts | 2 -- packages/auth/lib/types/auth.ts | 6 ----- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/.github/scripts/compare-types/packages/auth/config.ts b/.github/scripts/compare-types/packages/auth/config.ts index df89feb97c..607660ae48 100644 --- a/.github/scripts/compare-types/packages/auth/config.ts +++ b/.github/scripts/compare-types/packages/auth/config.ts @@ -170,6 +170,11 @@ const config: PackageConfig = { reason: 'RN Firebase models disableWarnings as an optional property, while the firebase-js-sdk emitted type text shows a required boolean property.', }, + { + name: 'EmailAuthProvider', + reason: + 'RN Firebase now exports EmailAuthProvider from the modular surface, but its native helper class still exposes a reduced static API and RNFB credential objects rather than mirroring the firebase-js-sdk EmailAuthProvider class shape.', + }, { name: 'isSignInWithEmailLink', reason: @@ -215,6 +220,11 @@ const config: PackageConfig = { reason: 'RN Firebase now exports GoogleAuthProvider from the modular surface, but its native helper class only exposes the credential factory used by RNFB and does not yet mirror the firebase-js-sdk static fields and credentialFromResult/credentialFromError helpers.', }, + { + name: 'OAuthProvider', + reason: + 'RN Firebase now exports OAuthProvider from the modular surface, but its native helper class still differs from the firebase-js-sdk class by exposing RNFB-specific credential construction and omitting credentialFromJSON/credentialFromResult/credentialFromError helpers.', + }, { name: 'ParsedToken', reason: @@ -225,6 +235,21 @@ const config: PackageConfig = { reason: 'RN Firebase now exports PhoneAuthProvider from the modular surface, but the native helper class still exposes a reduced static API and looser signatures than the firebase-js-sdk PhoneAuthProvider class.', }, + { + name: 'PhoneMultiFactorGenerator', + reason: + 'RN Firebase now exports PhoneMultiFactorGenerator from the modular surface, but its helper class still returns RNFB credential/assertion shapes rather than the firebase-js-sdk PhoneMultiFactorGenerator static API exactly.', + }, + { + name: 'TotpMultiFactorGenerator', + reason: + 'RN Firebase now exports TotpMultiFactorGenerator from the modular surface, but its helper class still differs from the firebase-js-sdk static API in signatures and returned assertion/secret shapes.', + }, + { + name: 'TotpSecret', + reason: + 'RN Firebase now exports TotpSecret from the modular surface, but the native-backed helper class exposes a reduced field set plus async/native helper methods that do not match the firebase-js-sdk TotpSecret class shape.', + }, { name: 'TwitterAuthProvider', reason: diff --git a/packages/auth/lib/namespaced.ts b/packages/auth/lib/namespaced.ts index 2776035c7f..eb14bafb9e 100644 --- a/packages/auth/lib/namespaced.ts +++ b/packages/auth/lib/namespaced.ts @@ -51,7 +51,6 @@ import OAuthProvider from './providers/OAuthProvider'; import OIDCAuthProvider from './providers/OIDCAuthProvider'; import PhoneAuthProvider from './providers/PhoneAuthProvider'; import TwitterAuthProvider from './providers/TwitterAuthProvider'; -import { TotpSecret } from './TotpSecret'; import { version } from './version'; import fallBackModule from './web/RNFBAuthModule'; import { PasswordPolicyMixin } from './password-policy/PasswordPolicyMixin'; @@ -78,7 +77,6 @@ type AuthErrorWithCodeInternal = Error & { const nativeEvents = ['auth_state_changed', 'auth_id_token_changed', 'phone_auth_state_changed']; - const statics = { AppleAuthProvider, EmailAuthProvider, diff --git a/packages/auth/lib/types/auth.ts b/packages/auth/lib/types/auth.ts index f20117b657..084435779d 100644 --- a/packages/auth/lib/types/auth.ts +++ b/packages/auth/lib/types/auth.ts @@ -111,13 +111,7 @@ export interface AuthError extends ReactNativeFirebase.NativeFirebaseError { export type NativeFirebaseAuthError = FirebaseAuthTypes.NativeFirebaseAuthError; export type AuthCredential = FirebaseAuthTypes.AuthCredential; -export type OAuthProvider = FirebaseAuthTypes.OAuthProvider; export type OIDCProvider = FirebaseAuthTypes.OIDCProvider; -export type EmailAuthProvider = FirebaseAuthTypes.EmailAuthProvider; -export type PhoneAuthState = FirebaseAuthTypes.PhoneAuthState; -export type PhoneMultiFactorGenerator = FirebaseAuthTypes.PhoneMultiFactorGenerator; -export type TotpSecret = FirebaseAuthTypes.TotpSecret; -export type TotpMultiFactorGenerator = FirebaseAuthTypes.TotpMultiFactorGenerator; export interface MultiFactorError extends AuthError { readonly customData: AuthError['customData'] & { readonly operationType: (typeof OperationType)[keyof typeof OperationType]; From 6dab56b96cff241c29ce51fca5728cf50e636edc Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 24 Apr 2026 11:13:30 +0100 Subject: [PATCH 11/45] fix: clean up auth index.ts exports --- packages/auth/lib/index.ts | 34 +++++----------------------------- 1 file changed, 5 insertions(+), 29 deletions(-) diff --git a/packages/auth/lib/index.ts b/packages/auth/lib/index.ts index 9d8a4d6410..37b41812c2 100644 --- a/packages/auth/lib/index.ts +++ b/packages/auth/lib/index.ts @@ -14,35 +14,11 @@ * limitations under the License. * */ - -export type FirebaseApp = import('@react-native-firebase/app').ReactNativeFirebase.FirebaseApp; -export type Observer = { - next?: ((value: T) => void) | null; - error?: ((error: Error) => void) | null; - complete?: (() => void) | null; -}; -export type ActionCodeInfoData = import('./types/namespaced').FirebaseAuthTypes.ActionCodeInfoData; -export type ActionCodeSettingsAndroid = - import('./types/namespaced').FirebaseAuthTypes.ActionCodeSettingsAndroid; -export type ActionCodeSettingsIos = - import('./types/namespaced').FirebaseAuthTypes.ActionCodeSettingsIos; -export type AuthListenerCallback = - import('./types/namespaced').FirebaseAuthTypes.AuthListenerCallback; -export type MultiFactor = import('./types/namespaced').FirebaseAuthTypes.MultiFactor; -export type MultiFactorInfoCommon = - import('./types/namespaced').FirebaseAuthTypes.MultiFactorInfoCommon; -export type UpdateProfile = import('./types/namespaced').FirebaseAuthTypes.UpdateProfile; - -export { - ActionCodeOperation, - FactorId, - OperationType, - ProviderId, - SignInMethod, -} from './types/auth'; - +// modular API export type * from './types/auth'; -export * from './types/namespaced'; export * from './modular'; -export { SDK_VERSION, firebase } from './namespaced'; + +// namespaced API +export * from './types/namespaced'; +export * from './namespaced'; export { default } from './namespaced'; From 95d2de3c97ff6b762ae51f3d5deb3daac86ad295 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 24 Apr 2026 11:28:06 +0100 Subject: [PATCH 12/45] fix: password policy to use TS --- .../lib/password-policy/PasswordPolicyImpl.ts | 57 ++++++++++++------- .../password-policy/PasswordPolicyMixin.ts | 34 ++++++++--- .../lib/password-policy/passwordPolicyApi.ts | 37 ++++++++---- packages/auth/lib/types/internal.ts | 35 +++++++++++- 4 files changed, 122 insertions(+), 41 deletions(-) diff --git a/packages/auth/lib/password-policy/PasswordPolicyImpl.ts b/packages/auth/lib/password-policy/PasswordPolicyImpl.ts index 6613758106..77c84b732b 100644 --- a/packages/auth/lib/password-policy/PasswordPolicyImpl.ts +++ b/packages/auth/lib/password-policy/PasswordPolicyImpl.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -16,6 +15,13 @@ * */ +import type { + PasswordPolicyCustomStrengthOptionsInternal, + PasswordPolicyInternal, + PasswordPolicyResponseInternal, + PasswordValidationStatusInternal, +} from '../types/internal'; + // Minimum min password length enforced by the backend, even if no minimum length is set. const MINIMUM_MIN_PASSWORD_LENGTH = 6; @@ -24,14 +30,20 @@ const MINIMUM_MIN_PASSWORD_LENGTH = 6; * * @internal */ -export class PasswordPolicyImpl { - constructor(response) { +export class PasswordPolicyImpl implements PasswordPolicyInternal { + customStrengthOptions: PasswordPolicyCustomStrengthOptionsInternal; + allowedNonAlphanumericCharacters: string; + enforcementState: string; + forceUpgradeOnSignin: boolean; + schemaVersion: number; + + constructor(response: PasswordPolicyResponseInternal) { // Only include custom strength options defined in the response. - const responseOptions = response.customStrengthOptions; + const responseOptions = response.customStrengthOptions ?? {}; this.customStrengthOptions = {}; this.customStrengthOptions.minPasswordLength = responseOptions.minPasswordLength ?? MINIMUM_MIN_PASSWORD_LENGTH; - if (responseOptions.maxPasswordLength) { + if (responseOptions.maxPasswordLength !== undefined) { this.customStrengthOptions.maxPasswordLength = responseOptions.maxPasswordLength; } if (responseOptions.containsLowercaseCharacter !== undefined) { @@ -54,7 +66,7 @@ export class PasswordPolicyImpl { this.enforcementState = response.enforcementState === 'ENFORCEMENT_STATE_UNSPECIFIED' ? 'OFF' - : response.enforcementState; + : (response.enforcementState ?? 'OFF'); // Use an empty string if no non-alphanumeric characters are specified in the response. this.allowedNonAlphanumericCharacters = @@ -64,8 +76,8 @@ export class PasswordPolicyImpl { this.schemaVersion = response.schemaVersion; } - validatePassword(password): any { - const status = { + validatePassword(password: string): PasswordValidationStatusInternal { + const status: PasswordValidationStatusInternal = { isValid: true, passwordPolicy: this, }; @@ -83,18 +95,24 @@ export class PasswordPolicyImpl { return status; } - validatePasswordLengthOptions(password, status) { + private validatePasswordLengthOptions( + password: string, + status: PasswordValidationStatusInternal, + ): void { const minPasswordLength = this.customStrengthOptions.minPasswordLength; const maxPasswordLength = this.customStrengthOptions.maxPasswordLength; - if (minPasswordLength) { + if (minPasswordLength !== undefined) { status.meetsMinPasswordLength = password.length >= minPasswordLength; } - if (maxPasswordLength) { + if (maxPasswordLength !== undefined) { status.meetsMaxPasswordLength = password.length <= maxPasswordLength; } } - validatePasswordCharacterOptions(password, status) { + private validatePasswordCharacterOptions( + password: string, + status: PasswordValidationStatusInternal, + ): void { this.updatePasswordCharacterOptionsStatuses(status, false, false, false, false); for (let i = 0; i < password.length; i++) { @@ -109,13 +127,13 @@ export class PasswordPolicyImpl { } } - updatePasswordCharacterOptionsStatuses( - status, - containsLowercaseCharacter, - containsUppercaseCharacter, - containsNumericCharacter, - containsNonAlphanumericCharacter, - ) { + private updatePasswordCharacterOptionsStatuses( + status: PasswordValidationStatusInternal, + containsLowercaseCharacter: boolean, + containsUppercaseCharacter: boolean, + containsNumericCharacter: boolean, + containsNonAlphanumericCharacter: boolean, + ): void { if (this.customStrengthOptions.containsLowercaseLetter) { status.containsLowercaseLetter ||= containsLowercaseCharacter; } @@ -130,4 +148,3 @@ export class PasswordPolicyImpl { } } } -export default PasswordPolicyImpl; diff --git a/packages/auth/lib/password-policy/PasswordPolicyMixin.ts b/packages/auth/lib/password-policy/PasswordPolicyMixin.ts index db6eeb091d..803073eab0 100644 --- a/packages/auth/lib/password-policy/PasswordPolicyMixin.ts +++ b/packages/auth/lib/password-policy/PasswordPolicyMixin.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -18,23 +17,32 @@ import { fetchPasswordPolicy } from './passwordPolicyApi'; import { PasswordPolicyImpl } from './PasswordPolicyImpl'; +import type { + PasswordPolicyHostInternal, + PasswordPolicyInternal, + PasswordPolicyMixinInternal, + PasswordValidationStatusInternal, +} from '../types/internal'; const EXPECTED_PASSWORD_POLICY_SCHEMA_VERSION = 1; +type PasswordPolicyMixinTarget = PasswordPolicyHostInternal & PasswordPolicyMixinInternal; +type PasswordPolicyMixinShape = PasswordPolicyMixinInternal & ThisType; + /** * Password policy mixin - provides password policy caching and validation. * Expects the target object to have: _tenantId, _projectPasswordPolicy, * _tenantPasswordPolicies, and app.options.apiKey */ -export const PasswordPolicyMixin = { - _getPasswordPolicyInternal() { +export const PasswordPolicyMixin: PasswordPolicyMixinShape = { + _getPasswordPolicyInternal(): PasswordPolicyInternal | null { if (this._tenantId === null) { return this._projectPasswordPolicy; } - return this._tenantPasswordPolicies[this._tenantId]; + return this._tenantPasswordPolicies[this._tenantId] ?? null; }, - async _updatePasswordPolicy() { + async _updatePasswordPolicy(): Promise { const response = await fetchPasswordPolicy(this); const passwordPolicy = new PasswordPolicyImpl(response); if (this._tenantId === null) { @@ -44,17 +52,25 @@ export const PasswordPolicyMixin = { } }, - async _recachePasswordPolicy() { + async _recachePasswordPolicy(): Promise { if (this._getPasswordPolicyInternal()) { await this._updatePasswordPolicy(); } }, - async validatePassword(password) { - if (!this._getPasswordPolicyInternal()) { + async validatePassword(password: string): Promise { + let passwordPolicy = this._getPasswordPolicyInternal(); + + if (!passwordPolicy) { await this._updatePasswordPolicy(); + passwordPolicy = this._getPasswordPolicyInternal(); + } + + if (!passwordPolicy) { + throw new Error( + 'firebase.auth().validatePassword(*) Failed to load password policy for validation.', + ); } - const passwordPolicy = this._getPasswordPolicyInternal(); if (passwordPolicy.schemaVersion !== EXPECTED_PASSWORD_POLICY_SCHEMA_VERSION) { throw new Error( diff --git a/packages/auth/lib/password-policy/passwordPolicyApi.ts b/packages/auth/lib/password-policy/passwordPolicyApi.ts index 77cd2341c5..c61623b8a8 100644 --- a/packages/auth/lib/password-policy/passwordPolicyApi.ts +++ b/packages/auth/lib/password-policy/passwordPolicyApi.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -16,6 +15,16 @@ * */ +import type { PasswordPolicyHostInternal, PasswordPolicyResponseInternal } from '../types/internal'; + +function getErrorMessage(error: unknown): string { + if (error instanceof Error) { + return error.message; + } + + return String(error); +} + /** * Performs an API request to Firebase Console to get password policy json. * @@ -23,23 +32,29 @@ * @returns {Promise} A promise that resolves to the API response. * @throws {Error} Throws an error if the request fails or encounters an issue. */ -export async function fetchPasswordPolicy(auth) { +export async function fetchPasswordPolicy( + auth: PasswordPolicyHostInternal, +): Promise { + let response: Response; + try { // Identity toolkit API endpoint for password policy. Ensure this is enabled on Google cloud. const baseURL = 'https://identitytoolkit.googleapis.com/v2/passwordPolicy?key='; const apiKey = auth.app.options.apiKey; - const response = await fetch(`${baseURL}${apiKey}`); - if (!response.ok) { - const errorDetails = await response.text(); - throw new Error( - `firebase.auth().validatePassword(*) failed to fetch password policy from Firebase Console: ${response.statusText}. Details: ${errorDetails}`, - ); - } - return await response.json(); + response = await fetch(`${baseURL}${apiKey}`); } catch (error) { throw new Error( - `firebase.auth().validatePassword(*) Failed to fetch password policy: ${error.message}`, + `firebase.auth().validatePassword(*) Failed to fetch password policy: ${getErrorMessage(error)}`, ); } + + if (!response.ok) { + const errorDetails = await response.text(); + throw new Error( + `firebase.auth().validatePassword(*) failed to fetch password policy from Firebase Console: ${response.statusText}. Details: ${errorDetails}`, + ); + } + + return (await response.json()) as PasswordPolicyResponseInternal; } diff --git a/packages/auth/lib/types/internal.ts b/packages/auth/lib/types/internal.ts index 36fc9819db..c3f582b46d 100644 --- a/packages/auth/lib/types/internal.ts +++ b/packages/auth/lib/types/internal.ts @@ -82,7 +82,40 @@ export type AuthNativeEventInternal = | AuthIdTokenChangedEventInternal | PhoneAuthStateChangedEventInternal; -export type PasswordPolicyInternal = FirebaseAuthTypes.PasswordPolicy; +export interface PasswordPolicyCustomStrengthOptionsInternal { + minPasswordLength?: number; + maxPasswordLength?: number; + containsLowercaseLetter?: boolean; + containsUppercaseLetter?: boolean; + containsNumericCharacter?: boolean; + containsNonAlphanumericCharacter?: boolean; +} + +export interface PasswordPolicyInternal { + readonly customStrengthOptions: PasswordPolicyCustomStrengthOptionsInternal; + readonly allowedNonAlphanumericCharacters: string; + readonly enforcementState: string; + readonly forceUpgradeOnSignin: boolean; + readonly schemaVersion: number; + validatePassword(password: string): PasswordValidationStatusInternal; +} + +export interface PasswordPolicyResponseCustomStrengthOptionsInternal { + minPasswordLength?: number; + maxPasswordLength?: number; + containsLowercaseCharacter?: boolean; + containsUppercaseCharacter?: boolean; + containsNumericCharacter?: boolean; + containsNonAlphanumericCharacter?: boolean; +} + +export interface PasswordPolicyResponseInternal { + customStrengthOptions?: PasswordPolicyResponseCustomStrengthOptionsInternal; + allowedNonAlphanumericCharacters?: string[]; + enforcementState?: string; + forceUpgradeOnSignin?: boolean; + schemaVersion: number; +} export type PasswordValidationStatusInternal = { isValid: boolean; From e861fb949fb455de515c7b0b27ec5a1f1e33ef1d Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 24 Apr 2026 13:14:38 +0100 Subject: [PATCH 13/45] fix: update types for auth providers --- .../auth/lib/providers/AppleAuthProvider.ts | 9 ++- .../auth/lib/providers/EmailAuthProvider.ts | 11 +-- .../lib/providers/FacebookAuthProvider.ts | 9 ++- .../auth/lib/providers/GithubAuthProvider.ts | 7 +- .../auth/lib/providers/GoogleAuthProvider.ts | 9 ++- packages/auth/lib/providers/OAuthProvider.ts | 45 ++++++----- .../auth/lib/providers/OIDCAuthProvider.ts | 9 ++- .../auth/lib/providers/PhoneAuthProvider.ts | 80 +++++++++++++++++-- .../auth/lib/providers/TwitterAuthProvider.ts | 7 +- 9 files changed, 129 insertions(+), 57 deletions(-) diff --git a/packages/auth/lib/providers/AppleAuthProvider.ts b/packages/auth/lib/providers/AppleAuthProvider.ts index d0d1fc5fa2..5e1b46630d 100644 --- a/packages/auth/lib/providers/AppleAuthProvider.ts +++ b/packages/auth/lib/providers/AppleAuthProvider.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -16,7 +15,9 @@ * */ -const providerId = 'apple.com'; +import type { AuthCredential } from '../types/auth'; + +const providerId = 'apple.com' as const; export default class AppleAuthProvider { constructor() { @@ -27,10 +28,10 @@ export default class AppleAuthProvider { return providerId; } - static credential(token, secret) { + static credential(token: string, secret?: string): AuthCredential { return { token, - secret, + secret: secret ?? '', providerId, }; } diff --git a/packages/auth/lib/providers/EmailAuthProvider.ts b/packages/auth/lib/providers/EmailAuthProvider.ts index e69dd0ff2b..de1a28cdbe 100644 --- a/packages/auth/lib/providers/EmailAuthProvider.ts +++ b/packages/auth/lib/providers/EmailAuthProvider.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -16,8 +15,10 @@ * */ -const linkProviderId = 'emailLink'; -const passwordProviderId = 'password'; +import type { AuthCredential } from '../types/auth'; + +const linkProviderId = 'emailLink' as const; +const passwordProviderId = 'password' as const; export default class EmailAuthProvider { constructor() { @@ -36,7 +37,7 @@ export default class EmailAuthProvider { return passwordProviderId; } - static credential(email, password) { + static credential(email: string, password: string): AuthCredential { return { token: email, secret: password, @@ -44,7 +45,7 @@ export default class EmailAuthProvider { }; } - static credentialWithLink(email, emailLink) { + static credentialWithLink(email: string, emailLink: string): AuthCredential { return { token: email, secret: emailLink, diff --git a/packages/auth/lib/providers/FacebookAuthProvider.ts b/packages/auth/lib/providers/FacebookAuthProvider.ts index ab73c1c5c7..220d461a11 100644 --- a/packages/auth/lib/providers/FacebookAuthProvider.ts +++ b/packages/auth/lib/providers/FacebookAuthProvider.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -16,7 +15,9 @@ * */ -const providerId = 'facebook.com'; +import type { AuthCredential } from '../types/auth'; + +const providerId = 'facebook.com' as const; export default class FacebookAuthProvider { constructor() { @@ -27,10 +28,10 @@ export default class FacebookAuthProvider { return providerId; } - static credential(token, secret = '') { + static credential(token: string, secret?: string): AuthCredential { return { token, - secret, + secret: secret ?? '', providerId, }; } diff --git a/packages/auth/lib/providers/GithubAuthProvider.ts b/packages/auth/lib/providers/GithubAuthProvider.ts index 39e7348655..af74e2234a 100644 --- a/packages/auth/lib/providers/GithubAuthProvider.ts +++ b/packages/auth/lib/providers/GithubAuthProvider.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -16,7 +15,9 @@ * */ -const providerId = 'github.com'; +import type { AuthCredential } from '../types/auth'; + +const providerId = 'github.com' as const; export default class GithubAuthProvider { constructor() { @@ -27,7 +28,7 @@ export default class GithubAuthProvider { return providerId; } - static credential(token) { + static credential(token: string): AuthCredential { return { token, secret: '', diff --git a/packages/auth/lib/providers/GoogleAuthProvider.ts b/packages/auth/lib/providers/GoogleAuthProvider.ts index eb695afc36..3bcb8b6d6a 100644 --- a/packages/auth/lib/providers/GoogleAuthProvider.ts +++ b/packages/auth/lib/providers/GoogleAuthProvider.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -16,7 +15,9 @@ * */ -const providerId = 'google.com'; +import type { AuthCredential } from '../types/auth'; + +const providerId = 'google.com' as const; export default class GoogleAuthProvider { constructor() { @@ -27,10 +28,10 @@ export default class GoogleAuthProvider { return providerId; } - static credential(token, secret) { + static credential(token: string, secret?: string): AuthCredential { return { token, - secret, + secret: secret ?? '', providerId, }; } diff --git a/packages/auth/lib/providers/OAuthProvider.ts b/packages/auth/lib/providers/OAuthProvider.ts index ce20fd3ccf..d7c5ea99f2 100644 --- a/packages/auth/lib/providers/OAuthProvider.ts +++ b/packages/auth/lib/providers/OAuthProvider.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -16,56 +15,58 @@ * */ +import type { AuthCredential, CustomParameters } from '../types/auth'; + export default class OAuthProvider { /** @internal */ - #providerId = null; + private providerId: string; /** @internal */ - #customParameters = {}; + private customParameters: CustomParameters = {}; /** @internal */ - #scopes = []; + private scopes: string[] = []; - constructor(providerId) { - this.#providerId = providerId; + constructor(providerId: string) { + this.providerId = providerId; } - static credential(idToken, accessToken) { + static credential(idToken: string, accessToken?: string): AuthCredential { return { token: idToken, - secret: accessToken, + secret: accessToken ?? '', providerId: 'oauth', }; } get PROVIDER_ID() { - return this.#providerId; + return this.providerId; } - setCustomParameters(customOAuthParameters) { - this.#customParameters = customOAuthParameters; + setCustomParameters(customOAuthParameters: CustomParameters): OAuthProvider { + this.customParameters = customOAuthParameters; return this; } - getCustomParameters() { - return this.#customParameters; + getCustomParameters(): CustomParameters { + return this.customParameters; } - addScope(scope) { - if (!this.#scopes.includes(scope)) { - this.#scopes.push(scope); + addScope(scope: string): OAuthProvider { + if (!this.scopes.includes(scope)) { + this.scopes.push(scope); } return this; } - getScopes() { - return [...this.#scopes]; + getScopes(): string[] { + return [...this.scopes]; } /** @internal */ - toObject() { + toObject(): { providerId: string; scopes: string[]; customParameters: CustomParameters } { return { - providerId: this.#providerId, - scopes: this.#scopes, - customParameters: this.#customParameters, + providerId: this.providerId, + scopes: this.scopes, + customParameters: this.customParameters, }; } } diff --git a/packages/auth/lib/providers/OIDCAuthProvider.ts b/packages/auth/lib/providers/OIDCAuthProvider.ts index ce1a7eb2aa..37fb1e35a7 100644 --- a/packages/auth/lib/providers/OIDCAuthProvider.ts +++ b/packages/auth/lib/providers/OIDCAuthProvider.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -16,7 +15,9 @@ * */ -const providerId = 'oidc.'; +import type { AuthCredential } from '../types/auth'; + +const providerId = 'oidc.' as const; export default class OIDCAuthProvider { constructor() { @@ -27,10 +28,10 @@ export default class OIDCAuthProvider { return providerId; } - static credential(oidcSuffix, idToken, accessToken) { + static credential(oidcSuffix: string, idToken: string, accessToken?: string): AuthCredential { return { token: idToken, - secret: accessToken, + secret: accessToken ?? '', providerId: providerId + oidcSuffix, }; } diff --git a/packages/auth/lib/providers/PhoneAuthProvider.ts b/packages/auth/lib/providers/PhoneAuthProvider.ts index 2c4963a1aa..cfd4c62185 100644 --- a/packages/auth/lib/providers/PhoneAuthProvider.ts +++ b/packages/auth/lib/providers/PhoneAuthProvider.ts @@ -1,5 +1,3 @@ -// @ts-nocheck -/* eslint-disable @typescript-eslint/no-unused-vars */ /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -17,10 +15,56 @@ * */ -const providerId = 'phone'; +import type { + ApplicationVerifier, + AuthCredential, + MultiFactorInfo, + PhoneMultiFactorEnrollInfoOptions, + PhoneMultiFactorSignInInfoOptions, +} from '../types/auth'; + +const providerId = 'phone' as const; + +type PhoneAuthProviderAuth = { + app: { + auth(): { + verifyPhoneNumberWithMultiFactorInfo( + hint: Pick, + session: PhoneMultiFactorSignInInfoOptions['session'], + ): Promise; + verifyPhoneNumberForMultiFactor( + phoneInfoOptions: PhoneMultiFactorEnrollInfoOptions, + ): Promise; + }; + }; +}; + +type SupportedPhoneInfoOptions = + | PhoneMultiFactorEnrollInfoOptions + | PhoneMultiFactorSignInInfoOptions; + +function isPhoneMultiFactorSignInOptions( + phoneInfoOptions: SupportedPhoneInfoOptions, +): phoneInfoOptions is PhoneMultiFactorSignInInfoOptions & { multiFactorHint: MultiFactorInfo } { + return 'multiFactorHint' in phoneInfoOptions && phoneInfoOptions.multiFactorHint !== undefined; +} + +function isPhoneMultiFactorUidOptions( + phoneInfoOptions: SupportedPhoneInfoOptions, +): phoneInfoOptions is PhoneMultiFactorSignInInfoOptions & { multiFactorUid: string } { + return 'multiFactorUid' in phoneInfoOptions && phoneInfoOptions.multiFactorUid !== undefined; +} + +function isPhoneMultiFactorEnrollOptions( + phoneInfoOptions: SupportedPhoneInfoOptions, +): phoneInfoOptions is PhoneMultiFactorEnrollInfoOptions { + return 'phoneNumber' in phoneInfoOptions; +} export default class PhoneAuthProvider { - constructor(auth) { + private readonly _auth: PhoneAuthProviderAuth; + + constructor(auth: PhoneAuthProviderAuth) { if (auth === undefined) { throw new Error('`new PhoneAuthProvider()` is not supported on the native Firebase SDKs.'); } @@ -31,7 +75,7 @@ export default class PhoneAuthProvider { return providerId; } - static credential(verificationId, code) { + static credential(verificationId: string, code: string): AuthCredential { return { token: verificationId, secret: code, @@ -39,8 +83,11 @@ export default class PhoneAuthProvider { }; } - verifyPhoneNumber(phoneInfoOptions, appVerifier) { - if (phoneInfoOptions.multiFactorHint) { + verifyPhoneNumber( + phoneInfoOptions: SupportedPhoneInfoOptions, + _appVerifier?: ApplicationVerifier, + ): Promise { + if (isPhoneMultiFactorSignInOptions(phoneInfoOptions)) { return this._auth.app .auth() .verifyPhoneNumberWithMultiFactorInfo( @@ -48,6 +95,23 @@ export default class PhoneAuthProvider { phoneInfoOptions.session, ); } - return this._auth.app.auth().verifyPhoneNumberForMultiFactor(phoneInfoOptions); + + if (isPhoneMultiFactorUidOptions(phoneInfoOptions)) { + // The native bridge only needs the enrollment uid for MFA sign-in verification. + return this._auth.app + .auth() + .verifyPhoneNumberWithMultiFactorInfo( + { uid: phoneInfoOptions.multiFactorUid }, + phoneInfoOptions.session, + ); + } + + if (isPhoneMultiFactorEnrollOptions(phoneInfoOptions)) { + return this._auth.app.auth().verifyPhoneNumberForMultiFactor(phoneInfoOptions); + } + + throw new Error( + '`PhoneAuthProvider.verifyPhoneNumber()` requires either a multi-factor hint, a multi-factor uid, or enrollment phone info.', + ); } } diff --git a/packages/auth/lib/providers/TwitterAuthProvider.ts b/packages/auth/lib/providers/TwitterAuthProvider.ts index a1b80de931..f5f54288da 100644 --- a/packages/auth/lib/providers/TwitterAuthProvider.ts +++ b/packages/auth/lib/providers/TwitterAuthProvider.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -16,7 +15,9 @@ * */ -const providerId = 'twitter.com'; +import type { AuthCredential } from '../types/auth'; + +const providerId = 'twitter.com' as const; export default class TwitterAuthProvider { constructor() { @@ -27,7 +28,7 @@ export default class TwitterAuthProvider { return providerId; } - static credential(token, secret) { + static credential(token: string, secret: string): AuthCredential { return { token, secret, From a84e01182f5d52ee6053b603fa6f75aa32f476cf Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 24 Apr 2026 13:35:33 +0100 Subject: [PATCH 14/45] refactor: remove ts no-check and type properly --- packages/auth/lib/ConfirmationResult.ts | 18 +- packages/auth/lib/MultiFactorResolver.ts | 40 +++- packages/auth/lib/PhoneAuthListener.ts | 144 ++++++++++---- .../auth/lib/PhoneMultiFactorGenerator.ts | 11 +- packages/auth/lib/Settings.ts | 18 +- packages/auth/lib/TotpMultiFactorGenerator.ts | 39 +++- packages/auth/lib/TotpSecret.ts | 13 +- packages/auth/lib/User.ts | 185 ++++++++++-------- packages/auth/lib/getMultiFactorResolver.ts | 28 ++- packages/auth/lib/modular.ts | 5 +- packages/auth/lib/multiFactor.ts | 68 +++++-- 11 files changed, 392 insertions(+), 177 deletions(-) diff --git a/packages/auth/lib/ConfirmationResult.ts b/packages/auth/lib/ConfirmationResult.ts index b0d44c19a9..94faaacf74 100644 --- a/packages/auth/lib/ConfirmationResult.ts +++ b/packages/auth/lib/ConfirmationResult.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -16,19 +15,28 @@ * */ +import type { FirebaseAuthTypes } from './types/namespaced'; +import type { AuthInternal } from './types/internal'; + export default class ConfirmationResult { - constructor(auth, verificationId) { + private readonly _auth: AuthInternal; + private readonly _verificationId: string; + + constructor(auth: AuthInternal, verificationId: string) { this._auth = auth; this._verificationId = verificationId; } - confirm(verificationCode) { + confirm(verificationCode: string): Promise { return this._auth.native .confirmationResultConfirm(verificationCode) - .then(userCredential => this._auth._setUserCredential(userCredential)); + .then( + userCredential => + this._auth._setUserCredential(userCredential) as FirebaseAuthTypes.UserCredential, + ); } - get verificationId() { + get verificationId(): string { return this._verificationId; } } diff --git a/packages/auth/lib/MultiFactorResolver.ts b/packages/auth/lib/MultiFactorResolver.ts index 1ec99aa1ad..9232de5d67 100644 --- a/packages/auth/lib/MultiFactorResolver.ts +++ b/packages/auth/lib/MultiFactorResolver.ts @@ -1,21 +1,51 @@ -// @ts-nocheck /** * Base class to facilitate multi-factor authentication. */ +import type { FirebaseAuthTypes } from './types/namespaced'; +import type { AuthInternal } from './types/internal'; + +type ResolverLike = { + hints: FirebaseAuthTypes.MultiFactorInfo[]; + session: FirebaseAuthTypes.MultiFactorSession; +}; + +type PhoneMultiFactorAssertion = { + token?: string; + secret?: string; + uid?: string; + verificationCode?: string; +}; + export default class MultiFactorResolver { - constructor(auth, resolver) { + readonly hints: FirebaseAuthTypes.MultiFactorInfo[]; + readonly session: FirebaseAuthTypes.MultiFactorSession; + private readonly _auth: AuthInternal; + + constructor(auth: AuthInternal, resolver: ResolverLike) { this._auth = auth; this.hints = resolver.hints; this.session = resolver.session; } - resolveSignIn(assertion) { + resolveSignIn(assertion: PhoneMultiFactorAssertion): Promise { const { token, secret, uid, verificationCode } = assertion; if (token && secret) { - return this._auth.resolveMultiFactorSignIn(this.session, token, secret); + return this._auth.resolveMultiFactorSignIn( + this.session, + token, + secret, + ) as Promise; + } + + if (uid && verificationCode) { + return this._auth.resolveTotpSignIn( + this.session, + uid, + verificationCode, + ) as Promise; } - return this._auth.resolveTotpSignIn(this.session, uid, verificationCode); + throw new Error('Invalid multi-factor assertion provided for sign-in resolution.'); } } diff --git a/packages/auth/lib/PhoneAuthListener.ts b/packages/auth/lib/PhoneAuthListener.ts index 90a014ae64..1820cc088a 100644 --- a/packages/auth/lib/PhoneAuthListener.ts +++ b/packages/auth/lib/PhoneAuthListener.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -22,17 +21,46 @@ import { isIOS, promiseDefer, } from '@react-native-firebase/app/dist/module/common'; +import type { ReactNativeFirebase } from '@react-native-firebase/app'; import NativeFirebaseError from '@react-native-firebase/app/dist/module/internal/NativeFirebaseError'; +import type { FirebaseAuthTypes } from './types/namespaced'; +import type { + AuthInternal, + NativePhoneAuthCredentialInternal, + NativePhoneAuthErrorInternal, +} from './types/internal'; + +type PhoneAuthInternalEventType = + | 'codeSent' + | 'verificationFailed' + | 'verificationComplete' + | 'codeAutoRetrievalTimeout'; + +type InternalEvents = Record; +type PublicEvents = Record<'error' | 'event' | 'success', string>; +type PhoneAuthSnapshot = FirebaseAuthTypes.PhoneAuthSnapshot; +type PhoneAuthError = FirebaseAuthTypes.PhoneAuthError; let REQUEST_ID = 0; export default class PhoneAuthListener { - constructor(auth, phoneNumber, timeout, forceResend) { + private readonly _auth: AuthInternal; + private _reject: ((error: ReactNativeFirebase.NativeFirebaseError) => void) | null; + private _resolve: ((snapshot: PhoneAuthSnapshot) => void) | null; + private _promise: Promise | null; + private readonly _jsStack: string; + private readonly _timeout: number; + private readonly _phoneAuthRequestId: number; + private readonly _forceResending: boolean; + private readonly _internalEvents: InternalEvents; + private readonly _publicEvents: PublicEvents; + + constructor(auth: AuthInternal, phoneNumber: string, timeout?: number, forceResend?: boolean) { this._auth = auth; this._reject = null; this._resolve = null; this._promise = null; - this._jsStack = new Error().stack; + this._jsStack = new Error().stack ?? ''; this._timeout = timeout || 20; this._phoneAuthRequestId = REQUEST_ID++; @@ -69,42 +97,64 @@ export default class PhoneAuthListener { } } - _subscribeToEvents() { - const events = Object.keys(this._internalEvents); + private _subscribeToEvents(): void { + const events: PhoneAuthInternalEventType[] = [ + 'codeSent', + 'verificationFailed', + 'verificationComplete', + 'codeAutoRetrievalTimeout', + ]; - for (let i = 0, len = events.length; i < len; i++) { - const type = events[i]; + for (const type of events) { const subscription = this._auth.emitter.addListener(this._internalEvents[type], event => { - this[`_${type}Handler`](event); + switch (type) { + case 'codeSent': + this._codeSentHandler(event as NativePhoneAuthCredentialInternal); + break; + case 'verificationFailed': + this._verificationFailedHandler(event as NativePhoneAuthErrorInternal); + break; + case 'verificationComplete': + this._verificationCompleteHandler(event as NativePhoneAuthCredentialInternal); + break; + case 'codeAutoRetrievalTimeout': + this._codeAutoRetrievalTimeoutHandler(event as NativePhoneAuthCredentialInternal); + break; + } subscription.remove(); }); } } - _addUserObserver(observer) { + private _addUserObserver(observer: (snapshot: PhoneAuthSnapshot) => void): void { this._auth.emitter.addListener(this._publicEvents.event, observer); } - _emitToObservers(snapshot) { + private _emitToObservers(snapshot: PhoneAuthSnapshot): void { this._auth.emitter.emit(this._publicEvents.event, snapshot); } - _emitToErrorCb(snapshot) { + private _emitToErrorCb(snapshot: PhoneAuthSnapshot): void { const { error } = snapshot; - if (this._reject) { + if (this._reject && error) { this._reject(error); } - this._auth.emitter.emit(this._publicEvents.error, error); + this._auth.emitter.emit(this._publicEvents.error, { + code: error?.code ?? null, + verificationId: snapshot.verificationId, + message: error?.message ?? null, + stack: error?.stack ?? null, + } as PhoneAuthError); } - _emitToSuccessCb(snapshot) { + private _emitToSuccessCb(snapshot: PhoneAuthSnapshot): void { if (this._resolve) { this._resolve(snapshot); } this._auth.emitter.emit(this._publicEvents.success, snapshot); } - _removeAllListeners() { + private _removeAllListeners(): void { setTimeout(() => { // move to next event loop - not sure if needed // internal listeners @@ -119,9 +169,13 @@ export default class PhoneAuthListener { }, 0); } - _promiseDeferred() { + private _promiseDeferred(): void { if (!this._promise) { - const { promise, resolve, reject } = promiseDefer(); + const { promise, resolve, reject } = promiseDefer() as { + promise: Promise; + resolve: (snapshot: PhoneAuthSnapshot) => void; + reject: (error: ReactNativeFirebase.NativeFirebaseError) => void; + }; this._promise = promise; this._resolve = resolve; this._reject = reject; @@ -132,8 +186,8 @@ export default class PhoneAuthListener { --- INTERNAL EVENT HANDLERS ---------------------------- */ - _codeSentHandler(credential) { - const snapshot = { + private _codeSentHandler(credential: NativePhoneAuthCredentialInternal): void { + const snapshot: PhoneAuthSnapshot = { verificationId: credential.verificationId, code: null, error: null, @@ -152,8 +206,8 @@ export default class PhoneAuthListener { } } - _codeAutoRetrievalTimeoutHandler(credential) { - const snapshot = { + private _codeAutoRetrievalTimeoutHandler(credential: NativePhoneAuthCredentialInternal): void { + const snapshot: PhoneAuthSnapshot = { verificationId: credential.verificationId, code: null, error: null, @@ -164,8 +218,8 @@ export default class PhoneAuthListener { this._emitToSuccessCb(snapshot); } - _verificationCompleteHandler(credential) { - const snapshot = { + private _verificationCompleteHandler(credential: NativePhoneAuthCredentialInternal): void { + const snapshot: PhoneAuthSnapshot = { verificationId: credential.verificationId, code: credential.code || null, error: null, @@ -177,15 +231,19 @@ export default class PhoneAuthListener { this._removeAllListeners(); } - _verificationFailedHandler(state) { - const snapshot = { + private _verificationFailedHandler(state: NativePhoneAuthErrorInternal): void { + const snapshot: PhoneAuthSnapshot = { verificationId: state.verificationId, code: null, error: null, state: 'error', }; - snapshot.error = new NativeFirebaseError({ userInfo: state.error }, this._jsStack, 'auth'); + snapshot.error = new NativeFirebaseError( + { userInfo: state.error }, + this._jsStack, + 'auth', + ) as ReactNativeFirebase.NativeFirebaseError; this._emitToObservers(snapshot); this._emitToErrorCb(snapshot); @@ -196,7 +254,12 @@ export default class PhoneAuthListener { -- PUBLIC API --------------*/ - on(event, observer, errorCb, successCb) { + on( + event: string, + observer: (snapshot: PhoneAuthSnapshot) => void, + errorCb?: (error: PhoneAuthError) => void, + successCb?: (snapshot: PhoneAuthSnapshot) => void, + ): PhoneAuthListener { if (event !== 'state_changed') { throw new Error( "firebase.auth.PhoneAuthListener.on(*, _, _, _) 'event' must equal 'state_changed'.", @@ -214,33 +277,36 @@ export default class PhoneAuthListener { if (isFunction(errorCb)) { const subscription = this._auth.emitter.addListener(this._publicEvents.error, event => { subscription.remove(); - errorCb(event); + errorCb(event as PhoneAuthError); }); } if (isFunction(successCb)) { const subscription = this._auth.emitter.addListener(this._publicEvents.success, event => { subscription.remove(); - successCb(event); + successCb(event as PhoneAuthSnapshot); }); } return this; } - then(fn) { + then( + onFulfilled?: ((value: PhoneAuthSnapshot) => TResult1 | PromiseLike) | null, + onRejected?: + | ((reason: ReactNativeFirebase.NativeFirebaseError) => TResult2 | PromiseLike) + | null, + ): Promise { this._promiseDeferred(); - if (this._promise) { - return this._promise.then.bind(this._promise)(fn); - } - return undefined; + return this._promise!.then(onFulfilled ?? undefined, onRejected ?? undefined); } - catch(fn) { + catch( + onRejected?: + | ((reason: ReactNativeFirebase.NativeFirebaseError) => TResult | PromiseLike) + | null, + ): Promise { this._promiseDeferred(); - if (this._promise) { - return this._promise.catch.bind(this._promise)(fn); - } - return undefined; + return this._promise!.catch(onRejected ?? undefined); } } diff --git a/packages/auth/lib/PhoneMultiFactorGenerator.ts b/packages/auth/lib/PhoneMultiFactorGenerator.ts index 01527e8f0a..d8a7e7dcc9 100644 --- a/packages/auth/lib/PhoneMultiFactorGenerator.ts +++ b/packages/auth/lib/PhoneMultiFactorGenerator.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -16,6 +15,8 @@ * */ +import type { AuthCredential, MultiFactorAssertion } from './types/auth'; + export default class PhoneMultiFactorGenerator { static FACTOR_ID = 'phone'; @@ -25,10 +26,14 @@ export default class PhoneMultiFactorGenerator { ); } - static assertion(credential) { + static assertion(credential: AuthCredential): MultiFactorAssertion { // There is no logic here, we mainly do this for API compatibility // (following the Web API). const { token, secret } = credential; - return { token, secret }; + return { + token, + secret, + factorId: 'phone', + } as MultiFactorAssertion; } } diff --git a/packages/auth/lib/Settings.ts b/packages/auth/lib/Settings.ts index 2e45f29266..c4c48955a7 100644 --- a/packages/auth/lib/Settings.ts +++ b/packages/auth/lib/Settings.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -17,35 +16,40 @@ */ import { isAndroid } from '@react-native-firebase/app/dist/module/common'; +import type { AuthInternal } from './types/internal'; export default class Settings { - constructor(auth) { + private readonly _auth: AuthInternal; + private _forceRecaptchaFlowForTesting: boolean; + private _appVerificationDisabledForTesting: boolean; + + constructor(auth: AuthInternal) { this._auth = auth; this._forceRecaptchaFlowForTesting = false; this._appVerificationDisabledForTesting = false; } - get forceRecaptchaFlowForTesting() { + get forceRecaptchaFlowForTesting(): boolean { return this._forceRecaptchaFlowForTesting; } - set forceRecaptchaFlowForTesting(forceRecaptchaFlow) { + set forceRecaptchaFlowForTesting(forceRecaptchaFlow: boolean) { if (isAndroid) { this._forceRecaptchaFlowForTesting = forceRecaptchaFlow; this._auth.native.forceRecaptchaFlowForTesting(forceRecaptchaFlow); } } - get appVerificationDisabledForTesting() { + get appVerificationDisabledForTesting(): boolean { return this._appVerificationDisabledForTesting; } - set appVerificationDisabledForTesting(disabled) { + set appVerificationDisabledForTesting(disabled: boolean) { this._appVerificationDisabledForTesting = disabled; this._auth.native.setAppVerificationDisabledForTesting(disabled); } - setAutoRetrievedSmsCodeForPhoneNumber(phoneNumber, smsCode) { + setAutoRetrievedSmsCodeForPhoneNumber(phoneNumber: string, smsCode: string): Promise { if (isAndroid) { return this._auth.native.setAutoRetrievedSmsCodeForPhoneNumber(phoneNumber, smsCode); } diff --git a/packages/auth/lib/TotpMultiFactorGenerator.ts b/packages/auth/lib/TotpMultiFactorGenerator.ts index 3e8fef6666..d6e540ec61 100644 --- a/packages/auth/lib/TotpMultiFactorGenerator.ts +++ b/packages/auth/lib/TotpMultiFactorGenerator.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -19,6 +18,8 @@ import { isOther } from '@react-native-firebase/app/dist/module/common'; import { TotpSecret } from './TotpSecret'; import { getAuth } from './modular'; +import type { FirebaseAuthTypes } from './types/namespaced'; +import type { AuthInternal } from './types/internal'; export default class TotpMultiFactorGenerator { static FACTOR_ID = 'totp'; @@ -29,20 +30,40 @@ export default class TotpMultiFactorGenerator { ); } - static assertionForSignIn(uid, verificationCode) { + static assertionForSignIn( + uid: string, + verificationCode: string, + ): FirebaseAuthTypes.MultiFactorAssertion { if (isOther) { // we require the web native assertion when using firebase-js-sdk // as it has functions used by the SDK, a shim won't do - return getAuth().native.assertionForSignIn(uid, verificationCode); + return (getAuth() as unknown as AuthInternal).native.assertionForSignIn( + uid, + verificationCode, + ) as unknown as FirebaseAuthTypes.MultiFactorAssertion; } - return { uid, verificationCode }; + return { + uid, + verificationCode, + factorId: 'totp', + } as unknown as FirebaseAuthTypes.MultiFactorAssertion; } - static assertionForEnrollment(totpSecret, verificationCode) { - return { totpSecret: totpSecret.secretKey, verificationCode }; + static assertionForEnrollment( + totpSecret: TotpSecret, + verificationCode: string, + ): FirebaseAuthTypes.MultiFactorAssertion { + return { + totpSecret: totpSecret.secretKey, + verificationCode, + factorId: 'totp', + } as unknown as FirebaseAuthTypes.MultiFactorAssertion; } - static async generateSecret(session, auth) { + static async generateSecret( + session: FirebaseAuthTypes.MultiFactorSession, + auth: FirebaseAuthTypes.Module, + ): Promise { if (!session) { throw new Error('Session is required to generate a TOTP secret.'); } @@ -50,8 +71,8 @@ export default class TotpMultiFactorGenerator { secretKey, // Other properties are not publicly exposed in native APIs // hashingAlgorithm, codeLength, codeIntervalSeconds, enrollmentCompletionDeadline - } = await auth.native.generateTotpSecret(session); + } = await (auth as unknown as AuthInternal).native.generateTotpSecret(session); - return new TotpSecret(secretKey, auth); + return new TotpSecret(secretKey, auth as unknown as AuthInternal); } } diff --git a/packages/auth/lib/TotpSecret.ts b/packages/auth/lib/TotpSecret.ts index 6131c0b83f..4f8338f4a6 100644 --- a/packages/auth/lib/TotpSecret.ts +++ b/packages/auth/lib/TotpSecret.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -16,9 +15,13 @@ */ import { isString } from '@react-native-firebase/app/dist/module/common'; +import type { AuthInternal } from './types/internal'; export class TotpSecret { - constructor(secretKey, auth) { + readonly secretKey: string; + private readonly auth: AuthInternal; + + constructor(secretKey: string, auth: AuthInternal) { // The native TotpSecret has many more properties, but they are // internal to the native SDKs, we only maintain the secret in JS layer this.secretKey = secretKey; @@ -30,8 +33,6 @@ export class TotpSecret { /** * Shared secret key/seed used for enrolling in TOTP MFA and generating OTPs. */ - secretKey = null; - /** * Returns a QR code URL as described in * https://github.com/google/google-authenticator/wiki/Key-Uri-Format @@ -42,7 +43,7 @@ export class TotpSecret { * @param issuer issuer of the TOTP (likely the app name). * @returns A Promise that resolves to a QR code URL string. */ - async generateQrCodeUrl(accountName, issuer) { + async generateQrCodeUrl(accountName?: string, issuer?: string): Promise { // accountName and issure are nullable in the API specification but are // required by tha native SDK. The JS SDK returns '' if they are missing/empty. if (!isString(accountName) || !isString(issuer) || accountName === '' || issuer === '') { @@ -60,7 +61,7 @@ export class TotpSecret { * * @param qrCodeUrl the URL to open in the app, from generateQrCodeUrl */ - openInOtpApp(qrCodeUrl) { + openInOtpApp(qrCodeUrl: string): string | void { if (isString(qrCodeUrl) && qrCodeUrl !== '') { return this.auth.native.openInOtpApp(this.secretKey, qrCodeUrl); } diff --git a/packages/auth/lib/User.ts b/packages/auth/lib/User.ts index fc3604d2d9..66590858d9 100644 --- a/packages/auth/lib/User.ts +++ b/packages/auth/lib/User.ts @@ -1,4 +1,3 @@ -// @ts-nocheck /* * Copyright (c) 2016-present Invertase Limited & Contributors * @@ -22,30 +21,39 @@ import { isUndefined, isBoolean, } from '@react-native-firebase/app/dist/module/common'; +import type { FirebaseAuthTypes } from './types/namespaced'; +import type { AuthInternal, NativeUserInternal } from './types/internal'; + +type AuthProviderWithObject = FirebaseAuthTypes.AuthProvider & { + toObject(): Record; +}; export default class User { - constructor(auth, user) { + private readonly _auth: AuthInternal; + private readonly _user: NativeUserInternal; + + constructor(auth: AuthInternal, user: NativeUserInternal) { this._auth = auth; this._user = user; } - get displayName() { + get displayName(): string | null { return this._user.displayName || null; } - get email() { + get email(): string | null { return this._user.email || null; } - get emailVerified() { + get emailVerified(): boolean { return this._user.emailVerified || false; } - get isAnonymous() { + get isAnonymous(): boolean { return this._user.isAnonymous || false; } - get metadata() { + get metadata(): FirebaseAuthTypes.UserMetadata { const { metadata } = this._user; return { @@ -54,148 +62,164 @@ export default class User { }; } - get multiFactor() { + get multiFactor(): FirebaseAuthTypes.MultiFactor | null { return this._user.multiFactor || null; } - get phoneNumber() { + get phoneNumber(): string | null { return this._user.phoneNumber || null; } - get tenantId() { + get tenantId(): string | null { return this._user.tenantId || null; } - get photoURL() { + get photoURL(): string | null { return this._user.photoURL || null; } - get providerData() { + get providerData(): FirebaseAuthTypes.UserInfo[] { return this._user.providerData; } - get providerId() { + get providerId(): string { return this._user.providerId; } - get uid() { + get uid(): string { return this._user.uid; } - delete() { + delete(): Promise { return this._auth.native.delete().then(() => { this._auth._setUser(null); }); } - getIdToken(forceRefresh = false) { + getIdToken(forceRefresh = false): Promise { return this._auth.native.getIdToken(forceRefresh); } - getIdTokenResult(forceRefresh = false) { - return this._auth.native.getIdTokenResult(forceRefresh); + getIdTokenResult(forceRefresh = false): Promise { + return this._auth.native.getIdTokenResult( + forceRefresh, + ) as Promise; } - linkWithCredential(credential) { + linkWithCredential( + credential: FirebaseAuthTypes.AuthCredential, + ): Promise { return this._auth.native .linkWithCredential(credential.providerId, credential.token, credential.secret) - .then(userCredential => this._auth._setUserCredential(userCredential)); + .then( + userCredential => + this._auth._setUserCredential(userCredential) as FirebaseAuthTypes.UserCredential, + ); } - linkWithPopup(provider) { + linkWithPopup(provider: AuthProviderWithObject): Promise { // call through to linkWithRedirect for shared implementation return this.linkWithRedirect(provider); } - linkWithRedirect(provider) { + linkWithRedirect(provider: AuthProviderWithObject): Promise { return this._auth.native .linkWithProvider(provider.toObject()) - .then(userCredential => this._auth._setUserCredential(userCredential)); + .then( + userCredential => + this._auth._setUserCredential(userCredential) as FirebaseAuthTypes.UserCredential, + ); } - reauthenticateWithCredential(credential) { + reauthenticateWithCredential( + credential: FirebaseAuthTypes.AuthCredential, + ): Promise { return this._auth.native .reauthenticateWithCredential(credential.providerId, credential.token, credential.secret) - .then(userCredential => this._auth._setUserCredential(userCredential)); + .then( + userCredential => + this._auth._setUserCredential(userCredential) as FirebaseAuthTypes.UserCredential, + ); } - reauthenticateWithPopup(provider) { + reauthenticateWithPopup( + provider: AuthProviderWithObject, + ): Promise { // call through to reauthenticateWithRedirect for shared implementation - return this.reauthenticateWithRedirect(provider); - } - - reauthenticateWithRedirect(provider) { return this._auth.native .reauthenticateWithProvider(provider.toObject()) - .then(userCredential => this._auth._setUserCredential(userCredential)); + .then( + userCredential => + this._auth._setUserCredential(userCredential) as FirebaseAuthTypes.UserCredential, + ); } - reload() { + reauthenticateWithRedirect(provider: AuthProviderWithObject): Promise { + return this._auth.native.reauthenticateWithProvider(provider.toObject()).then(() => {}); + } + + reload(): Promise { return this._auth.native.reload().then(user => { this._auth._setUser(user); }); } - sendEmailVerification(actionCodeSettings) { + sendEmailVerification(actionCodeSettings?: FirebaseAuthTypes.ActionCodeSettings): Promise { if (isObject(actionCodeSettings)) { - if (!isString(actionCodeSettings.url)) { + const settings = actionCodeSettings as FirebaseAuthTypes.ActionCodeSettings; + + if (!isString(settings.url)) { throw new Error( "firebase.auth.User.sendEmailVerification(*) 'actionCodeSettings.url' expected a string value.", ); } - if (!isUndefined(actionCodeSettings.linkDomain) && !isString(actionCodeSettings.linkDomain)) { + if (!isUndefined(settings.linkDomain) && !isString(settings.linkDomain)) { throw new Error( "firebase.auth.User.sendEmailVerification(*) 'actionCodeSettings.linkDomain' expected a string value.", ); } - if ( - !isUndefined(actionCodeSettings.handleCodeInApp) && - !isBoolean(actionCodeSettings.handleCodeInApp) - ) { + if (!isUndefined(settings.handleCodeInApp) && !isBoolean(settings.handleCodeInApp)) { throw new Error( "firebase.auth.User.sendEmailVerification(*) 'actionCodeSettings.handleCodeInApp' expected a boolean value.", ); } - if (!isUndefined(actionCodeSettings.iOS)) { - if (!isObject(actionCodeSettings.iOS)) { + if (!isUndefined(settings.iOS)) { + if (!isObject(settings.iOS)) { throw new Error( "firebase.auth.User.sendEmailVerification(*) 'actionCodeSettings.iOS' expected an object value.", ); } - if (!isString(actionCodeSettings.iOS.bundleId)) { + if (!isString(settings.iOS.bundleId)) { throw new Error( "firebase.auth.User.sendEmailVerification(*) 'actionCodeSettings.iOS.bundleId' expected a string value.", ); } } - if (!isUndefined(actionCodeSettings.android)) { - if (!isObject(actionCodeSettings.android)) { + if (!isUndefined(settings.android)) { + if (!isObject(settings.android)) { throw new Error( "firebase.auth.User.sendEmailVerification(*) 'actionCodeSettings.android' expected an object value.", ); } - if (!isString(actionCodeSettings.android.packageName)) { + if (!isString(settings.android.packageName)) { throw new Error( "firebase.auth.User.sendEmailVerification(*) 'actionCodeSettings.android.packageName' expected a string value.", ); } - if ( - !isUndefined(actionCodeSettings.android.installApp) && - !isBoolean(actionCodeSettings.android.installApp) - ) { + if (!isUndefined(settings.android.installApp) && !isBoolean(settings.android.installApp)) { throw new Error( "firebase.auth.User.sendEmailVerification(*) 'actionCodeSettings.android.installApp' expected a boolean value.", ); } if ( - !isUndefined(actionCodeSettings.android.minimumVersion) && - !isString(actionCodeSettings.android.minimumVersion) + !isUndefined(settings.android.minimumVersion) && + !isString(settings.android.minimumVersion) ) { throw new Error( "firebase.auth.User.sendEmailVerification(*) 'actionCodeSettings.android.minimumVersion' expected a string value.", @@ -209,27 +233,29 @@ export default class User { }); } - toJSON() { + toJSON(): object { return Object.assign({}, this._user); } - unlink(providerId) { - return this._auth.native.unlink(providerId).then(user => this._auth._setUser(user)); + unlink(providerId: string): Promise { + return this._auth.native + .unlink(providerId) + .then(user => this._auth._setUser(user) as FirebaseAuthTypes.User); } - updateEmail(email) { + updateEmail(email: string): Promise { return this._auth.native.updateEmail(email).then(user => { this._auth._setUser(user); }); } - updatePassword(password) { + updatePassword(password: string): Promise { return this._auth.native.updatePassword(password).then(user => { this._auth._setUser(user); }); } - updatePhoneNumber(credential) { + updatePhoneNumber(credential: FirebaseAuthTypes.AuthCredential): Promise { return this._auth.native .updatePhoneNumber(credential.providerId, credential.token, credential.secret) .then(user => { @@ -237,13 +263,16 @@ export default class User { }); } - updateProfile(updates) { + updateProfile(updates: FirebaseAuthTypes.UpdateProfile): Promise { return this._auth.native.updateProfile(updates).then(user => { this._auth._setUser(user); }); } - verifyBeforeUpdateEmail(newEmail, actionCodeSettings) { + verifyBeforeUpdateEmail( + newEmail: string, + actionCodeSettings?: FirebaseAuthTypes.ActionCodeSettings, + ): Promise { if (!isString(newEmail)) { throw new Error( "firebase.auth.User.verifyBeforeUpdateEmail(*) 'newEmail' expected a string value.", @@ -251,64 +280,60 @@ export default class User { } if (isObject(actionCodeSettings)) { - if (!isString(actionCodeSettings.url)) { + const settings = actionCodeSettings as FirebaseAuthTypes.ActionCodeSettings; + + if (!isString(settings.url)) { throw new Error( "firebase.auth.User.verifyBeforeUpdateEmail(_, *) 'actionCodeSettings.url' expected a string value.", ); } - if (!isUndefined(actionCodeSettings.linkDomain) && !isString(actionCodeSettings.linkDomain)) { + if (!isUndefined(settings.linkDomain) && !isString(settings.linkDomain)) { throw new Error( "firebase.auth.User.verifyBeforeUpdateEmail(_, *) 'actionCodeSettings.linkDomain' expected a string value.", ); } - if ( - !isUndefined(actionCodeSettings.handleCodeInApp) && - !isBoolean(actionCodeSettings.handleCodeInApp) - ) { + if (!isUndefined(settings.handleCodeInApp) && !isBoolean(settings.handleCodeInApp)) { throw new Error( "firebase.auth.User.verifyBeforeUpdateEmail(_, *) 'actionCodeSettings.handleCodeInApp' expected a boolean value.", ); } - if (!isUndefined(actionCodeSettings.iOS)) { - if (!isObject(actionCodeSettings.iOS)) { + if (!isUndefined(settings.iOS)) { + if (!isObject(settings.iOS)) { throw new Error( "firebase.auth.User.verifyBeforeUpdateEmail(_, *) 'actionCodeSettings.iOS' expected an object value.", ); } - if (!isString(actionCodeSettings.iOS.bundleId)) { + if (!isString(settings.iOS.bundleId)) { throw new Error( "firebase.auth.User.verifyBeforeUpdateEmail(_, *) 'actionCodeSettings.iOS.bundleId' expected a string value.", ); } } - if (!isUndefined(actionCodeSettings.android)) { - if (!isObject(actionCodeSettings.android)) { + if (!isUndefined(settings.android)) { + if (!isObject(settings.android)) { throw new Error( "firebase.auth.User.verifyBeforeUpdateEmail(_, *) 'actionCodeSettings.android' expected an object value.", ); } - if (!isString(actionCodeSettings.android.packageName)) { + if (!isString(settings.android.packageName)) { throw new Error( "firebase.auth.User.verifyBeforeUpdateEmail(_, *) 'actionCodeSettings.android.packageName' expected a string value.", ); } - if ( - !isUndefined(actionCodeSettings.android.installApp) && - !isBoolean(actionCodeSettings.android.installApp) - ) { + if (!isUndefined(settings.android.installApp) && !isBoolean(settings.android.installApp)) { throw new Error( "firebase.auth.User.verifyBeforeUpdateEmail(_, *) 'actionCodeSettings.android.installApp' expected a boolean value.", ); } if ( - !isUndefined(actionCodeSettings.android.minimumVersion) && - !isString(actionCodeSettings.android.minimumVersion) + !isUndefined(settings.android.minimumVersion) && + !isString(settings.android.minimumVersion) ) { throw new Error( "firebase.auth.User.verifyBeforeUpdateEmail(_, *) 'actionCodeSettings.android.minimumVersion' expected a string value.", @@ -326,19 +351,19 @@ export default class User { * KNOWN UNSUPPORTED METHODS */ - linkWithPhoneNumber() { + linkWithPhoneNumber(): never { throw new Error( 'firebase.auth.User.linkWithPhoneNumber() is unsupported by the native Firebase SDKs.', ); } - reauthenticateWithPhoneNumber() { + reauthenticateWithPhoneNumber(): never { throw new Error( 'firebase.auth.User.reauthenticateWithPhoneNumber() is unsupported by the native Firebase SDKs.', ); } - get refreshToken() { + get refreshToken(): never { throw new Error('firebase.auth.User.refreshToken is unsupported by the native Firebase SDKs.'); } } diff --git a/packages/auth/lib/getMultiFactorResolver.ts b/packages/auth/lib/getMultiFactorResolver.ts index 5b9412f715..c5b4205264 100644 --- a/packages/auth/lib/getMultiFactorResolver.ts +++ b/packages/auth/lib/getMultiFactorResolver.ts @@ -1,6 +1,16 @@ -// @ts-nocheck import { isOther } from '@react-native-firebase/app/dist/module/common'; -import MultiFactorResolver from './MultiFactorResolver.js'; +import MultiFactorResolver from './MultiFactorResolver'; +import type { FirebaseAuthTypes } from './types/namespaced'; +import type { AuthInternal } from './types/internal'; + +type ErrorWithResolver = FirebaseAuthTypes.MultiFactorError & { + userInfo?: { + resolver?: { + hints: FirebaseAuthTypes.MultiFactorResolver['hints']; + session: FirebaseAuthTypes.MultiFactorResolver['session']; + }; + }; +}; /** * Create a new resolver based on an auth instance and error @@ -8,16 +18,22 @@ import MultiFactorResolver from './MultiFactorResolver.js'; * * Returns null if no resolver object can be found on the error. */ -export function getMultiFactorResolver(auth, error) { +export function getMultiFactorResolver( + auth: AuthInternal, + error: ErrorWithResolver, +): FirebaseAuthTypes.MultiFactorResolver | null { if (isOther) { - return auth.native.getMultiFactorResolver(error); + return auth.native.getMultiFactorResolver(error) as FirebaseAuthTypes.MultiFactorResolver | null; } if ( error.hasOwnProperty('userInfo') && - error.userInfo.hasOwnProperty('resolver') && + error.userInfo?.hasOwnProperty('resolver') && error.userInfo.resolver ) { - return new MultiFactorResolver(auth, error.userInfo.resolver); + return new MultiFactorResolver( + auth, + error.userInfo.resolver, + ) as unknown as FirebaseAuthTypes.MultiFactorResolver; } return null; diff --git a/packages/auth/lib/modular.ts b/packages/auth/lib/modular.ts index ce859b4f76..2e8f00c95f 100644 --- a/packages/auth/lib/modular.ts +++ b/packages/auth/lib/modular.ts @@ -551,8 +551,9 @@ export function linkWithRedirect( export function multiFactor(user: User): MultiFactorUser { return new MultiFactorUserModule( - (user as unknown as UserInternal)._auth || getAuth(), - user, + ((user as unknown as UserInternal)._auth || + (getAuth() as unknown as UserInternal['_auth'])) as NonNullable, + user as unknown as FirebaseAuthTypes.User, ) as MultiFactorUser; } diff --git a/packages/auth/lib/multiFactor.ts b/packages/auth/lib/multiFactor.ts index 9729959eb6..be27e274b0 100644 --- a/packages/auth/lib/multiFactor.ts +++ b/packages/auth/lib/multiFactor.ts @@ -1,23 +1,47 @@ -// @ts-nocheck import { reload } from './modular'; +import type { + MultiFactorAssertion as ModularMultiFactorAssertion, + User as ModularUser, +} from './types/auth'; +import type { FirebaseAuthTypes } from './types/namespaced'; +import type { AuthInternal } from './types/internal'; + +type EnrollmentAssertion = { + token?: string; + secret?: string; + totpSecret?: string; + verificationCode?: string; +}; + +type MultiFactorAuthHost = { + currentUser: FirebaseAuthTypes.User | null; + native: AuthInternal['native']; +}; /** * Return a MultiFactorUser instance the gateway to multi-factor operations. */ -export function multiFactor(auth) { +export function multiFactor(auth: MultiFactorAuthHost): FirebaseAuthTypes.MultiFactorUser { return new MultiFactorUser(auth); } export class MultiFactorUser { - constructor(auth, user) { + readonly enrolledFactors: FirebaseAuthTypes.MultiFactorInfo[]; + private readonly _auth: MultiFactorAuthHost; + + constructor(auth: MultiFactorAuthHost, user?: FirebaseAuthTypes.User) { this._auth = auth; if (user === undefined) { - user = auth.currentUser; + user = auth.currentUser as FirebaseAuthTypes.User; } - this._user = user; - this.enrolledFactors = user.multiFactor.enrolledFactors; + + if (!user) { + throw new Error('A user is required to access multi-factor operations.'); + } + + this.enrolledFactors = user.multiFactor?.enrolledFactors ?? []; } - getSession() { + getSession(): Promise { return this._auth.native.getSession(); } @@ -26,26 +50,40 @@ export class MultiFactorUser { * Optionally set a displayName. This method will reload the current user * profile, which is necessary to see the multi-factor changes. */ - async enroll(multiFactorAssertion, displayName) { - const { token, secret, totpSecret, verificationCode } = multiFactorAssertion; + async enroll( + multiFactorAssertion: FirebaseAuthTypes.MultiFactorAssertion | ModularMultiFactorAssertion, + displayName?: string | null, + ): Promise { + const assertion = multiFactorAssertion as EnrollmentAssertion; + const { token, secret, totpSecret, verificationCode } = assertion; if (token && secret) { - await this._auth.native.finalizeMultiFactorEnrollment(token, secret, displayName); + await this._auth.native.finalizeMultiFactorEnrollment( + token, + secret, + displayName ?? undefined, + ); } else if (totpSecret && verificationCode) { - await this._auth.native.finalizeTotpEnrollment(totpSecret, verificationCode, displayName); + await this._auth.native.finalizeTotpEnrollment( + totpSecret, + verificationCode, + displayName ?? undefined, + ); } else { throw new Error('Invalid multi-factor assertion provided for enrollment.'); } // We need to reload the user otherwise the changes are not visible // TODO reload not working on Other platform - return reload(this._auth.currentUser); + await reload(this._auth.currentUser as unknown as ModularUser); } - async unenroll(enrollmentId) { - await this._auth.native.unenrollMultiFactor(enrollmentId); + async unenroll(enrollmentId: FirebaseAuthTypes.MultiFactorInfo | string): Promise { + await this._auth.native.unenrollMultiFactor( + enrollmentId as string | FirebaseAuthTypes.MultiFactorInfo, + ); if (this._auth.currentUser) { - return reload(this._auth.currentUser); + await reload(this._auth.currentUser as unknown as ModularUser); } } } From 99f20f19c6c1e73a8dd950b28f12d05f14735bc4 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 24 Apr 2026 15:23:31 +0100 Subject: [PATCH 15/45] refactor: web TS implementation --- .../auth/lib/web/RNFBAuthModule.android.ts | 1 - packages/auth/lib/web/RNFBAuthModule.ios.ts | 1 - packages/auth/lib/web/RNFBAuthModule.ts | 340 +++++++++++++----- 3 files changed, 241 insertions(+), 101 deletions(-) diff --git a/packages/auth/lib/web/RNFBAuthModule.android.ts b/packages/auth/lib/web/RNFBAuthModule.android.ts index 56a9885699..af77c859b1 100644 --- a/packages/auth/lib/web/RNFBAuthModule.android.ts +++ b/packages/auth/lib/web/RNFBAuthModule.android.ts @@ -1,3 +1,2 @@ -// @ts-nocheck // No-op for android. export default {}; diff --git a/packages/auth/lib/web/RNFBAuthModule.ios.ts b/packages/auth/lib/web/RNFBAuthModule.ios.ts index 93d22181a4..a3429ada0e 100644 --- a/packages/auth/lib/web/RNFBAuthModule.ios.ts +++ b/packages/auth/lib/web/RNFBAuthModule.ios.ts @@ -1,3 +1,2 @@ -// @ts-nocheck // No-op for ios. export default {}; diff --git a/packages/auth/lib/web/RNFBAuthModule.ts b/packages/auth/lib/web/RNFBAuthModule.ts index 2774b3976e..fd5609ca85 100644 --- a/packages/auth/lib/web/RNFBAuthModule.ts +++ b/packages/auth/lib/web/RNFBAuthModule.ts @@ -1,9 +1,8 @@ -// @ts-nocheck import { Platform } from 'react-native'; +import * as firebaseAuthModule from '@react-native-firebase/app/dist/module/internal/web/firebaseAuth'; import { getApp, initializeAuth, - getReactNativePersistence, onAuthStateChanged, onIdTokenChanged, signInAnonymously, @@ -45,6 +44,22 @@ import { PhoneAuthProvider, OAuthProvider, } from '@react-native-firebase/app/dist/module/internal/web/firebaseAuth'; +import type { + ActionCodeSettings, + Auth, + AuthCredential, + MultiFactorInfo, + MultiFactorError, + MultiFactorSession, + MultiFactorResolver, + PhoneAuthCredential, + TotpSecret as WebTotpSecret, + Unsubscribe, + User, + UserCredential, + UserInfo, + UserMetadata, +} from '@react-native-firebase/app/dist/module/internal/web/firebaseAuth'; import { guard, getWebError, @@ -54,13 +69,71 @@ import { getReactNativeAsyncStorageInternal, isMemoryStorage, } from '@react-native-firebase/app/dist/module/internal/asyncStorage'; +type UserInfoObject = { + providerId: string; + uid: string; + displayName: string | null; + email: string | null; + photoURL: string | null; + phoneNumber: string | null; +}; + +type WebErrorLike = { + name?: string; + code?: string; + message: string; + details?: unknown; + customData?: unknown; + userInfo?: Record; +}; + +type MultiFactorInfoObject = { + displayName?: string | null; + enrollmentTime: string; + factorId: string; + uid: string; + phoneNumber?: string | null; +}; + +type UserMetadataObject = { + creationTime: string | null; + lastSignInTime: string | null; +}; + +type UserObject = UserInfoObject & { + emailVerified: boolean; + isAnonymous: boolean; + tenantId: string | null; + providerData: UserInfoObject[]; + metadata: UserMetadataObject; + multiFactor: { + enrolledFactors: MultiFactorInfoObject[]; + }; +}; + +type AuthResultObject = { + user: UserObject; + additionalUserInfo: { + isNewUser: boolean; + profile: Record | null; + providerId: string | null; + username?: string | null; + } | null; +}; + +const getReactNativePersistence = + ( + firebaseAuthModule as unknown as { + getReactNativePersistence?: (storage: unknown) => unknown; + } + ).getReactNativePersistence ?? ((storage: unknown) => storage); /** * Resolves or rejects an auth method promise without a user (user was missing). * @param {boolean} isError whether to reject the promise. * @returns {Promise} - Void promise. */ -function promiseNoUser(isError = false) { +function promiseNoUser(isError = false): Promise { if (isError) { return rejectPromiseWithCodeAndMessage('no-current-user', 'No user currently signed in.'); } @@ -74,13 +147,14 @@ function promiseNoUser(isError = false) { * @param {string} code - The error code. * @param {string} message - The error message. */ -function rejectPromiseWithCodeAndMessage(code, message) { - return rejectPromise(getWebError({ code: `auth/${code}`, message })); +function rejectPromiseWithCodeAndMessage(code: string, message: string): Promise { + return rejectPromise(getWebError({ name: 'FirebaseError', code: `auth/${code}`, message })); } -function rejectWithCodeAndMessage(code, message) { +function rejectWithCodeAndMessage(code: string, message: string): Promise { return Promise.reject( getWebError({ + name: 'FirebaseError', code, message, }), @@ -92,10 +166,10 @@ function rejectWithCodeAndMessage(code, message) { * @param {error} error The error object. * @returns {never} */ -function rejectPromise(error) { +function rejectPromise(error: WebErrorLike): Promise { const { code, message, details } = error; const nativeError = { - code, + code: code ?? 'auth/unknown', message, userInfo: { code: code ? code.replace('auth/', '') : 'unknown', @@ -111,7 +185,7 @@ function rejectPromise(error) { * @param {User} user - The User object to convert. * @returns {object} */ -function userToObject(user) { +function userToObject(user: User): UserObject { return { ...userInfoToObject(user), emailVerified: user.emailVerified, @@ -133,7 +207,12 @@ function userToObject(user) { * @param {string|null} secret - The secret to use for the credential. * @returns {AuthCredential|null} - The AuthCredential object. */ -function getAuthCredential(_auth, provider, token, secret) { +function getAuthCredential( + _auth: Auth, + provider: string, + token: string, + secret?: string | null, +): AuthCredential | null { if (provider.startsWith('oidc.')) { return new OAuthProvider(provider).credential({ idToken: token, @@ -142,29 +221,29 @@ function getAuthCredential(_auth, provider, token, secret) { switch (provider) { case 'facebook.com': - return FacebookAuthProvider().credential(token); + return FacebookAuthProvider.credential(token); case 'google.com': - return GoogleAuthProvider().credential(token, secret); + return GoogleAuthProvider.credential(token, secret ?? undefined); case 'twitter.com': - return TwitterAuthProvider().credential(token, secret); + return TwitterAuthProvider.credential(token, secret ?? ''); case 'github.com': - return GithubAuthProvider().credential(token); + return GithubAuthProvider.credential(token); case 'apple.com': return new OAuthProvider(provider).credential({ idToken: token, - rawNonce: secret, + rawNonce: secret ?? undefined, }); case 'oauth': - return OAuthProvider(provider).credential({ + return new OAuthProvider(provider).credential({ idToken: token, - accessToken: secret, + accessToken: secret ?? undefined, }); case 'phone': - return PhoneAuthProvider.credential(token, secret); + return PhoneAuthProvider.credential(token, secret ?? ''); case 'password': - return EmailAuthProvider.credential(token, secret); + return EmailAuthProvider.credential(token, secret ?? ''); case 'emailLink': - return EmailAuthProvider.credentialWithLink(token, secret); + return EmailAuthProvider.credentialWithLink(token, secret ?? ''); default: return null; } @@ -174,7 +253,7 @@ function getAuthCredential(_auth, provider, token, secret) { * Converts a user info object to a plain object. * @param {UserInfo} userInfo - The UserInfo object to convert. */ -function userInfoToObject(userInfo) { +function userInfoToObject(userInfo: UserInfo): UserInfoObject { return { providerId: userInfo.providerId, uid: userInfo.uid, @@ -191,7 +270,7 @@ function userInfoToObject(userInfo) { * Converts a user metadata object to a plain object. * @param {UserMetadata} metadata - The UserMetadata object to convert. */ -function userMetadataToObject(metadata) { +function userMetadataToObject(metadata: UserMetadata): UserMetadataObject { return { creationTime: metadata.creationTime ? new Date(metadata.creationTime).toISOString() : null, lastSignInTime: metadata.lastSignInTime @@ -204,8 +283,8 @@ function userMetadataToObject(metadata) { * Converts a MultiFactorInfo object to a plain object. * @param {MultiFactorInfo} multiFactorInfo - The MultiFactorInfo object to convert. */ -function multiFactorInfoToObject(multiFactorInfo) { - const obj = { +function multiFactorInfoToObject(multiFactorInfo: MultiFactorInfo): MultiFactorInfoObject { + const obj: MultiFactorInfoObject = { displayName: multiFactorInfo.displayName, enrollmentTime: multiFactorInfo.enrollmentTime, factorId: multiFactorInfo.factorId, @@ -214,7 +293,9 @@ function multiFactorInfoToObject(multiFactorInfo) { // If https://firebase.google.com/docs/reference/js/auth.phonemultifactorinfo if ('phoneNumber' in multiFactorInfo) { - obj.phoneNumber = multiFactorInfo.phoneNumber; + obj.phoneNumber = ( + multiFactorInfo as MultiFactorInfo & { phoneNumber?: string | null } + ).phoneNumber; } return obj; @@ -224,28 +305,30 @@ function multiFactorInfoToObject(multiFactorInfo) { * Converts a user credential object to a plain object. * @param {UserCredential} userCredential - The user credential object to convert. */ -function authResultToObject(userCredential) { +function authResultToObject(userCredential: UserCredential): AuthResultObject { const additional = getAdditionalUserInfo(userCredential); return { user: userToObject(userCredential.user), - additionalUserInfo: { - isNewUser: additional.isNewUser, - profile: additional.profile, - providerId: additional.providerId, - username: additional.username, - }, + additionalUserInfo: additional + ? { + isNewUser: additional.isNewUser, + profile: (additional.profile as Record | null) ?? null, + providerId: additional.providerId, + username: additional.username, + } + : null, }; } -const instances = {}; -const authStateListeners = {}; -const idTokenListeners = {}; -const sessionMap = new Map(); -const totpSecretMap = new Map(); +const instances: Record = {}; +const authStateListeners: Record = {}; +const idTokenListeners: Record = {}; +const sessionMap = new Map(); +const totpSecretMap = new Map(); let sessionId = 0; // Returns a cached Firestore instance. -function getCachedAuthInstance(appName) { +function getCachedAuthInstance(appName: string): Auth { if (!instances[appName]) { if (isMemoryStorage()) { // Warn auth persistence is is disabled unless Async Storage implementation is provided. @@ -266,7 +349,7 @@ function getCachedAuthInstance(appName) { ); } - const authOptions = {}; + const authOptions: { persistence?: unknown } = {}; if (Platform.OS !== 'web') { // Non-web platforms pull the react-native export from package.json and // get a bundle that defines `getReactNativePersistence` etc, but web platforms @@ -274,13 +357,16 @@ function getCachedAuthInstance(appName) { authOptions.persistence = getReactNativePersistence(getReactNativeAsyncStorageInternal()); } - instances[appName] = initializeAuth(getApp(appName), authOptions); + instances[appName] = initializeAuth(getApp(appName), authOptions as never); } return instances[appName]; } // getConstants -const CONSTANTS = { +const CONSTANTS: { + APP_LANGUAGE: Record; + APP_USER: Record; +} = { APP_LANGUAGE: {}, APP_USER: {}, }; @@ -329,7 +415,7 @@ export default { * @param {string} appName - The name of the app to get the auth instance for. * @returns {Promise} - Void promise. */ - addAuthStateListener(appName) { + addAuthStateListener(appName: string) { if (authStateListeners[appName]) { return; } @@ -337,7 +423,7 @@ export default { return guard(async () => { const auth = getCachedAuthInstance(appName); - authStateListeners[appName] = onAuthStateChanged(auth, user => { + authStateListeners[appName] = onAuthStateChanged(auth, (user: User | null) => { emitEvent('auth_state_changed', { appName, user: user ? userToObject(user) : null, @@ -351,7 +437,7 @@ export default { * @param {string} appName - The name of the app to get the auth instance for. * @returns {Promise} - Void promise. */ - removeAuthStateListener(appName) { + removeAuthStateListener(appName: string) { if (authStateListeners[appName]) { authStateListeners[appName](); delete authStateListeners[appName]; @@ -363,7 +449,7 @@ export default { * @param {string} appName - The name of the app to get the auth instance for. * @returns {Promise} - Void promise. */ - addIdTokenListener(appName) { + addIdTokenListener(appName: string) { if (idTokenListeners[appName]) { return; } @@ -371,7 +457,7 @@ export default { return guard(async () => { const auth = getCachedAuthInstance(appName); - idTokenListeners[appName] = onIdTokenChanged(auth, user => { + idTokenListeners[appName] = onIdTokenChanged(auth, (user: User | null) => { emitEvent('auth_id_token_changed', { authenticated: !!user, appName, @@ -386,28 +472,28 @@ export default { * @param {string} appName - The name of the app to get the auth instance for. * @returns {Promise} - Void promise. */ - removeIdTokenListener(appName) { + removeIdTokenListener(appName: string) { if (idTokenListeners[appName]) { idTokenListeners[appName](); delete idTokenListeners[appName]; } }, - async forceRecaptchaFlowForTesting() { + async forceRecaptchaFlowForTesting(): Promise { return rejectPromiseWithCodeAndMessage( 'unsupported', 'This operation is not supported in this environment.', ); }, - async setAutoRetrievedSmsCodeForPhoneNumber() { + async setAutoRetrievedSmsCodeForPhoneNumber(): Promise { return rejectPromiseWithCodeAndMessage( 'unsupported', 'This operation is not supported in this environment.', ); }, - async setAppVerificationDisabledForTesting() { + async setAppVerificationDisabledForTesting(): Promise { return rejectPromiseWithCodeAndMessage( 'unsupported', 'This operation is not supported in this environment.', @@ -419,7 +505,7 @@ export default { * @param {string} appName - The name of the app to get the auth instance for. * @returns {Promise} - Void promise. */ - signOut(appName) { + signOut(appName: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); @@ -437,7 +523,7 @@ export default { * @param {*} appName - The name of the app to get the auth instance for. * @returns */ - signInAnonymously(appName) { + signInAnonymously(appName: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); const credential = await signInAnonymously(auth); @@ -452,7 +538,7 @@ export default { * @param {string} password - The password to sign in with. * @returns {Promise} - The result of the sign in. */ - async createUserWithEmailAndPassword(appName, email, password) { + async createUserWithEmailAndPassword(appName: string, email: string, password: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); const credential = await createUserWithEmailAndPassword(auth, email, password); @@ -467,7 +553,7 @@ export default { * @param {string} password - The password to sign in with. * @returns {Promise} - The result of the sign in. */ - async signInWithEmailAndPassword(appName, email, password) { + async signInWithEmailAndPassword(appName: string, email: string, password: string) { // The default guard / getWebError process doesn't work well here, // since it creates a new error object that is then passed through // a native module proxy and gets processed again. @@ -481,13 +567,14 @@ export default { password, ); return authResultToObject(credential); - } catch (e) { - e.userInfo = { - code: e.code.split('/')[1], - message: e.message, - customData: e.customData, + } catch (e: unknown) { + const error = e as WebErrorLike; + error.userInfo = { + code: error.code?.split('/')[1] ?? 'unknown', + message: error.message, + customData: error.customData, }; - throw e; + throw error; } // }); }, @@ -498,7 +585,7 @@ export default { * @param {string} emailLink - The email link to sign in with. * @returns {Promise} - Whether the link is a valid sign in with email link. */ - async isSignInWithEmailLink(appName, emailLink) { + async isSignInWithEmailLink(appName: string, emailLink: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); return await isSignInWithEmailLink(auth, emailLink); @@ -512,7 +599,7 @@ export default { * @param {string} emailLink - The email link to sign in with. * @returns {Promise} - The result of the sign in. */ - async signInWithEmailLink(appName, email, emailLink) { + async signInWithEmailLink(appName: string, email: string, emailLink: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); const credential = await signInWithEmailLink(auth, email, emailLink); @@ -526,7 +613,7 @@ export default { * @param {string} token - The token to sign in with. * @returns {Promise} - The result of the sign in. */ - async signInWithCustomToken(appName, token) { + async signInWithCustomToken(appName: string, token: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); const credential = await signInWithCustomToken(auth, token); @@ -548,7 +635,7 @@ export default { * @param {ActionCodeSettings} settings - The settings to use for the password reset email. * @returns {Promise} */ - async sendPasswordResetEmail(appName, email, settings) { + async sendPasswordResetEmail(appName: string, email: string, settings?: ActionCodeSettings) { return guard(async () => { const auth = getCachedAuthInstance(appName); await sendPasswordResetEmail(auth, email, settings); @@ -563,7 +650,7 @@ export default { * @param {ActionCodeSettings} settings - The settings to use for the password reset email. * @returns {Promise} */ - async sendSignInLinkToEmail(appName, email, settings) { + async sendSignInLinkToEmail(appName: string, email: string, settings: ActionCodeSettings) { return guard(async () => { const auth = getCachedAuthInstance(appName); await sendSignInLinkToEmail(auth, email, settings); @@ -580,7 +667,7 @@ export default { * @param {string} appName - The name of the app to get the auth instance for. * @returns {Promise} */ - async delete(appName) { + async delete(appName: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); @@ -598,7 +685,7 @@ export default { * @param {string} appName - The name of the app to get the auth instance for. * @returns {Promise} - The current user object. */ - async reload(appName) { + async reload(appName: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); @@ -617,7 +704,7 @@ export default { * @param {ActionCodeSettings} actionCodeSettings - The settings to use for the email verification. * @returns {Promise} - The current user object. */ - async sendEmailVerification(appName, actionCodeSettings) { + async sendEmailVerification(appName: string, actionCodeSettings?: ActionCodeSettings | null) { return guard(async () => { const auth = getCachedAuthInstance(appName); @@ -637,7 +724,11 @@ export default { * @param {ActionCodeSettings} actionCodeSettings - The settings to use for the email verification. * @returns {Promise} - The current user object. */ - async verifyBeforeUpdateEmail(appName, email, actionCodeSettings) { + async verifyBeforeUpdateEmail( + appName: string, + email: string, + actionCodeSettings?: ActionCodeSettings | null, + ) { return guard(async () => { const auth = getCachedAuthInstance(appName); @@ -656,7 +747,7 @@ export default { * @param {string} email - The email to update. * @returns {Promise} - The current user object. */ - async updateEmail(appName, email) { + async updateEmail(appName: string, email: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); @@ -675,7 +766,7 @@ export default { * @param {string} password - The password to update. * @returns {Promise} - The current user object. */ - async updatePassword(appName, password) { + async updatePassword(appName: string, password: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); @@ -696,7 +787,12 @@ export default { * @param {string} authSecret - The auth secret to update the phone number with. * @returns {Promise} - The current user object. */ - async updatePhoneNumber(appName, provider, authToken, authSecret) { + async updatePhoneNumber( + appName: string, + provider: string, + authToken: string, + authSecret?: string | null, + ) { return guard(async () => { const auth = getCachedAuthInstance(appName); @@ -720,7 +816,7 @@ export default { ); } - await updatePhoneNumber(auth.currentUser, credential); + await updatePhoneNumber(auth.currentUser, credential as PhoneAuthCredential); return userToObject(auth.currentUser); }); @@ -732,7 +828,10 @@ export default { * @param {object} props - The properties to update. * @returns {Promise} - The current user object. */ - async updateProfile(appName, props) { + async updateProfile( + appName: string, + props: { displayName?: string | null; photoURL?: string | null }, + ) { return guard(async () => { const auth = getCachedAuthInstance(appName); @@ -757,7 +856,12 @@ export default { * @param {string} authSecret - The auth secret to sign in with. * @returns {Promise} - The result of the sign in. */ - async signInWithCredential(appName, provider, authToken, authSecret) { + async signInWithCredential( + appName: string, + provider: string, + authToken: string, + authSecret?: string | null, + ) { return guard(async () => { const auth = getCachedAuthInstance(appName); const credential = getAuthCredential(auth, provider, authToken, authSecret); @@ -793,7 +897,7 @@ export default { * @param {string} appName - The name of the app to get the auth instance for. * @returns {Promise} - The session ID. */ - async getSession(appName) { + async getSession(appName: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); @@ -854,7 +958,7 @@ export default { * @param {string} newPassword - The new password to set. * @returns {Promise} */ - async confirmPasswordReset(appName, code, newPassword) { + async confirmPasswordReset(appName: string, code: string, newPassword: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); await confirmPasswordReset(auth, code, newPassword); @@ -868,7 +972,7 @@ export default { * @param {string} code - The code to apply. * @returns {Promise} - Void promise. */ - async applyActionCode(appName, code) { + async applyActionCode(appName: string, code: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); await applyActionCode(auth, code); @@ -881,7 +985,7 @@ export default { * @param {string} code - The code to check. * @returns {Promise} - The result of the check. */ - async checkActionCode(appName, code) { + async checkActionCode(appName: string, code: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); const result = await checkActionCode(auth, code); @@ -905,7 +1009,12 @@ export default { * @param {string} authSecret - The auth secret to link. * @returns {Promise} - The current user object. */ - async linkWithCredential(appName, provider, authToken, authSecret) { + async linkWithCredential( + appName: string, + provider: string, + authToken: string, + authSecret?: string | null, + ) { return guard(async () => { const auth = getCachedAuthInstance(appName); const credential = getAuthCredential(auth, provider, authToken, authSecret); @@ -939,7 +1048,7 @@ export default { * @param {string} providerId - The provider ID to unlink. * @returns {Promise} - The current user object. */ - async unlink(appName, providerId) { + async unlink(appName: string, providerId: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); @@ -960,7 +1069,12 @@ export default { * @param {string} authSecret - The auth secret to reauthenticate with. * @returns {Promise} - The current user object. */ - async reauthenticateWithCredential(appName, provider, authToken, authSecret) { + async reauthenticateWithCredential( + appName: string, + provider: string, + authToken: string, + authSecret?: string | null, + ) { return guard(async () => { const auth = getCachedAuthInstance(appName); const credential = getAuthCredential(auth, provider, authToken, authSecret); @@ -994,7 +1108,7 @@ export default { * @param {boolean} forceRefresh - Whether to force a token refresh. * @returns {Promise} - The ID token. */ - async getIdToken(appName, forceRefresh) { + async getIdToken(appName: string, forceRefresh: boolean) { return guard(async () => { const auth = getCachedAuthInstance(appName); @@ -1013,7 +1127,7 @@ export default { * @param {boolean} forceRefresh - Whether to force a token refresh. * @returns {Promise} - The ID token result. */ - async getIdTokenResult(appName, forceRefresh) { + async getIdTokenResult(appName: string, forceRefresh: boolean) { return guard(async () => { const auth = getCachedAuthInstance(appName); @@ -1042,7 +1156,7 @@ export default { * @param {*} code the code from the user TOTP app * @return TotpMultiFactorAssertion to use for resolving */ - assertionForSignIn(_appName, uid, code) { + assertionForSignIn(_appName: string, uid: string, code: string) { return TotpMultiFactorGenerator.assertionForSignIn(uid, code); }, @@ -1052,7 +1166,7 @@ export default { * @param {*} error the MFA error returned from initial factor login attempt * @return MultiFactorResolver to use for verifying the second factor */ - getMultiFactorResolver(appName, error) { + getMultiFactorResolver(appName: string, error: MultiFactorError): MultiFactorResolver | null { return getMultiFactorResolver(getCachedAuthInstance(appName), error); }, @@ -1062,9 +1176,16 @@ export default { * @param {*} session - The MultiFactorSession to associate with the secret * @returns object with secretKey to associate with TotpSecret */ - async generateTotpSecret(_appName, session) { + async generateTotpSecret(_appName: string, session: string) { return guard(async () => { - const totpSecret = await TotpMultiFactorGenerator.generateSecret(sessionMap.get(session)); + const mappedSession = sessionMap.get(session); + if (!mappedSession) { + return rejectPromiseWithCodeAndMessage( + 'invalid-multi-factor-session', + 'The supplied multi-factor session is invalid or has expired.', + ); + } + const totpSecret = await TotpMultiFactorGenerator.generateSecret(mappedSession); totpSecretMap.set(totpSecret.secretKey, totpSecret); return { secretKey: totpSecret.secretKey }; }); @@ -1076,13 +1197,14 @@ export default { * @param {*} enrollmentId - The ID to associate with the enrollment * @returns */ - async unenrollMultiFactor(appName, enrollmentId) { + async unenrollMultiFactor(appName: string, enrollmentId: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); if (auth.currentUser === null) { return promiseNoUser(true); } await multiFactor(auth.currentUser).unenroll(enrollmentId); + return promiseNoUser(); }); }, @@ -1094,17 +1216,30 @@ export default { * @param {*} displayName - The name to associate as a hint * @returns */ - async finalizeTotpEnrollment(appName, secretKey, verificationCode, displayName) { + async finalizeTotpEnrollment( + appName: string, + secretKey: string, + verificationCode: string, + displayName?: string | null, + ) { return guard(async () => { const auth = getCachedAuthInstance(appName); if (auth.currentUser === null) { return promiseNoUser(true); } + const totpSecret = totpSecretMap.get(secretKey); + if (!totpSecret) { + return rejectPromiseWithCodeAndMessage( + 'invalid-multi-factor-secret', + "can't find secret for provided key", + ); + } const multiFactorAssertion = TotpMultiFactorGenerator.assertionForEnrollment( - totpSecretMap.get(secretKey), + totpSecret, verificationCode, ); await multiFactor(auth.currentUser).enroll(multiFactorAssertion, displayName); + return promiseNoUser(); }); }, @@ -1116,8 +1251,15 @@ export default { * @param {*} issuer - The issuer to use in auth app * @returns QR Code URL */ - generateQrCodeUrl(_appName, secretKey, accountName, issuer) { - return totpSecretMap.get(secretKey).generateQrCodeUrl(accountName, issuer); + generateQrCodeUrl(_appName: string, secretKey: string, accountName?: string, issuer?: string) { + const totpSecret = totpSecretMap.get(secretKey); + if (!totpSecret) { + return rejectPromiseWithCodeAndMessage( + 'invalid-multi-factor-secret', + "can't find secret for provided key", + ); + } + return totpSecret.generateQrCodeUrl(accountName, issuer); }, /** @@ -1143,7 +1285,7 @@ export default { * @param {string} email - The email to fetch the sign in methods for. * @returns {Promise} - The sign in methods for the email. */ - async fetchSignInMethodsForEmail(appName, email) { + async fetchSignInMethodsForEmail(appName: string, email: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); const methods = await fetchSignInMethodsForEmail(auth, email); @@ -1157,7 +1299,7 @@ export default { * @param {string} code - The language code to set. * @returns {void} */ - setLanguageCode(appName, code) { + setLanguageCode(appName: string, code: string | null) { return guard(async () => { const auth = getCachedAuthInstance(appName); auth.languageCode = code; @@ -1170,7 +1312,7 @@ export default { * @param {string} tenantId - The tenant ID to set. * @returns {void} */ - setTenantId(appName, tenantId) { + setTenantId(appName: string, tenantId: string | null) { return guard(async () => { const auth = getCachedAuthInstance(appName); auth.tenantId = tenantId; @@ -1182,7 +1324,7 @@ export default { * @param {string} appName - The name of the app to get the auth instance for. * @returns void */ - useDeviceLanguage(appName) { + useDeviceLanguage(appName: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); useDeviceLanguage(auth); @@ -1193,7 +1335,7 @@ export default { * Verify the provided password reset code. * @returns {string} - The users email address if valid. */ - verifyPasswordResetCode(appName, code) { + verifyPasswordResetCode(appName: string, code: string) { return guard(async () => { const auth = getCachedAuthInstance(appName); const email = await verifyPasswordResetCode(auth, code); @@ -1208,7 +1350,7 @@ export default { * @param {number} port - The port to use for the auth emulator. * @returns {void} */ - useEmulator(appName, host, port) { + useEmulator(appName: string, host: string, port: number) { return guard(async () => { const auth = getCachedAuthInstance(appName); connectAuthEmulator(auth, `http://${host}:${port}`); From 0507718424a70895d0317df58e40f6423c124f34 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 24 Apr 2026 16:25:04 +0100 Subject: [PATCH 16/45] fix(auth): phoneauthprovider, remove additional native call --- packages/auth/lib/providers/PhoneAuthProvider.ts | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/packages/auth/lib/providers/PhoneAuthProvider.ts b/packages/auth/lib/providers/PhoneAuthProvider.ts index cfd4c62185..6ea6a11b38 100644 --- a/packages/auth/lib/providers/PhoneAuthProvider.ts +++ b/packages/auth/lib/providers/PhoneAuthProvider.ts @@ -96,16 +96,6 @@ export default class PhoneAuthProvider { ); } - if (isPhoneMultiFactorUidOptions(phoneInfoOptions)) { - // The native bridge only needs the enrollment uid for MFA sign-in verification. - return this._auth.app - .auth() - .verifyPhoneNumberWithMultiFactorInfo( - { uid: phoneInfoOptions.multiFactorUid }, - phoneInfoOptions.session, - ); - } - if (isPhoneMultiFactorEnrollOptions(phoneInfoOptions)) { return this._auth.app.auth().verifyPhoneNumberForMultiFactor(phoneInfoOptions); } From c33df005678312ec479de49f61c01f94f392f31c Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 27 Apr 2026 09:53:27 +0100 Subject: [PATCH 17/45] refactor: auth and internal auth type --- .../compare-types/packages/auth/config.ts | 5 -- packages/auth/lib/modular.ts | 23 +++---- packages/auth/lib/types/auth.ts | 16 +++-- packages/auth/lib/types/internal.ts | 60 ++++++++++++++++++- 4 files changed, 72 insertions(+), 32 deletions(-) diff --git a/.github/scripts/compare-types/packages/auth/config.ts b/.github/scripts/compare-types/packages/auth/config.ts index 607660ae48..f0055a1ff0 100644 --- a/.github/scripts/compare-types/packages/auth/config.ts +++ b/.github/scripts/compare-types/packages/auth/config.ts @@ -200,11 +200,6 @@ const config: PackageConfig = { reason: 'RN Firebase accepts the broader AuthCredential surface, while the firebase-js-sdk narrows this parameter to PhoneAuthCredential.', }, - { - name: 'Auth', - reason: - 'The public Auth surface now matches structurally, but the emitted declaration text still differs from the firebase-js-sdk because RN Firebase uses its local FirebaseApp and NextOrObserver spellings in the generated interface.', - }, { name: 'FacebookAuthProvider', reason: diff --git a/packages/auth/lib/modular.ts b/packages/auth/lib/modular.ts index 2e8f00c95f..cf190d4716 100644 --- a/packages/auth/lib/modular.ts +++ b/packages/auth/lib/modular.ts @@ -58,7 +58,7 @@ import type { UserCredential, } from './types/auth'; import type { FirebaseAuthTypes } from './types/namespaced'; -import type { UserInternal } from './types/internal'; +import type { AuthInternal, UserInternal } from './types/internal'; type AnyFn = (...args: any[]) => any; @@ -66,29 +66,20 @@ type WithModularDeprecationArg = ( ...args: [...Parameters, typeof MODULAR_DEPRECATION_ARG] ) => ReturnType; -type AuthModuleInternal = FirebaseAuthTypes.Module & { - validatePassword(password: string): Promise; - getCustomAuthDomain(): Promise; -}; - type UserModuleInternal = UserInternal; type AuthProviderWithObjectInternal = FirebaseAuthTypes.AuthProvider & { toObject(): Record; }; -function getAuthInternal(auth: Auth): AuthModuleInternal { - return auth as unknown as AuthModuleInternal; +function getAuthInternal(auth: Auth): AuthInternal { + return auth as unknown as AuthInternal; } function getUserInternal(user: User): UserModuleInternal { return user as unknown as UserModuleInternal; } -function asAuth(auth: FirebaseAuthTypes.Module): Auth { - return auth as unknown as Auth; -} - function asActionCodeInfo( promise: Promise, ): Promise { @@ -143,7 +134,7 @@ function normalizeAuthListener( } function callAuthMethod( - auth: AuthModuleInternal, + auth: AuthInternal, method: F, ...args: Parameters ): ReturnType { @@ -171,17 +162,17 @@ function callUserMethod( */ export function getAuth(app?: FirebaseApp): Auth { if (app) { - return asAuth(getApp(app.name).auth()); + return getApp(app.name).auth() as unknown as Auth; } - return asAuth(getApp().auth()); + return getApp().auth() as unknown as Auth; } /** * This function allows more control over the Auth instance than getAuth(). */ export function initializeAuth(app: FirebaseApp, _deps?: Dependencies): Auth { - return asAuth(getApp(app.name).auth()); + return getApp(app.name).auth() as unknown as Auth; } export function applyActionCode(auth: Auth, oobCode: string): Promise { diff --git a/packages/auth/lib/types/auth.ts b/packages/auth/lib/types/auth.ts index 084435779d..579fbe045e 100644 --- a/packages/auth/lib/types/auth.ts +++ b/packages/auth/lib/types/auth.ts @@ -15,7 +15,7 @@ * */ -import type { ReactNativeFirebase } from '@react-native-firebase/app'; +import type { FirebaseApp, ReactNativeFirebase } from '@react-native-firebase/app'; import type { FirebaseAuthTypes } from './namespaced'; export type CompleteFn = () => void; @@ -29,8 +29,6 @@ interface Observer { complete?: CompleteFn | null; } -type FirebaseApp = ReactNativeFirebase.FirebaseApp; - export const ActionCodeOperation = { EMAIL_SIGNIN: 'EMAIL_SIGNIN', PASSWORD_RESET: 'PASSWORD_RESET', @@ -70,7 +68,7 @@ export const SignInMethod = { TWITTER: 'twitter.com', } as const; -export type Auth = { +export interface Auth { readonly app: FirebaseApp; readonly name: string; readonly config: Config; @@ -79,7 +77,7 @@ export type Auth = { tenantId: string | null; readonly settings: AuthSettings; onAuthStateChanged( - nextOrObserver: NextOrObserver, + nextOrObserver: NextOrObserver, error?: ErrorFn, completed?: CompleteFn, ): Unsubscribe; @@ -88,17 +86,17 @@ export type Auth = { onAbort?: () => void, ): Unsubscribe; onIdTokenChanged( - nextOrObserver: NextOrObserver, + nextOrObserver: NextOrObserver, error?: ErrorFn, completed?: CompleteFn, ): Unsubscribe; - authStateReady?: () => Promise; + authStateReady(): Promise; readonly currentUser: User | null; - readonly emulatorConfig?: EmulatorConfig | null; + readonly emulatorConfig: EmulatorConfig | null; updateCurrentUser(user: User | null): Promise; useDeviceLanguage(): void; signOut(): Promise; -}; +} export interface AuthError extends ReactNativeFirebase.NativeFirebaseError { readonly customData: { diff --git a/packages/auth/lib/types/internal.ts b/packages/auth/lib/types/internal.ts index c3f582b46d..25975715d5 100644 --- a/packages/auth/lib/types/internal.ts +++ b/packages/auth/lib/types/internal.ts @@ -22,7 +22,8 @@ import type { NativeErrorUserInfo, } from '@react-native-firebase/app/dist/module/types/internal'; import type EventEmitter from 'react-native/Libraries/vendor/emitter/EventEmitter'; -import type { FirebaseAuthTypes } from './namespaced'; +import type { Auth } from './auth'; +import type { CallbackOrObserver, FirebaseAuthTypes } from './namespaced'; export interface NativeUserMetadataInternal { creationTime: string; @@ -270,9 +271,64 @@ export interface RNFBAuthModule { ): { uid: string; verificationCode: string }; } -export type AuthInternal = { +export type AuthInternal = Auth & { app: ReactNativeFirebase.FirebaseApp; currentUser: FirebaseAuthTypes.User | null; + applyActionCode(code: string): Promise; + checkActionCode(code: string): Promise; + confirmPasswordReset(code: string, newPassword: string): Promise; + createUserWithEmailAndPassword( + email: string, + password: string, + ): Promise; + fetchSignInMethodsForEmail(email: string): Promise; + getCustomAuthDomain(): Promise; + getMultiFactorResolver(error: unknown): FirebaseAuthTypes.MultiFactorResolver | null; + isSignInWithEmailLink(emailLink: string): Promise; + onAuthStateChanged( + listenerOrObserver: CallbackOrObserver, + ): () => void; + onIdTokenChanged( + listenerOrObserver: CallbackOrObserver, + ): () => void; + sendPasswordResetEmail( + email: string, + actionCodeSettings?: FirebaseAuthTypes.ActionCodeSettings | null, + ): Promise; + sendSignInLinkToEmail( + email: string, + actionCodeSettings?: FirebaseAuthTypes.ActionCodeSettings, + ): Promise; + setLanguageCode(code: string | null): Promise; + signInAnonymously(): Promise; + signInWithCredential( + credential: FirebaseAuthTypes.AuthCredential, + ): Promise; + signInWithCustomToken(customToken: string): Promise; + signInWithEmailAndPassword( + email: string, + password: string, + ): Promise; + signInWithEmailLink(email: string, emailLink: string): Promise; + signInWithPhoneNumber( + phoneNumber: string, + forceResend?: boolean, + ): Promise; + signInWithPopup( + provider: FirebaseAuthTypes.AuthProvider, + ): Promise; + signInWithRedirect( + provider: FirebaseAuthTypes.AuthProvider, + ): Promise; + signOut(): Promise; + useEmulator(url: string): void; + useUserAccessGroup(userAccessGroup: string): Promise; + verifyPhoneNumber( + phoneNumber: string, + autoVerifyTimeoutOrForceResend?: number | boolean, + forceResend?: boolean, + ): FirebaseAuthTypes.PhoneAuthListener; + verifyPasswordResetCode(code: string): Promise; native: RNFBAuthModule; emitter: EventEmitter; eventNameForApp(...args: Array): string; From e70785c0b8a338584e0c6b3348feb19d16825fee Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 27 Apr 2026 11:08:13 +0100 Subject: [PATCH 18/45] refactor: use modular types rather than deprecated namespace types --- packages/auth/lib/modular.ts | 189 +++++++++------------------- packages/auth/lib/types/internal.ts | 101 +++++++++++---- 2 files changed, 135 insertions(+), 155 deletions(-) diff --git a/packages/auth/lib/modular.ts b/packages/auth/lib/modular.ts index cf190d4716..437a235aa7 100644 --- a/packages/auth/lib/modular.ts +++ b/packages/auth/lib/modular.ts @@ -32,7 +32,6 @@ import PhoneAuthProvider from './providers/PhoneAuthProvider'; import TwitterAuthProvider from './providers/TwitterAuthProvider'; import type { FirebaseApp } from '@react-native-firebase/app'; import type { - ActionCodeInfo, ActionCodeSettings, ActionCodeURL, AdditionalUserInfo, @@ -58,19 +57,23 @@ import type { UserCredential, } from './types/auth'; import type { FirebaseAuthTypes } from './types/namespaced'; -import type { AuthInternal, UserInternal } from './types/internal'; +import type { + AppWithAuthInternal, + AuthInternal, + AuthListenerCallbackInternal, + AuthProviderWithObjectInternal, + UserCredentialWithAdditionalUserInfoInternal, + UserInternal, + WithAuthDeprecationArg, +} from './types/internal'; type AnyFn = (...args: any[]) => any; -type WithModularDeprecationArg = ( - ...args: [...Parameters, typeof MODULAR_DEPRECATION_ARG] -) => ReturnType; - type UserModuleInternal = UserInternal; -type AuthProviderWithObjectInternal = FirebaseAuthTypes.AuthProvider & { - toObject(): Record; -}; +function appWithAuth(app?: FirebaseApp): AppWithAuthInternal { + return (app ? getApp(app.name) : getApp()) as unknown as AppWithAuthInternal; +} function getAuthInternal(auth: Auth): AuthInternal { return auth as unknown as AuthInternal; @@ -80,28 +83,6 @@ function getUserInternal(user: User): UserModuleInternal { return user as unknown as UserModuleInternal; } -function asActionCodeInfo( - promise: Promise, -): Promise { - return promise as unknown as Promise; -} - -function asUserCredential( - promise: Promise, -): Promise { - return promise as unknown as Promise; -} - -function asIdTokenResult( - promise: Promise, -): Promise { - return promise as unknown as Promise; -} - -function asUser(promise: Promise): Promise { - return promise as unknown as Promise; -} - export { AppleAuthProvider, EmailAuthProvider, @@ -120,15 +101,15 @@ export { function normalizeAuthListener( nextOrObserver: NextOrObserver, -): FirebaseAuthTypes.AuthListenerCallback | { next: FirebaseAuthTypes.AuthListenerCallback } { +): AuthListenerCallbackInternal | { next: AuthListenerCallbackInternal } { if (typeof nextOrObserver === 'function') { - return nextOrObserver as unknown as FirebaseAuthTypes.AuthListenerCallback; + return nextOrObserver as AuthListenerCallbackInternal; } return { next: typeof nextOrObserver.next === 'function' - ? (nextOrObserver.next as unknown as FirebaseAuthTypes.AuthListenerCallback) + ? (nextOrObserver.next as AuthListenerCallbackInternal) : () => {}, }; } @@ -138,7 +119,7 @@ function callAuthMethod( method: F, ...args: Parameters ): ReturnType { - return (method as unknown as WithModularDeprecationArg).call( + return (method as unknown as WithAuthDeprecationArg).call( auth, ...args, MODULAR_DEPRECATION_ARG, @@ -150,7 +131,7 @@ function callUserMethod( method: F, ...args: Parameters ): ReturnType { - return (method as unknown as WithModularDeprecationArg).call( + return (method as unknown as WithAuthDeprecationArg).call( user, ...args, MODULAR_DEPRECATION_ARG, @@ -161,18 +142,14 @@ function callUserMethod( * Returns the Auth instance associated with the provided FirebaseApp. */ export function getAuth(app?: FirebaseApp): Auth { - if (app) { - return getApp(app.name).auth() as unknown as Auth; - } - - return getApp().auth() as unknown as Auth; + return appWithAuth(app).auth(MODULAR_DEPRECATION_ARG); } /** * This function allows more control over the Auth instance than getAuth(). */ export function initializeAuth(app: FirebaseApp, _deps?: Dependencies): Auth { - return getApp(app.name).auth() as unknown as Auth; + return appWithAuth(app).auth(MODULAR_DEPRECATION_ARG); } export function applyActionCode(auth: Auth, oobCode: string): Promise { @@ -188,9 +165,9 @@ export function beforeAuthStateChanged( throw new Error('beforeAuthStateChanged is unsupported by the native Firebase SDKs'); } -export function checkActionCode(auth: Auth, oobCode: string): Promise { +export function checkActionCode(auth: Auth, oobCode: string) { const authInternal = getAuthInternal(auth); - return asActionCodeInfo(callAuthMethod(authInternal, authInternal.checkActionCode, oobCode)); + return callAuthMethod(authInternal, authInternal.checkActionCode, oobCode); } export function confirmPasswordReset( @@ -217,9 +194,7 @@ export function createUserWithEmailAndPassword( password: string, ): Promise { const authInternal = getAuthInternal(auth); - return asUserCredential( - callAuthMethod(authInternal, authInternal.createUserWithEmailAndPassword, email, password), - ); + return callAuthMethod(authInternal, authInternal.createUserWithEmailAndPassword, email, password); } export function fetchSignInMethodsForEmail(auth: Auth, email: string): Promise { @@ -229,13 +204,7 @@ export function fetchSignInMethodsForEmail(auth: Auth, email: string): Promise FirebaseAuthTypes.MultiFactorResolver, - error, - ) as unknown as MultiFactorResolver; + return callAuthMethod(authInternal, authInternal.getMultiFactorResolver, error) as MultiFactorResolver; } export function getRedirectResult( @@ -261,11 +230,7 @@ export function onAuthStateChanged( const authInternal = getAuthInternal(auth); return callAuthMethod( authInternal, - authInternal.onAuthStateChanged as unknown as ( - nextOrObserver: - | FirebaseAuthTypes.AuthListenerCallback - | { next: FirebaseAuthTypes.AuthListenerCallback }, - ) => Unsubscribe, + authInternal.onAuthStateChanged, normalizeAuthListener(nextOrObserver), ); } @@ -281,11 +246,7 @@ export function onIdTokenChanged( const authInternal = getAuthInternal(auth); return callAuthMethod( authInternal, - authInternal.onIdTokenChanged as unknown as ( - nextOrObserver: - | FirebaseAuthTypes.AuthListenerCallback - | { next: FirebaseAuthTypes.AuthListenerCallback }, - ) => Unsubscribe, + authInternal.onIdTokenChanged, normalizeAuthListener(nextOrObserver), ); } @@ -328,7 +289,7 @@ export function setPersistence(_auth: Auth, _persistence: Persistence): Promise< export function signInAnonymously(auth: Auth): Promise { const authInternal = getAuthInternal(auth); - return asUserCredential(callAuthMethod(authInternal, authInternal.signInAnonymously)); + return callAuthMethod(authInternal, authInternal.signInAnonymously); } export function signInWithCredential( @@ -336,16 +297,12 @@ export function signInWithCredential( credential: AuthCredential, ): Promise { const authInternal = getAuthInternal(auth); - return asUserCredential( - callAuthMethod(authInternal, authInternal.signInWithCredential, credential), - ); + return callAuthMethod(authInternal, authInternal.signInWithCredential, credential); } export function signInWithCustomToken(auth: Auth, customToken: string): Promise { const authInternal = getAuthInternal(auth); - return asUserCredential( - callAuthMethod(authInternal, authInternal.signInWithCustomToken, customToken), - ); + return callAuthMethod(authInternal, authInternal.signInWithCustomToken, customToken); } export function signInWithEmailAndPassword( @@ -354,9 +311,7 @@ export function signInWithEmailAndPassword( password: string, ): Promise { const authInternal = getAuthInternal(auth); - return asUserCredential( - callAuthMethod(authInternal, authInternal.signInWithEmailAndPassword, email, password), - ); + return callAuthMethod(authInternal, authInternal.signInWithEmailAndPassword, email, password); } export function signInWithEmailLink( @@ -365,9 +320,7 @@ export function signInWithEmailLink( emailLink: string, ): Promise { const authInternal = getAuthInternal(auth); - return asUserCredential( - callAuthMethod(authInternal, authInternal.signInWithEmailLink, email, emailLink), - ); + return callAuthMethod(authInternal, authInternal.signInWithEmailLink, email, emailLink); } export function signInWithPhoneNumber( @@ -378,11 +331,7 @@ export function signInWithPhoneNumber( // Native SDKs own the verification flow, so the modular wrapper intentionally ignores the // JS SDK's optional ApplicationVerifier and forwards only the phone number. const authInternal = getAuthInternal(auth); - const signInWithPhoneNumberInternal = authInternal.signInWithPhoneNumber as unknown as ( - phoneNumber: string, - ) => Promise; - - return callAuthMethod(authInternal, signInWithPhoneNumberInternal, phoneNumber); + return callAuthMethod(authInternal, authInternal.signInWithPhoneNumber, phoneNumber); } export function verifyPhoneNumber( @@ -392,20 +341,12 @@ export function verifyPhoneNumber( forceResend?: boolean, ): PhoneAuthListener { const authInternal = getAuthInternal(auth); - return ( - authInternal.verifyPhoneNumber as unknown as WithModularDeprecationArg< - ( - phoneNumber: string, - autoVerifyTimeoutOrForceResend?: number | boolean, - forceResend?: boolean, - ) => PhoneAuthListener - > - ).call( + return callAuthMethod( authInternal, + authInternal.verifyPhoneNumber, phoneNumber, autoVerifyTimeoutOrForceResend, forceResend, - MODULAR_DEPRECATION_ARG, ); } @@ -415,12 +356,10 @@ export function signInWithPopup( _resolver?: PopupRedirectResolver, ): Promise { const authInternal = getAuthInternal(auth); - return asUserCredential( - callAuthMethod( - authInternal, - authInternal.signInWithPopup, - provider as unknown as AuthProviderWithObjectInternal, - ), + return callAuthMethod( + authInternal, + authInternal.signInWithPopup, + provider as unknown as AuthProviderWithObjectInternal, ); } @@ -432,12 +371,10 @@ export function signInWithRedirect( // Native provider flows complete immediately and return a credential instead of following the // browser redirect contract from the Firebase JS SDK. const authInternal = getAuthInternal(auth); - return asUserCredential( - callAuthMethod( - authInternal, - authInternal.signInWithRedirect, - provider as unknown as AuthProviderWithObjectInternal, - ), + return callAuthMethod( + authInternal, + authInternal.signInWithRedirect, + provider as unknown as AuthProviderWithObjectInternal, ); } @@ -487,7 +424,7 @@ export function getIdToken(user: User, forceRefresh?: boolean): Promise export function getIdTokenResult(user: User, forceRefresh?: boolean): Promise { const userInternal = getUserInternal(user); - return asIdTokenResult(callUserMethod(userInternal, userInternal.getIdTokenResult, forceRefresh)); + return callUserMethod(userInternal, userInternal.getIdTokenResult, forceRefresh); } export function linkWithCredential( @@ -495,9 +432,7 @@ export function linkWithCredential( credential: AuthCredential, ): Promise { const userInternal = getUserInternal(user); - return asUserCredential( - callUserMethod(userInternal, userInternal.linkWithCredential, credential), - ); + return callUserMethod(userInternal, userInternal.linkWithCredential, credential); } export function linkWithPhoneNumber( @@ -514,12 +449,10 @@ export function linkWithPopup( _resolver?: PopupRedirectResolver, ): Promise { const userInternal = getUserInternal(user); - return asUserCredential( - callUserMethod( - userInternal, - userInternal.linkWithPopup, - provider as unknown as AuthProviderWithObjectInternal, - ), + return callUserMethod( + userInternal, + userInternal.linkWithPopup, + provider as unknown as AuthProviderWithObjectInternal, ); } @@ -531,12 +464,10 @@ export function linkWithRedirect( // Native provider flows complete immediately and return a credential instead of following the // browser redirect contract from the Firebase JS SDK. const userInternal = getUserInternal(user); - return asUserCredential( - callUserMethod( - userInternal, - userInternal.linkWithRedirect, - provider as unknown as AuthProviderWithObjectInternal, - ), + return callUserMethod( + userInternal, + userInternal.linkWithRedirect, + provider as unknown as AuthProviderWithObjectInternal, ); } @@ -553,9 +484,7 @@ export function reauthenticateWithCredential( credential: AuthCredential, ): Promise { const userInternal = getUserInternal(user); - return asUserCredential( - callUserMethod(userInternal, userInternal.reauthenticateWithCredential, credential), - ); + return callUserMethod(userInternal, userInternal.reauthenticateWithCredential, credential); } export function reauthenticateWithPhoneNumber( @@ -572,12 +501,10 @@ export function reauthenticateWithPopup( _resolver?: PopupRedirectResolver, ): Promise { const userInternal = getUserInternal(user); - return asUserCredential( - callUserMethod( - userInternal, - userInternal.reauthenticateWithPopup, - provider as unknown as AuthProviderWithObjectInternal, - ), + return callUserMethod( + userInternal, + userInternal.reauthenticateWithPopup, + provider as unknown as AuthProviderWithObjectInternal, ); } @@ -613,7 +540,7 @@ export function sendEmailVerification( export function unlink(user: User, providerId: string): Promise { const userInternal = getUserInternal(user); - return asUser(callUserMethod(userInternal, userInternal.unlink, providerId)); + return callUserMethod(userInternal, userInternal.unlink, providerId); } export function updateEmail(user: User, newEmail: string): Promise { @@ -657,7 +584,7 @@ export function verifyBeforeUpdateEmail( } export function getAdditionalUserInfo(userCredential: UserCredential): AdditionalUserInfo | null { - const info = (userCredential as unknown as FirebaseAuthTypes.UserCredential).additionalUserInfo; + const info = (userCredential as UserCredentialWithAdditionalUserInfoInternal).additionalUserInfo; if (!info) { return null; } diff --git a/packages/auth/lib/types/internal.ts b/packages/auth/lib/types/internal.ts index 25975715d5..cb3820a169 100644 --- a/packages/auth/lib/types/internal.ts +++ b/packages/auth/lib/types/internal.ts @@ -22,9 +22,41 @@ import type { NativeErrorUserInfo, } from '@react-native-firebase/app/dist/module/types/internal'; import type EventEmitter from 'react-native/Libraries/vendor/emitter/EventEmitter'; -import type { Auth } from './auth'; +import type { + ActionCodeInfo, + ActionCodeSettings, + Auth, + AuthCredential, + ConfirmationResult, + IdTokenResult, + MultiFactorResolver, + PhoneAuthListener, + User, + UserCredential, +} from './auth'; import type { CallbackOrObserver, FirebaseAuthTypes } from './namespaced'; +export type AuthModularDeprecationArg = string; + +export type WithAuthDeprecationArg = F extends (...args: infer P) => infer R + ? (...args: [...P, AuthModularDeprecationArg]) => R + : never; + +export interface AppWithAuthInternal { + auth(deprecationArg?: AuthModularDeprecationArg): Auth; +} + +export type AuthListenerCallbackInternal = (user: User | null) => void; + +export type AuthProviderWithObjectInternal = FirebaseAuthTypes.AuthProvider & { + toObject(): Record; +}; + +export type UserCredentialWithAdditionalUserInfoInternal = UserCredential & { + user: FirebaseAuthTypes.User; + additionalUserInfo?: FirebaseAuthTypes.AdditionalUserInfo; +}; + export interface NativeUserMetadataInternal { creationTime: string; lastSignInTime: string; @@ -275,51 +307,52 @@ export type AuthInternal = Auth & { app: ReactNativeFirebase.FirebaseApp; currentUser: FirebaseAuthTypes.User | null; applyActionCode(code: string): Promise; - checkActionCode(code: string): Promise; + checkActionCode(code: string): Promise; confirmPasswordReset(code: string, newPassword: string): Promise; createUserWithEmailAndPassword( email: string, password: string, - ): Promise; + ): Promise; fetchSignInMethodsForEmail(email: string): Promise; getCustomAuthDomain(): Promise; - getMultiFactorResolver(error: unknown): FirebaseAuthTypes.MultiFactorResolver | null; + getMultiFactorResolver(error: unknown): MultiFactorResolver | null; isSignInWithEmailLink(emailLink: string): Promise; onAuthStateChanged( - listenerOrObserver: CallbackOrObserver, + listenerOrObserver: CallbackOrObserver, ): () => void; onIdTokenChanged( - listenerOrObserver: CallbackOrObserver, + listenerOrObserver: CallbackOrObserver, ): () => void; sendPasswordResetEmail( email: string, - actionCodeSettings?: FirebaseAuthTypes.ActionCodeSettings | null, + actionCodeSettings?: ActionCodeSettings | null, ): Promise; sendSignInLinkToEmail( email: string, - actionCodeSettings?: FirebaseAuthTypes.ActionCodeSettings, + actionCodeSettings?: ActionCodeSettings, ): Promise; setLanguageCode(code: string | null): Promise; - signInAnonymously(): Promise; - signInWithCredential( - credential: FirebaseAuthTypes.AuthCredential, - ): Promise; - signInWithCustomToken(customToken: string): Promise; + signInAnonymously(): Promise; + signInWithCredential(credential: AuthCredential): Promise; + signInWithCustomToken(customToken: string): Promise; signInWithEmailAndPassword( email: string, password: string, - ): Promise; - signInWithEmailLink(email: string, emailLink: string): Promise; + ): Promise; + signInWithEmailLink( + email: string, + emailLink: string, + ): Promise; signInWithPhoneNumber( phoneNumber: string, forceResend?: boolean, - ): Promise; + ): Promise; signInWithPopup( - provider: FirebaseAuthTypes.AuthProvider, - ): Promise; + provider: AuthProviderWithObjectInternal, + ): Promise; signInWithRedirect( - provider: FirebaseAuthTypes.AuthProvider, - ): Promise; + provider: AuthProviderWithObjectInternal, + ): Promise; signOut(): Promise; useEmulator(url: string): void; useUserAccessGroup(userAccessGroup: string): Promise; @@ -327,7 +360,7 @@ export type AuthInternal = Auth & { phoneNumber: string, autoVerifyTimeoutOrForceResend?: number | boolean, forceResend?: boolean, - ): FirebaseAuthTypes.PhoneAuthListener; + ): PhoneAuthListener; verifyPasswordResetCode(code: string): Promise; native: RNFBAuthModule; emitter: EventEmitter; @@ -339,21 +372,41 @@ export type AuthInternal = Auth & { _setUser(user?: NativeUserInternal | null): FirebaseAuthTypes.User | null; _setUserCredential( userCredential: NativeUserCredentialInternal, - ): FirebaseAuthTypes.UserCredential; + ): UserCredentialWithAdditionalUserInfoInternal; resolveMultiFactorSignIn( session: FirebaseAuthTypes.MultiFactorSession, verificationId: string, verificationCode: string, - ): Promise; + ): Promise; resolveTotpSignIn( session: FirebaseAuthTypes.MultiFactorSession, uid: string, totpSecret: string, - ): Promise; + ): Promise; } & PasswordPolicyMixinInternal; export type UserInternal = FirebaseAuthTypes.User & { _auth?: AuthInternal; + getIdTokenResult(forceRefresh?: boolean): Promise; + linkWithCredential(credential: AuthCredential): Promise; + linkWithPopup(provider: AuthProviderWithObjectInternal): Promise; + linkWithRedirect( + provider: AuthProviderWithObjectInternal, + ): Promise; + reauthenticateWithCredential( + credential: AuthCredential, + ): Promise; + reauthenticateWithPopup( + provider: AuthProviderWithObjectInternal, + ): Promise; + reauthenticateWithRedirect(provider: AuthProviderWithObjectInternal): Promise; + sendEmailVerification(actionCodeSettings?: ActionCodeSettings): Promise; + unlink(providerId: string): Promise; + updateEmail(email: string): Promise; + updatePassword(password: string): Promise; + updatePhoneNumber(credential: AuthCredential): Promise; + updateProfile(updates: { displayName?: string | null; photoURL?: string | null }): Promise; + verifyBeforeUpdateEmail(newEmail: string, actionCodeSettings?: ActionCodeSettings): Promise; }; export type ConfirmationResultInternal = FirebaseAuthTypes.ConfirmationResult; From 94cbcb237649c97611e68ef0cbb83c2e0b301ae6 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 27 Apr 2026 11:18:25 +0100 Subject: [PATCH 19/45] chore: remove unused function --- packages/auth/lib/providers/PhoneAuthProvider.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/auth/lib/providers/PhoneAuthProvider.ts b/packages/auth/lib/providers/PhoneAuthProvider.ts index 6ea6a11b38..b6e09cc9ad 100644 --- a/packages/auth/lib/providers/PhoneAuthProvider.ts +++ b/packages/auth/lib/providers/PhoneAuthProvider.ts @@ -49,12 +49,6 @@ function isPhoneMultiFactorSignInOptions( return 'multiFactorHint' in phoneInfoOptions && phoneInfoOptions.multiFactorHint !== undefined; } -function isPhoneMultiFactorUidOptions( - phoneInfoOptions: SupportedPhoneInfoOptions, -): phoneInfoOptions is PhoneMultiFactorSignInInfoOptions & { multiFactorUid: string } { - return 'multiFactorUid' in phoneInfoOptions && phoneInfoOptions.multiFactorUid !== undefined; -} - function isPhoneMultiFactorEnrollOptions( phoneInfoOptions: SupportedPhoneInfoOptions, ): phoneInfoOptions is PhoneMultiFactorEnrollInfoOptions { From 67562b52825fb92ba6a4e155690e7932f1bb3ee8 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 27 Apr 2026 11:54:08 +0100 Subject: [PATCH 20/45] chore: annotate namespace types as deprecated --- packages/auth/lib/types/namespaced.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/auth/lib/types/namespaced.ts b/packages/auth/lib/types/namespaced.ts index 6f6a4c3c7f..c97bb8ef38 100644 --- a/packages/auth/lib/types/namespaced.ts +++ b/packages/auth/lib/types/namespaced.ts @@ -384,6 +384,9 @@ export declare namespace FirebaseAuthTypes { /** * firebase.auth.X */ + /** + * @deprecated Use the package default export or modular APIs instead. + */ export interface Statics { /** * Return the #{@link MultiFactorUser} instance for the current user. @@ -1681,6 +1684,9 @@ export declare namespace FirebaseAuthTypes { * * TODO @salakar missing updateCurrentUser */ + /** + * @deprecated Use the package default export or modular APIs instead. + */ export class Module extends FirebaseModule { /** * The current `FirebaseApp` instance for this Firebase service. From cf8e1d6b67930c5412e2589ee517c4a4f53a3001 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 27 Apr 2026 12:41:58 +0100 Subject: [PATCH 21/45] chore: use multifactor internal type --- packages/auth/lib/multiFactor.ts | 32 ++++++++++++----------------- packages/auth/lib/types/internal.ts | 12 +++++++++++ 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/packages/auth/lib/multiFactor.ts b/packages/auth/lib/multiFactor.ts index be27e274b0..d95ffc7536 100644 --- a/packages/auth/lib/multiFactor.ts +++ b/packages/auth/lib/multiFactor.ts @@ -1,17 +1,10 @@ import { reload } from './modular'; import type { MultiFactorAssertion as ModularMultiFactorAssertion, - User as ModularUser, + User, } from './types/auth'; import type { FirebaseAuthTypes } from './types/namespaced'; -import type { AuthInternal } from './types/internal'; - -type EnrollmentAssertion = { - token?: string; - secret?: string; - totpSecret?: string; - verificationCode?: string; -}; +import type { AuthInternal, MultiFactorEnrollmentAssertionInternal } from './types/internal'; type MultiFactorAuthHost = { currentUser: FirebaseAuthTypes.User | null; @@ -54,27 +47,28 @@ export class MultiFactorUser { multiFactorAssertion: FirebaseAuthTypes.MultiFactorAssertion | ModularMultiFactorAssertion, displayName?: string | null, ): Promise { - const assertion = multiFactorAssertion as EnrollmentAssertion; - const { token, secret, totpSecret, verificationCode } = assertion; - if (token && secret) { + const assertion = multiFactorAssertion as MultiFactorEnrollmentAssertionInternal; + + if (assertion.factorId === 'phone') { await this._auth.native.finalizeMultiFactorEnrollment( - token, - secret, + assertion.token, + assertion.secret, displayName ?? undefined, ); - } else if (totpSecret && verificationCode) { + } else if (assertion.factorId === 'totp') { await this._auth.native.finalizeTotpEnrollment( - totpSecret, - verificationCode, + assertion.totpSecret, + assertion.verificationCode, displayName ?? undefined, ); } else { + // Runtime guard for callers that bypass the typed MFA assertion helpers. throw new Error('Invalid multi-factor assertion provided for enrollment.'); } // We need to reload the user otherwise the changes are not visible // TODO reload not working on Other platform - await reload(this._auth.currentUser as unknown as ModularUser); + await reload(this._auth.currentUser as unknown as User); } async unenroll(enrollmentId: FirebaseAuthTypes.MultiFactorInfo | string): Promise { @@ -83,7 +77,7 @@ export class MultiFactorUser { ); if (this._auth.currentUser) { - await reload(this._auth.currentUser as unknown as ModularUser); + await reload(this._auth.currentUser as unknown as User); } } } diff --git a/packages/auth/lib/types/internal.ts b/packages/auth/lib/types/internal.ts index cb3820a169..515505df23 100644 --- a/packages/auth/lib/types/internal.ts +++ b/packages/auth/lib/types/internal.ts @@ -57,6 +57,18 @@ export type UserCredentialWithAdditionalUserInfoInternal = UserCredential & { additionalUserInfo?: FirebaseAuthTypes.AdditionalUserInfo; }; +export type MultiFactorEnrollmentAssertionInternal = + | { + factorId: 'phone'; + token: string; + secret: string; + } + | { + factorId: 'totp'; + totpSecret: string; + verificationCode: string; + }; + export interface NativeUserMetadataInternal { creationTime: string; lastSignInTime: string; From dad46843172f4846332058d0fe81a18bff4a4f9f Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 27 Apr 2026 13:20:52 +0100 Subject: [PATCH 22/45] fix: useEmulator type and internal logic --- packages/auth/lib/namespaced.ts | 11 ++++++----- packages/auth/lib/types/internal.ts | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/auth/lib/namespaced.ts b/packages/auth/lib/namespaced.ts index eb14bafb9e..6951313aa6 100644 --- a/packages/auth/lib/namespaced.ts +++ b/packages/auth/lib/namespaced.ts @@ -598,7 +598,7 @@ class FirebaseAuthModule extends FirebaseModule { ); } - useEmulator(url: string): [string, number] { + useEmulator(url: string): void { if (!url || !isString(url) || !isValidUrl(url)) { throw new Error('firebase.auth().useEmulator() takes a non-empty string URL'); } @@ -632,12 +632,13 @@ class FirebaseAuthModule extends FirebaseModule { } const host = urlMatches[1]; const portString = urlMatches[2]; - if (!host || !portString) { - throw new Error('firebase.auth().useEmulator() unable to parse host and port from URL'); + if (!host) { + throw new Error('firebase.auth().useEmulator() unable to parse host from URL'); } - const port = parseInt(portString, 10); + const port = portString ? parseInt(portString, 10) : undefined; this.native.useEmulator(host, port); - return [host, port]; // undocumented return, useful for unit testing + // @ts-ignore - undocumented return, useful for unit testing + return [host, port]; } getMultiFactorResolver( diff --git a/packages/auth/lib/types/internal.ts b/packages/auth/lib/types/internal.ts index 515505df23..1590a2b6a1 100644 --- a/packages/auth/lib/types/internal.ts +++ b/packages/auth/lib/types/internal.ts @@ -257,7 +257,7 @@ export interface RNFBAuthModule { verifyPasswordResetCode(code: string): Promise; useUserAccessGroup(userAccessGroup: string): Promise; signInWithProvider(provider: Record): Promise; - useEmulator(host: string, port: number): void; + useEmulator(host: string, port?: number): void; getCustomAuthDomain(): Promise; confirmationResultConfirm(verificationCode: string): Promise; delete(): Promise; From 9598bfd5555bb75a1e9cbca909c12a234f4037fa Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 27 Apr 2026 13:54:42 +0100 Subject: [PATCH 23/45] refactor: User public api should use modular api --- packages/auth/lib/User.ts | 36 +++++++++++++++++++---------- packages/auth/lib/types/internal.ts | 21 +++++++++++++---- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/packages/auth/lib/User.ts b/packages/auth/lib/User.ts index 66590858d9..0affbd3125 100644 --- a/packages/auth/lib/User.ts +++ b/packages/auth/lib/User.ts @@ -21,6 +21,7 @@ import { isUndefined, isBoolean, } from '@react-native-firebase/app/dist/module/common'; +import type { IdTokenResult, UserInfo, UserMetadata } from './types/auth'; import type { FirebaseAuthTypes } from './types/namespaced'; import type { AuthInternal, NativeUserInternal } from './types/internal'; @@ -53,7 +54,7 @@ export default class User { return this._user.isAnonymous || false; } - get metadata(): FirebaseAuthTypes.UserMetadata { + get metadata(): UserMetadata { const { metadata } = this._user; return { @@ -78,8 +79,15 @@ export default class User { return this._user.photoURL || null; } - get providerData(): FirebaseAuthTypes.UserInfo[] { - return this._user.providerData; + get providerData(): UserInfo[] { + return this._user.providerData.map(provider => ({ + displayName: provider.displayName ?? null, + email: provider.email ?? null, + phoneNumber: provider.phoneNumber ?? null, + photoURL: provider.photoURL ?? null, + providerId: provider.providerId, + uid: provider.uid, + })); } get providerId(): string { @@ -100,10 +108,8 @@ export default class User { return this._auth.native.getIdToken(forceRefresh); } - getIdTokenResult(forceRefresh = false): Promise { - return this._auth.native.getIdTokenResult( - forceRefresh, - ) as Promise; + getIdTokenResult(forceRefresh = false): Promise { + return this._auth.native.getIdTokenResult(forceRefresh) as Promise; } linkWithCredential( @@ -229,8 +235,8 @@ export default class User { } return this._auth.native.sendEmailVerification(actionCodeSettings).then(user => { - this._auth._setUser(user); - }); + this._auth._setUser(user); + }); } toJSON(): object { @@ -240,7 +246,13 @@ export default class User { unlink(providerId: string): Promise { return this._auth.native .unlink(providerId) - .then(user => this._auth._setUser(user) as FirebaseAuthTypes.User); + .then(user => { + const updatedUser = this._auth._setUser(user); + if (!updatedUser) { + throw new Error('firebase.auth.User.unlink() returned no user after unlinking provider.'); + } + return updatedUser; + }); } updateEmail(email: string): Promise { @@ -343,8 +355,8 @@ export default class User { } return this._auth.native.verifyBeforeUpdateEmail(newEmail, actionCodeSettings).then(user => { - this._auth._setUser(user); - }); + this._auth._setUser(user); + }); } /** diff --git a/packages/auth/lib/types/internal.ts b/packages/auth/lib/types/internal.ts index 1590a2b6a1..fb46b6f242 100644 --- a/packages/auth/lib/types/internal.ts +++ b/packages/auth/lib/types/internal.ts @@ -27,6 +27,7 @@ import type { ActionCodeSettings, Auth, AuthCredential, + AuthProvider, ConfirmationResult, IdTokenResult, MultiFactorResolver, @@ -48,7 +49,7 @@ export interface AppWithAuthInternal { export type AuthListenerCallbackInternal = (user: User | null) => void; -export type AuthProviderWithObjectInternal = FirebaseAuthTypes.AuthProvider & { +export type AuthProviderWithObjectInternal = AuthProvider & { toObject(): Record; }; @@ -74,10 +75,20 @@ export interface NativeUserMetadataInternal { lastSignInTime: string; } +export interface NativeUserInfoInternal { + uid: string; + providerId: string; + displayName?: string | null; + email?: string | null; + phoneNumber?: string | null; + photoURL?: string | null; + tenantId?: string | null; +} + export interface NativeUserInternal { uid: string; providerId: string; - providerData: FirebaseAuthTypes.UserInfo[]; + providerData: NativeUserInfoInternal[]; displayName?: string | null; email?: string | null; emailVerified?: boolean; @@ -262,7 +273,7 @@ export interface RNFBAuthModule { confirmationResultConfirm(verificationCode: string): Promise; delete(): Promise; getIdToken(forceRefresh: boolean): Promise; - getIdTokenResult(forceRefresh: boolean): Promise; + getIdTokenResult(forceRefresh: boolean): Promise; linkWithCredential( providerId: string, token: string, @@ -289,7 +300,9 @@ export interface RNFBAuthModule { token: string, secret?: string | null, ): Promise; - updateProfile(updates: FirebaseAuthTypes.UpdateProfile): Promise; + updateProfile( + updates: { displayName?: string | null; photoURL?: string | null }, + ): Promise; verifyBeforeUpdateEmail( newEmail: string, actionCodeSettings?: FirebaseAuthTypes.ActionCodeSettings, From b2c7d118b4fdd0333f86d21bb1ff39bf90d48fdd Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 27 Apr 2026 15:01:48 +0100 Subject: [PATCH 24/45] refactor: normalise namespaced types to modular for consumers --- packages/auth/lib/modular.ts | 261 +++++++++++++++++++++++++--- packages/auth/lib/types/internal.ts | 41 ++++- 2 files changed, 276 insertions(+), 26 deletions(-) diff --git a/packages/auth/lib/modular.ts b/packages/auth/lib/modular.ts index 437a235aa7..4b319c7538 100644 --- a/packages/auth/lib/modular.ts +++ b/packages/auth/lib/modular.ts @@ -31,7 +31,9 @@ import OIDCAuthProvider from './providers/OIDCAuthProvider'; import PhoneAuthProvider from './providers/PhoneAuthProvider'; import TwitterAuthProvider from './providers/TwitterAuthProvider'; import type { FirebaseApp } from '@react-native-firebase/app'; +import { ActionCodeOperation, FactorId, OperationType, ProviderId } from './types/auth'; import type { + ActionCodeInfo, ActionCodeSettings, ActionCodeURL, AdditionalUserInfo, @@ -45,24 +47,31 @@ import type { ErrorFn, IdTokenResult, MultiFactorError, + MultiFactorInfo, MultiFactorResolver, MultiFactorUser, NextOrObserver, PasswordValidationStatus, Persistence, + PhoneMultiFactorInfo, PhoneAuthListener, PopupRedirectResolver, + TotpMultiFactorInfo, Unsubscribe, User, UserCredential, } from './types/auth'; -import type { FirebaseAuthTypes } from './types/namespaced'; import type { + ActionCodeInfoResultInternal, AppWithAuthInternal, AuthInternal, AuthListenerCallbackInternal, AuthProviderWithObjectInternal, - UserCredentialWithAdditionalUserInfoInternal, + ConfirmationResultResultInternal, + MultiFactorResolverResultInternal, + MultiFactorUserResultInternal, + MultiFactorUserSourceInternal, + UserCredentialResultInternal, UserInternal, WithAuthDeprecationArg, } from './types/internal'; @@ -70,6 +79,11 @@ import type { type AnyFn = (...args: any[]) => any; type UserModuleInternal = UserInternal; +type MultiFactorInfoInternal = + | MultiFactorInfo + | MultiFactorResolverResultInternal['hints'][number]; + +const actionCodeOperations = new Set(Object.values(ActionCodeOperation)); function appWithAuth(app?: FirebaseApp): AppWithAuthInternal { return (app ? getApp(app.name) : getApp()) as unknown as AppWithAuthInternal; @@ -83,6 +97,129 @@ function getUserInternal(user: User): UserModuleInternal { return user as unknown as UserModuleInternal; } +function normalizeUserCredential( + userCredential: UserCredentialResultInternal, + overrides: Partial> = {}, +): UserCredential { + const normalizedUserCredential: UserCredential = { + user: userCredential.user as unknown as User, + providerId: + overrides.providerId ?? + userCredential.providerId ?? + userCredential.additionalUserInfo?.providerId ?? + null, + operationType: overrides.operationType ?? userCredential.operationType ?? OperationType.SIGN_IN, + }; + + if (userCredential.additionalUserInfo) { + Object.defineProperty(normalizedUserCredential, 'additionalUserInfo', { + value: userCredential.additionalUserInfo, + enumerable: false, + configurable: true, + }); + } + + return normalizedUserCredential; +} + +function normalizeActionCodeOperation(operation: string): ActionCodeInfo['operation'] { + if (actionCodeOperations.has(operation)) { + return operation as ActionCodeInfo['operation']; + } + + // Native auth may still surface the legacy 'ERROR' sentinel even though the modular public + // type does not model it. Preserve the native value instead of turning it into a new throw. + return operation as ActionCodeInfo['operation']; +} + +function normalizeMultiFactorInfo(info: MultiFactorInfoInternal): MultiFactorInfo { + const normalizedInfo = { + uid: info.uid, + displayName: info.displayName ?? null, + enrollmentTime: info.enrollmentTime, + factorId: info.factorId, + }; + + if ('phoneNumber' in info) { + return { + ...normalizedInfo, + phoneNumber: info.phoneNumber, + } as PhoneMultiFactorInfo; + } + + return normalizedInfo as TotpMultiFactorInfo; +} + +function normalizeActionCodeInfo(actionCodeInfo: ActionCodeInfoResultInternal): ActionCodeInfo { + const data = actionCodeInfo.data ?? {}; + + return { + data: { + email: data.email ?? null, + multiFactorInfo: + 'multiFactorInfo' in data && data.multiFactorInfo + ? normalizeMultiFactorInfo(data.multiFactorInfo) + : null, + previousEmail: + ('previousEmail' in data ? data.previousEmail : undefined) ?? + ('fromEmail' in data ? data.fromEmail : undefined) ?? + null, + }, + operation: normalizeActionCodeOperation(actionCodeInfo.operation), + }; +} + +function normalizeConfirmationResult( + confirmationResult: ConfirmationResultResultInternal, +): ConfirmationResult { + if (!confirmationResult.verificationId) { + throw new Error('signInWithPhoneNumber() did not return a verificationId.'); + } + + return { + verificationId: confirmationResult.verificationId, + async confirm(verificationCode: string) { + const userCredential = await confirmationResult.confirm(verificationCode); + + if (!userCredential) { + throw new Error('signInWithPhoneNumber().confirm() returned no user credential.'); + } + + return normalizeUserCredential(userCredential, { + providerId: ProviderId.PHONE, + operationType: OperationType.SIGN_IN, + }); + }, + }; +} + +function normalizeMultiFactorResolver( + resolver: MultiFactorResolverResultInternal, +): MultiFactorResolver { + return { + hints: resolver.hints.map(normalizeMultiFactorInfo), + session: resolver.session, + async resolveSignIn(assertion) { + return normalizeUserCredential(await resolver.resolveSignIn(assertion), { + providerId: assertion.factorId === FactorId.PHONE ? ProviderId.PHONE : null, + operationType: OperationType.SIGN_IN, + }); + }, + }; +} + +function normalizeMultiFactorUser(multiFactorUser: MultiFactorUserResultInternal): MultiFactorUser { + return { + enrolledFactors: multiFactorUser.enrolledFactors.map(normalizeMultiFactorInfo), + getSession: () => multiFactorUser.getSession(), + enroll: (assertion, displayName) => multiFactorUser.enroll(assertion, displayName), + unenroll: option => + multiFactorUser.unenroll( + option as Parameters[0], + ), + }; +} + export { AppleAuthProvider, EmailAuthProvider, @@ -165,9 +302,11 @@ export function beforeAuthStateChanged( throw new Error('beforeAuthStateChanged is unsupported by the native Firebase SDKs'); } -export function checkActionCode(auth: Auth, oobCode: string) { +export function checkActionCode(auth: Auth, oobCode: string): Promise { const authInternal = getAuthInternal(auth); - return callAuthMethod(authInternal, authInternal.checkActionCode, oobCode); + return callAuthMethod(authInternal, authInternal.checkActionCode, oobCode).then( + normalizeActionCodeInfo, + ); } export function confirmPasswordReset( @@ -194,7 +333,12 @@ export function createUserWithEmailAndPassword( password: string, ): Promise { const authInternal = getAuthInternal(auth); - return callAuthMethod(authInternal, authInternal.createUserWithEmailAndPassword, email, password); + return callAuthMethod(authInternal, authInternal.createUserWithEmailAndPassword, email, password).then( + userCredential => + normalizeUserCredential(userCredential, { + operationType: OperationType.SIGN_IN, + }), + ); } export function fetchSignInMethodsForEmail(auth: Auth, email: string): Promise { @@ -204,7 +348,17 @@ export function fetchSignInMethodsForEmail(auth: Auth, email: string): Promise { const authInternal = getAuthInternal(auth); - return callAuthMethod(authInternal, authInternal.signInAnonymously); + return callAuthMethod(authInternal, authInternal.signInAnonymously).then(userCredential => + normalizeUserCredential(userCredential, { + operationType: OperationType.SIGN_IN, + }), + ); } export function signInWithCredential( @@ -297,12 +455,23 @@ export function signInWithCredential( credential: AuthCredential, ): Promise { const authInternal = getAuthInternal(auth); - return callAuthMethod(authInternal, authInternal.signInWithCredential, credential); + return callAuthMethod(authInternal, authInternal.signInWithCredential, credential).then( + userCredential => + normalizeUserCredential(userCredential, { + providerId: credential.providerId, + operationType: OperationType.SIGN_IN, + }), + ); } export function signInWithCustomToken(auth: Auth, customToken: string): Promise { const authInternal = getAuthInternal(auth); - return callAuthMethod(authInternal, authInternal.signInWithCustomToken, customToken); + return callAuthMethod(authInternal, authInternal.signInWithCustomToken, customToken).then( + userCredential => + normalizeUserCredential(userCredential, { + operationType: OperationType.SIGN_IN, + }), + ); } export function signInWithEmailAndPassword( @@ -311,7 +480,12 @@ export function signInWithEmailAndPassword( password: string, ): Promise { const authInternal = getAuthInternal(auth); - return callAuthMethod(authInternal, authInternal.signInWithEmailAndPassword, email, password); + return callAuthMethod(authInternal, authInternal.signInWithEmailAndPassword, email, password).then( + userCredential => + normalizeUserCredential(userCredential, { + operationType: OperationType.SIGN_IN, + }), + ); } export function signInWithEmailLink( @@ -320,7 +494,13 @@ export function signInWithEmailLink( emailLink: string, ): Promise { const authInternal = getAuthInternal(auth); - return callAuthMethod(authInternal, authInternal.signInWithEmailLink, email, emailLink); + return callAuthMethod(authInternal, authInternal.signInWithEmailLink, email, emailLink).then( + userCredential => + normalizeUserCredential(userCredential, { + providerId: ProviderId.PASSWORD, + operationType: OperationType.SIGN_IN, + }), + ); } export function signInWithPhoneNumber( @@ -331,7 +511,9 @@ export function signInWithPhoneNumber( // Native SDKs own the verification flow, so the modular wrapper intentionally ignores the // JS SDK's optional ApplicationVerifier and forwards only the phone number. const authInternal = getAuthInternal(auth); - return callAuthMethod(authInternal, authInternal.signInWithPhoneNumber, phoneNumber); + return callAuthMethod(authInternal, authInternal.signInWithPhoneNumber, phoneNumber).then( + normalizeConfirmationResult, + ); } export function verifyPhoneNumber( @@ -360,6 +542,11 @@ export function signInWithPopup( authInternal, authInternal.signInWithPopup, provider as unknown as AuthProviderWithObjectInternal, + ).then(userCredential => + normalizeUserCredential(userCredential, { + providerId: provider.providerId, + operationType: OperationType.SIGN_IN, + }), ); } @@ -375,6 +562,11 @@ export function signInWithRedirect( authInternal, authInternal.signInWithRedirect, provider as unknown as AuthProviderWithObjectInternal, + ).then(userCredential => + normalizeUserCredential(userCredential, { + providerId: provider.providerId, + operationType: OperationType.SIGN_IN, + }), ); } @@ -432,7 +624,13 @@ export function linkWithCredential( credential: AuthCredential, ): Promise { const userInternal = getUserInternal(user); - return callUserMethod(userInternal, userInternal.linkWithCredential, credential); + return callUserMethod(userInternal, userInternal.linkWithCredential, credential).then( + userCredential => + normalizeUserCredential(userCredential, { + providerId: credential.providerId, + operationType: OperationType.LINK, + }), + ); } export function linkWithPhoneNumber( @@ -453,6 +651,11 @@ export function linkWithPopup( userInternal, userInternal.linkWithPopup, provider as unknown as AuthProviderWithObjectInternal, + ).then(userCredential => + normalizeUserCredential(userCredential, { + providerId: provider.providerId, + operationType: OperationType.LINK, + }), ); } @@ -468,15 +671,22 @@ export function linkWithRedirect( userInternal, userInternal.linkWithRedirect, provider as unknown as AuthProviderWithObjectInternal, + ).then(userCredential => + normalizeUserCredential(userCredential, { + providerId: provider.providerId, + operationType: OperationType.LINK, + }), ); } export function multiFactor(user: User): MultiFactorUser { - return new MultiFactorUserModule( - ((user as unknown as UserInternal)._auth || - (getAuth() as unknown as UserInternal['_auth'])) as NonNullable, - user as unknown as FirebaseAuthTypes.User, - ) as MultiFactorUser; + return normalizeMultiFactorUser( + new MultiFactorUserModule( + ((user as unknown as UserInternal)._auth || + (getAuth() as unknown as UserInternal['_auth'])) as NonNullable, + user as unknown as MultiFactorUserSourceInternal, + ), + ); } export function reauthenticateWithCredential( @@ -484,7 +694,13 @@ export function reauthenticateWithCredential( credential: AuthCredential, ): Promise { const userInternal = getUserInternal(user); - return callUserMethod(userInternal, userInternal.reauthenticateWithCredential, credential); + return callUserMethod(userInternal, userInternal.reauthenticateWithCredential, credential).then( + userCredential => + normalizeUserCredential(userCredential, { + providerId: credential.providerId, + operationType: OperationType.REAUTHENTICATE, + }), + ); } export function reauthenticateWithPhoneNumber( @@ -505,6 +721,11 @@ export function reauthenticateWithPopup( userInternal, userInternal.reauthenticateWithPopup, provider as unknown as AuthProviderWithObjectInternal, + ).then(userCredential => + normalizeUserCredential(userCredential, { + providerId: provider.providerId, + operationType: OperationType.REAUTHENTICATE, + }), ); } @@ -584,7 +805,7 @@ export function verifyBeforeUpdateEmail( } export function getAdditionalUserInfo(userCredential: UserCredential): AdditionalUserInfo | null { - const info = (userCredential as UserCredentialWithAdditionalUserInfoInternal).additionalUserInfo; + const info = (userCredential as unknown as UserCredentialResultInternal).additionalUserInfo; if (!info) { return null; } diff --git a/packages/auth/lib/types/internal.ts b/packages/auth/lib/types/internal.ts index fb46b6f242..27c8213ef5 100644 --- a/packages/auth/lib/types/internal.ts +++ b/packages/auth/lib/types/internal.ts @@ -28,9 +28,8 @@ import type { Auth, AuthCredential, AuthProvider, - ConfirmationResult, IdTokenResult, - MultiFactorResolver, + MultiFactorAssertion, PhoneAuthListener, User, UserCredential, @@ -58,6 +57,36 @@ export type UserCredentialWithAdditionalUserInfoInternal = UserCredential & { additionalUserInfo?: FirebaseAuthTypes.AdditionalUserInfo; }; +export type UserCredentialResultInternal = FirebaseAuthTypes.UserCredential & + Partial>; + +export type ActionCodeInfoResultInternal = FirebaseAuthTypes.ActionCodeInfo | ActionCodeInfo; + +export type ConfirmationResultResultInternal = { + verificationId: string | null; + confirm(verificationCode: string): Promise; +}; + +export type MultiFactorResolverResultInternal = { + hints: FirebaseAuthTypes.MultiFactorInfo[]; + session: FirebaseAuthTypes.MultiFactorSession; + resolveSignIn( + assertion: FirebaseAuthTypes.MultiFactorAssertion | MultiFactorAssertion, + ): Promise; +}; + +export type MultiFactorUserSourceInternal = FirebaseAuthTypes.User; + +export type MultiFactorUserResultInternal = { + enrolledFactors: FirebaseAuthTypes.MultiFactorInfo[]; + getSession(): Promise; + enroll( + assertion: FirebaseAuthTypes.MultiFactorAssertion | MultiFactorAssertion, + displayName?: string | null, + ): Promise; + unenroll(option: FirebaseAuthTypes.MultiFactorInfo | string): Promise; +}; + export type MultiFactorEnrollmentAssertionInternal = | { factorId: 'phone'; @@ -318,7 +347,7 @@ export interface RNFBAuthModule { displayName?: string, ): Promise; unenrollMultiFactor(enrollmentId: string | FirebaseAuthTypes.MultiFactorInfo): Promise; - getMultiFactorResolver(error: unknown): FirebaseAuthTypes.MultiFactorResolver | null; + getMultiFactorResolver(error: unknown): MultiFactorResolverResultInternal | null; generateTotpSecret(session: FirebaseAuthTypes.MultiFactorSession): Promise<{ secretKey: string }>; generateQrCodeUrl(secretKey: string, accountName: string, issuer: string): Promise; openInOtpApp(secretKey: string, qrCodeUrl: string): string | void; @@ -332,7 +361,7 @@ export type AuthInternal = Auth & { app: ReactNativeFirebase.FirebaseApp; currentUser: FirebaseAuthTypes.User | null; applyActionCode(code: string): Promise; - checkActionCode(code: string): Promise; + checkActionCode(code: string): Promise; confirmPasswordReset(code: string, newPassword: string): Promise; createUserWithEmailAndPassword( email: string, @@ -340,7 +369,7 @@ export type AuthInternal = Auth & { ): Promise; fetchSignInMethodsForEmail(email: string): Promise; getCustomAuthDomain(): Promise; - getMultiFactorResolver(error: unknown): MultiFactorResolver | null; + getMultiFactorResolver(error: unknown): MultiFactorResolverResultInternal | null; isSignInWithEmailLink(emailLink: string): Promise; onAuthStateChanged( listenerOrObserver: CallbackOrObserver, @@ -371,7 +400,7 @@ export type AuthInternal = Auth & { signInWithPhoneNumber( phoneNumber: string, forceResend?: boolean, - ): Promise; + ): Promise; signInWithPopup( provider: AuthProviderWithObjectInternal, ): Promise; From 2c0afc4e449de78d314be44cecb0c03c809eabb7 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 27 Apr 2026 15:02:09 +0100 Subject: [PATCH 25/45] fix: vertexai and ai packages tsconfig.json --- packages/ai/tsconfig.json | 2 +- packages/vertexai/tsconfig.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ai/tsconfig.json b/packages/ai/tsconfig.json index 837c336e3e..f57afbea70 100644 --- a/packages/ai/tsconfig.json +++ b/packages/ai/tsconfig.json @@ -32,7 +32,7 @@ ], "@react-native-firebase/app/lib/internal": ["../app/dist/typescript/lib/internal"], "@react-native-firebase/app": ["../app/dist/typescript/lib"], - "@react-native-firebase/auth": ["../auth/lib"], + "@react-native-firebase/auth": ["../auth/dist/typescript/lib"], "@react-native-firebase/app-check": ["../app-check/dist/typescript/lib"] } }, diff --git a/packages/vertexai/tsconfig.json b/packages/vertexai/tsconfig.json index 837c336e3e..f57afbea70 100644 --- a/packages/vertexai/tsconfig.json +++ b/packages/vertexai/tsconfig.json @@ -32,7 +32,7 @@ ], "@react-native-firebase/app/lib/internal": ["../app/dist/typescript/lib/internal"], "@react-native-firebase/app": ["../app/dist/typescript/lib"], - "@react-native-firebase/auth": ["../auth/lib"], + "@react-native-firebase/auth": ["../auth/dist/typescript/lib"], "@react-native-firebase/app-check": ["../app-check/dist/typescript/lib"] } }, From d5b597e29a6713c41cfc6409d4d66983f534344b Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Mon, 27 Apr 2026 15:42:52 +0100 Subject: [PATCH 26/45] chore: remove namespace types from auth modular public types --- packages/auth/lib/types/auth.ts | 61 ++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/packages/auth/lib/types/auth.ts b/packages/auth/lib/types/auth.ts index 579fbe045e..28f9e85c31 100644 --- a/packages/auth/lib/types/auth.ts +++ b/packages/auth/lib/types/auth.ts @@ -16,7 +16,6 @@ */ import type { FirebaseApp, ReactNativeFirebase } from '@react-native-firebase/app'; -import type { FirebaseAuthTypes } from './namespaced'; export type CompleteFn = () => void; export type ErrorFn = (error: Error) => void; @@ -107,18 +106,64 @@ export interface AuthError extends ReactNativeFirebase.NativeFirebaseError { }; } -export type NativeFirebaseAuthError = FirebaseAuthTypes.NativeFirebaseAuthError; -export type AuthCredential = FirebaseAuthTypes.AuthCredential; -export type OIDCProvider = FirebaseAuthTypes.OIDCProvider; +export interface NativeFirebaseAuthError extends ReactNativeFirebase.NativeFirebaseError { + readonly userInfo: { + readonly authCredential: AuthCredential | null; + readonly resolver: MultiFactorResolver | null; + }; +} + +export interface AuthCredential { + readonly providerId: string; + readonly token: string; + readonly secret: string; +} + +export interface OIDCProvider { + readonly PROVIDER_ID: string; + credential(oidcSuffix: string, idToken: string): AuthCredential; +} export interface MultiFactorError extends AuthError { readonly customData: AuthError['customData'] & { readonly operationType: (typeof OperationType)[keyof typeof OperationType]; }; } -export type PhoneAuthListener = FirebaseAuthTypes.PhoneAuthListener; -export type PhoneAuthError = FirebaseAuthTypes.PhoneAuthError; -export type PhoneAuthSnapshot = FirebaseAuthTypes.PhoneAuthSnapshot; -export type ActionCodeURL = FirebaseAuthTypes.ActionCodeURL; +export interface PhoneAuthSnapshot { + readonly state: 'sent' | 'timeout' | 'verified' | 'error'; + readonly verificationId: string; + readonly code: string | null; + readonly error: ReactNativeFirebase.NativeFirebaseError | null; +} + +export interface PhoneAuthError { + readonly code: string | null; + readonly verificationId: string; + readonly message: string | null; + readonly stack: string | null; +} + +export interface PhoneAuthListener { + on( + event: string, + observer: (snapshot: PhoneAuthSnapshot) => void, + errorCb?: (error: PhoneAuthError) => void, + successCb?: (snapshot: PhoneAuthSnapshot) => void, + ): PhoneAuthListener; + then( + onFulfilled?: ((value: PhoneAuthSnapshot) => any) | null, + onRejected?: ((error: ReactNativeFirebase.NativeFirebaseError) => any) | null, + ): Promise; + catch(onRejected: (error: ReactNativeFirebase.NativeFirebaseError) => any): Promise; +} + +export interface ActionCodeURL { + readonly apiKey: string; + readonly code: string; + readonly continueUrl?: string | null; + readonly languageCode?: string | null; + readonly operation: string; + readonly tenantId?: string | null; +} export interface Config { apiKey: string; From 118f3e1f05fc80f3acb25d54fd5f1f93450db541 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 30 Apr 2026 10:43:20 +0100 Subject: [PATCH 27/45] test: fix tests after TS migration --- packages/auth/__tests__/auth.test.ts | 55 +++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/packages/auth/__tests__/auth.test.ts b/packages/auth/__tests__/auth.test.ts index 87f042960c..ecff3eec25 100644 --- a/packages/auth/__tests__/auth.test.ts +++ b/packages/auth/__tests__/auth.test.ts @@ -91,6 +91,7 @@ import { } from '../../app/lib/common/unitTestUtils'; // @ts-ignore import { createDeprecationProxy } from '@react-native-firebase/app/dist/module/common'; +import { AuthInternal } from '../lib/types/internal'; describe('Auth', function () { describe('namespace', function () { @@ -243,7 +244,34 @@ describe('Auth', function () { sendPasswordResetEmail(auth, email, actionCodeSettings); sendSignInLinkToEmail(auth, email, actionCodeSettings); - const user: FirebaseAuthTypes.User = new User(auth, {}); + const user: FirebaseAuthTypes.User = new User(auth as AuthInternal, { + uid: 'test-user-id', + displayName: 'Test User', + email: 'test@example.com', + emailVerified: true, + isAnonymous: false, + metadata: { + lastSignInTime: '2023-01-01T00:00:00.000Z', + creationTime: '2023-01-01T00:00:00.000Z', + }, + multiFactor: { + enrolledFactors: [], + }, + phoneNumber: '+1234567890', + tenantId: null, + photoURL: 'https://example.com/photo.jpg', + providerData: [ + { + uid: 'test-uid', + displayName: 'Test User', + email: 'test@example.com', + phoneNumber: '+1234567890', + photoURL: 'https://example.com/photo.jpg', + providerId: 'password', + }, + ], + providerId: 'firebase', + }); user.sendEmailVerification(actionCodeSettings); user.verifyBeforeUpdateEmail(email, actionCodeSettings); @@ -551,6 +579,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => applyActionCode(auth, 'code'), + // @ts-expect-error Combines modular and namespace API () => auth.applyActionCode('code'), 'applyActionCode', ); @@ -560,6 +589,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => checkActionCode(auth, 'code'), + // @ts-expect-error Combines modular and namespace API () => auth.checkActionCode('code'), 'checkActionCode', ); @@ -569,6 +599,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => confirmPasswordReset(auth, 'code', 'newPassword'), + // @ts-expect-error Combines modular and namespace API () => auth.confirmPasswordReset('code', 'newPassword'), 'confirmPasswordReset', ); @@ -578,6 +609,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => createUserWithEmailAndPassword(auth, 'test@example.com', 'password'), + // @ts-expect-error Combines modular and namespace API () => auth.createUserWithEmailAndPassword('test@example.com', 'password'), 'createUserWithEmailAndPassword', ); @@ -587,6 +619,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => fetchSignInMethodsForEmail(auth, 'test@example.com'), + // @ts-expect-error Combines modular and namespace API () => auth.fetchSignInMethodsForEmail('test@example.com'), 'fetchSignInMethodsForEmail', ); @@ -597,6 +630,7 @@ describe('Auth', function () { const error = new Error() as any; authV9Deprecation( () => getMultiFactorResolver(auth, error), + // @ts-expect-error Combines modular and namespace API () => auth.getMultiFactorResolver(error), 'getMultiFactorResolver', ); @@ -606,6 +640,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => isSignInWithEmailLink(auth, 'emailLink'), + // @ts-expect-error Combines modular and namespace API () => auth.isSignInWithEmailLink('emailLink'), 'isSignInWithEmailLink', ); @@ -636,6 +671,7 @@ describe('Auth', function () { const provider = { toObject: () => ({}) } as any; authV9Deprecation( () => signInWithPopup(auth, provider), + // @ts-expect-error Combines modular and namespace API () => auth.signInWithPopup(provider), 'signInWithPopup', ); @@ -646,6 +682,7 @@ describe('Auth', function () { const provider = { toObject: () => ({}) } as any; authV9Deprecation( () => signInWithRedirect(auth, provider), + // @ts-expect-error Combines modular and namespace API () => auth.signInWithRedirect(provider), 'signInWithRedirect', ); @@ -655,6 +692,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => sendPasswordResetEmail(auth, 'test@example.com'), + // @ts-expect-error Combines modular and namespace API () => auth.sendPasswordResetEmail('test@example.com'), 'sendPasswordResetEmail', ); @@ -665,6 +703,7 @@ describe('Auth', function () { const actionCodeSettings = { url: 'https://example.com' }; authV9Deprecation( () => sendSignInLinkToEmail(auth, 'test@example.com', actionCodeSettings), + // @ts-expect-error Combines modular and namespace API () => auth.sendSignInLinkToEmail('test@example.com', actionCodeSettings), 'sendSignInLinkToEmail', ); @@ -674,6 +713,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => signInAnonymously(auth), + // @ts-expect-error Combines modular and namespace API () => auth.signInAnonymously(), 'signInAnonymously', ); @@ -684,6 +724,7 @@ describe('Auth', function () { const credential = {} as any; authV9Deprecation( () => signInWithCredential(auth, credential), + // @ts-expect-error Combines modular and namespace API () => auth.signInWithCredential(credential), 'signInWithCredential', ); @@ -693,6 +734,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => signInWithCustomToken(auth, 'customToken'), + // @ts-expect-error Combines modular and namespace API () => auth.signInWithCustomToken('customToken'), 'signInWithCustomToken', ); @@ -702,6 +744,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => signInWithEmailAndPassword(auth, 'test@example.com', 'password'), + // @ts-expect-error Combines modular and namespace API () => auth.signInWithEmailAndPassword('test@example.com', 'password'), 'signInWithEmailAndPassword', ); @@ -711,6 +754,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => signInWithEmailLink(auth, 'test@example.com', 'emailLink'), + // @ts-expect-error Combines modular and namespace API () => auth.signInWithEmailLink('test@example.com', 'emailLink'), 'signInWithEmailLink', ); @@ -720,6 +764,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => signInWithPhoneNumber(auth, '+1234567890', undefined), + // @ts-expect-error Combines modular and namespace API () => auth.signInWithPhoneNumber('+1234567890', false), 'signInWithPhoneNumber', ); @@ -738,6 +783,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => useUserAccessGroup(auth, 'group'), + // @ts-expect-error Combines modular and namespace API () => auth.useUserAccessGroup('group'), 'useUserAccessGroup', ); @@ -747,6 +793,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => verifyPasswordResetCode(auth, 'code'), + // @ts-expect-error Combines modular and namespace API () => auth.verifyPasswordResetCode('code'), 'verifyPasswordResetCode', ); @@ -756,6 +803,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => getCustomAuthDomain(auth), + // @ts-expect-error Combines modular and namespace API () => auth.getCustomAuthDomain(), 'getCustomAuthDomain', ); @@ -765,6 +813,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => connectAuthEmulator(auth, 'http://localhost:9099'), + // @ts-expect-error Combines modular and namespace API () => auth.useEmulator('http://localhost:9099'), 'useEmulator', ); @@ -774,6 +823,7 @@ describe('Auth', function () { const auth = getAuth(); authV9Deprecation( () => setLanguageCode(auth, 'en'), + // @ts-expect-error Combines modular and namespace API () => auth.setLanguageCode('en'), 'setLanguageCode', ); @@ -798,6 +848,7 @@ describe('Auth', function () { authV9Deprecation( () => multiFactor(mockUser), + // @ts-expect-error Combines modular and namespace API () => auth.multiFactor(mockUser), 'multiFactor', ); @@ -808,7 +859,7 @@ describe('Auth', function () { let mockUser: User; beforeEach(function () { - mockUser = new User(getAuth(), { + mockUser = new User(getAuth() as AuthInternal, { uid: 'test-user-id', displayName: 'Test User', email: 'test@example.com', From 1fd75885894045daba9dcd7617affeca664b46e5 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 30 Apr 2026 10:50:14 +0100 Subject: [PATCH 28/45] test: fix some test mixing modular/namespace --- packages/auth/__tests__/auth.test.ts | 7 ++++--- packages/auth/lib/types/namespaced.ts | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/auth/__tests__/auth.test.ts b/packages/auth/__tests__/auth.test.ts index ecff3eec25..fa0ba2f176 100644 --- a/packages/auth/__tests__/auth.test.ts +++ b/packages/auth/__tests__/auth.test.ts @@ -1,5 +1,6 @@ import { afterAll, beforeAll, beforeEach, describe, expect, it, jest } from '@jest/globals'; import { FirebaseAuthTypes } from '../lib/index'; +import type { ActionCodeSettings, User as ModularUser } from '../lib'; // @ts-ignore import User from '../lib/User'; // @ts-ignore test @@ -233,18 +234,18 @@ describe('Auth', function () { it('should allow linkDomain as `ActionCodeSettings.linkDomain`', function () { const auth = firebase.app().auth(); - const actionCodeSettings: FirebaseAuthTypes.ActionCodeSettings = { + const actionCodeSettings = { url: 'https://example.com', handleCodeInApp: true, linkDomain: 'example.com', - }; + } satisfies FirebaseAuthTypes.ActionCodeSettings & ActionCodeSettings; const email = 'fake@example.com'; auth.sendSignInLinkToEmail(email, actionCodeSettings); auth.sendPasswordResetEmail(email, actionCodeSettings); sendPasswordResetEmail(auth, email, actionCodeSettings); sendSignInLinkToEmail(auth, email, actionCodeSettings); - const user: FirebaseAuthTypes.User = new User(auth as AuthInternal, { + const user: FirebaseAuthTypes.User & ModularUser = new User(auth as AuthInternal, { uid: 'test-user-id', displayName: 'Test User', email: 'test@example.com', diff --git a/packages/auth/lib/types/namespaced.ts b/packages/auth/lib/types/namespaced.ts index c97bb8ef38..d86c37ad6e 100644 --- a/packages/auth/lib/types/namespaced.ts +++ b/packages/auth/lib/types/namespaced.ts @@ -757,19 +757,19 @@ export declare namespace FirebaseAuthTypes { /** * Returns the user's display name, if available. */ - displayName?: string; + displayName?: string | null; /** * Returns the email address corresponding to the user's account in the specified provider, if available. */ - email?: string; + email?: string | null; /** * The phone number normalized based on the E.164 standard (e.g. +16505550101) for the current user. This is null if the user has no phone credential linked to the account. */ - phoneNumber?: string; + phoneNumber?: string | null; /** * Returns a url to the user's profile picture, if available. */ - photoURL?: string; + photoURL?: string | null; /** * Returns the unique identifier of the provider type that this instance corresponds to. */ From 157657a6f74fdef2a14b84296bca165c1e381636 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 30 Apr 2026 10:56:34 +0100 Subject: [PATCH 29/45] fix: namespace "firebase" auth type --- packages/auth/lib/namespaced.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/auth/lib/namespaced.ts b/packages/auth/lib/namespaced.ts index 6951313aa6..0a8e32a31c 100644 --- a/packages/auth/lib/namespaced.ts +++ b/packages/auth/lib/namespaced.ts @@ -687,7 +687,13 @@ export default createModuleNamespace({ // import auth, { firebase } from '@react-native-firebase/auth'; // auth().X(...); // firebase.auth().X(...); -export const firebase = getFirebaseRoot(); +export const firebase = + getFirebaseRoot() as unknown as ReactNativeFirebase.FirebaseNamespacedExport< + 'auth', + FirebaseAuthTypes.Module, + FirebaseAuthTypes.Statics, + false + >; // Register the interop module for non-native platforms. setReactNativeModule(nativeModuleName, fallBackModule); From 852266d19bb6460a9ba815856bba78870c45236f Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 30 Apr 2026 11:02:34 +0100 Subject: [PATCH 30/45] fix: update namespace types --- packages/auth/__tests__/auth.test.ts | 2 +- packages/auth/lib/namespaced.ts | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/packages/auth/__tests__/auth.test.ts b/packages/auth/__tests__/auth.test.ts index fa0ba2f176..159d06e5ff 100644 --- a/packages/auth/__tests__/auth.test.ts +++ b/packages/auth/__tests__/auth.test.ts @@ -233,7 +233,7 @@ describe('Auth', function () { }); it('should allow linkDomain as `ActionCodeSettings.linkDomain`', function () { - const auth = firebase.app().auth(); + const auth = firebase.app().auth() as unknown as FirebaseAuthTypes.Module & AuthInternal; const actionCodeSettings = { url: 'https://example.com', handleCodeInApp: true, diff --git a/packages/auth/lib/namespaced.ts b/packages/auth/lib/namespaced.ts index 0a8e32a31c..c0e8bd6dcc 100644 --- a/packages/auth/lib/namespaced.ts +++ b/packages/auth/lib/namespaced.ts @@ -671,9 +671,7 @@ Object.assign(FirebaseAuthModule.prototype, PasswordPolicyMixin); // import { SDK_VERSION } from '@react-native-firebase/auth'; export const SDK_VERSION = version; -// import auth from '@react-native-firebase/auth'; -// auth().X(...); -export default createModuleNamespace({ +const authNamespace = createModuleNamespace({ statics, version, namespace, @@ -684,6 +682,22 @@ export default createModuleNamespace({ ModuleClass: FirebaseAuthModule, }); +type AuthNamespace = ReactNativeFirebase.FirebaseModuleWithStaticsAndApp< + FirebaseAuthTypes.Module, + FirebaseAuthTypes.Statics +> & { + auth: ReactNativeFirebase.FirebaseModuleWithStaticsAndApp< + FirebaseAuthTypes.Module, + FirebaseAuthTypes.Statics + >; + firebase: ReactNativeFirebase.Module; + app(name?: string): ReactNativeFirebase.FirebaseApp; +}; + +// import auth from '@react-native-firebase/auth'; +// auth().X(...); +export default authNamespace as unknown as AuthNamespace; + // import auth, { firebase } from '@react-native-firebase/auth'; // auth().X(...); // firebase.auth().X(...); From c8f25f2fb13234f6f1a7d1eccf1a88854d4ce258 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 30 Apr 2026 11:13:34 +0100 Subject: [PATCH 31/45] test: fix last remaining unit tests --- packages/auth/__tests__/auth.test.ts | 19 ++++++++++--- .../auth/__tests__/validatePassword.test.js | 27 +++++++++---------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/packages/auth/__tests__/auth.test.ts b/packages/auth/__tests__/auth.test.ts index 159d06e5ff..0e87837566 100644 --- a/packages/auth/__tests__/auth.test.ts +++ b/packages/auth/__tests__/auth.test.ts @@ -79,7 +79,7 @@ import auth, { PhoneAuthState, } from '../lib'; -const PasswordPolicyImpl = require('../lib/password-policy/PasswordPolicyImpl').default; +const { PasswordPolicyImpl } = require('../lib/password-policy/PasswordPolicyImpl'); // @ts-ignore test import FirebaseModule from '../../app/lib/internal/FirebaseModule'; @@ -628,7 +628,14 @@ describe('Auth', function () { it('getMultiFactorResolver', function () { const auth = getAuth(); - const error = new Error() as any; + const error = { + userInfo: { + resolver: { + hints: [], + session: {}, + }, + }, + } as any; authV9Deprecation( () => getMultiFactorResolver(auth, error), // @ts-expect-error Combines modular and namespace API @@ -1012,8 +1019,12 @@ describe('Auth', function () { it('unlink', function () { userV9Deprecation( - () => unlink(mockUser, 'google.com'), - () => mockUser.unlink('google.com'), + () => { + void unlink(mockUser, 'google.com').catch(() => {}); + }, + () => { + void mockUser.unlink('google.com').catch(() => {}); + }, 'unlink', ); }); diff --git a/packages/auth/__tests__/validatePassword.test.js b/packages/auth/__tests__/validatePassword.test.js index daecca77dd..5271a6b781 100644 --- a/packages/auth/__tests__/validatePassword.test.js +++ b/packages/auth/__tests__/validatePassword.test.js @@ -16,8 +16,9 @@ */ import { jest, describe, it, expect, beforeEach, afterEach } from '@jest/globals'; -import { PasswordPolicyImpl } from '../lib/password-policy/PasswordPolicyImpl.js'; -import { PasswordPolicyMixin } from '../lib/password-policy/PasswordPolicyMixin.js'; +import { PasswordPolicyImpl } from '../lib/password-policy/PasswordPolicyImpl'; +import { PasswordPolicyMixin } from '../lib/password-policy/PasswordPolicyMixin'; +import { validatePassword as validatePasswordModular } from '../lib/modular'; const mockPasswordPolicy = { schemaVersion: 1, @@ -274,36 +275,34 @@ describe('validatePassword (modular API)', () => { let validatePassword; let mockAuth; - beforeEach(async () => { - const modular = await import('../lib/modular/index.js'); - validatePassword = modular.validatePassword; - + beforeEach(() => { + validatePassword = validatePasswordModular; mockAuth = { app: { name: '[DEFAULT]', options: { apiKey: 'test-api-key' } }, validatePassword: jest.fn(), }; }); - it('should throw error for undefined auth', async () => { - await expect(validatePassword(undefined, 'Password123$')).rejects.toThrow( + it('should throw error for undefined auth', () => { + expect(() => validatePassword(undefined, 'Password123$')).toThrow( "firebase.auth().validatePassword(*) 'auth' must be a valid Auth instance with an 'app' property", ); }); - it('should throw error for auth without app property', async () => { - await expect(validatePassword({}, 'Password123$')).rejects.toThrow( + it('should throw error for auth without app property', () => { + expect(() => validatePassword({}, 'Password123$')).toThrow( "firebase.auth().validatePassword(*) 'auth' must be a valid Auth instance with an 'app' property", ); }); - it('should throw error for null password', async () => { - await expect(validatePassword(mockAuth, null)).rejects.toThrow( + it('should throw error for null password', () => { + expect(() => validatePassword(mockAuth, null)).toThrow( "firebase.auth().validatePassword(*) expected 'password' to be a non-null or a defined value.", ); }); - it('should throw error for undefined password', async () => { - await expect(validatePassword(mockAuth, undefined)).rejects.toThrow( + it('should throw error for undefined password', () => { + expect(() => validatePassword(mockAuth, undefined)).toThrow( "firebase.auth().validatePassword(*) expected 'password' to be a non-null or a defined value.", ); }); From 4ade4a843af32de54c8510c232cd44798350d347 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 30 Apr 2026 16:05:43 +0100 Subject: [PATCH 32/45] chore: fix type-test and export runtime types from modular.ts --- packages/auth/lib/modular.ts | 40 +++++++++++++++++++++- packages/auth/lib/types/auth.ts | 59 +++++++++------------------------ packages/auth/type-test.ts | 33 +++++++++++------- 3 files changed, 76 insertions(+), 56 deletions(-) diff --git a/packages/auth/lib/modular.ts b/packages/auth/lib/modular.ts index 4b319c7538..3352c24ad6 100644 --- a/packages/auth/lib/modular.ts +++ b/packages/auth/lib/modular.ts @@ -31,7 +31,6 @@ import OIDCAuthProvider from './providers/OIDCAuthProvider'; import PhoneAuthProvider from './providers/PhoneAuthProvider'; import TwitterAuthProvider from './providers/TwitterAuthProvider'; import type { FirebaseApp } from '@react-native-firebase/app'; -import { ActionCodeOperation, FactorId, OperationType, ProviderId } from './types/auth'; import type { ActionCodeInfo, ActionCodeSettings, @@ -83,6 +82,45 @@ type MultiFactorInfoInternal = | MultiFactorInfo | MultiFactorResolverResultInternal['hints'][number]; +export const ActionCodeOperation = { + EMAIL_SIGNIN: 'EMAIL_SIGNIN', + PASSWORD_RESET: 'PASSWORD_RESET', + RECOVER_EMAIL: 'RECOVER_EMAIL', + REVERT_SECOND_FACTOR_ADDITION: 'REVERT_SECOND_FACTOR_ADDITION', + VERIFY_AND_CHANGE_EMAIL: 'VERIFY_AND_CHANGE_EMAIL', + VERIFY_EMAIL: 'VERIFY_EMAIL', +} as const; + +export const FactorId = { + PHONE: 'phone', + TOTP: 'totp', +} as const; + +export const OperationType = { + LINK: 'link', + REAUTHENTICATE: 'reauthenticate', + SIGN_IN: 'signIn', +} as const; + +export const ProviderId = { + FACEBOOK: 'facebook.com', + GITHUB: 'github.com', + GOOGLE: 'google.com', + PASSWORD: 'password', + PHONE: 'phone', + TWITTER: 'twitter.com', +} as const; + +export const SignInMethod = { + EMAIL_LINK: 'emailLink', + EMAIL_PASSWORD: 'password', + FACEBOOK: 'facebook.com', + GITHUB: 'github.com', + GOOGLE: 'google.com', + PHONE: 'phone', + TWITTER: 'twitter.com', +} as const; + const actionCodeOperations = new Set(Object.values(ActionCodeOperation)); function appWithAuth(app?: FirebaseApp): AppWithAuthInternal { diff --git a/packages/auth/lib/types/auth.ts b/packages/auth/lib/types/auth.ts index 28f9e85c31..8fd356fa53 100644 --- a/packages/auth/lib/types/auth.ts +++ b/packages/auth/lib/types/auth.ts @@ -28,44 +28,17 @@ interface Observer { complete?: CompleteFn | null; } -export const ActionCodeOperation = { - EMAIL_SIGNIN: 'EMAIL_SIGNIN', - PASSWORD_RESET: 'PASSWORD_RESET', - RECOVER_EMAIL: 'RECOVER_EMAIL', - REVERT_SECOND_FACTOR_ADDITION: 'REVERT_SECOND_FACTOR_ADDITION', - VERIFY_AND_CHANGE_EMAIL: 'VERIFY_AND_CHANGE_EMAIL', - VERIFY_EMAIL: 'VERIFY_EMAIL', -} as const; - -export const FactorId = { - PHONE: 'phone', - TOTP: 'totp', -} as const; - -export const OperationType = { - LINK: 'link', - REAUTHENTICATE: 'reauthenticate', - SIGN_IN: 'signIn', -} as const; - -export const ProviderId = { - FACEBOOK: 'facebook.com', - GITHUB: 'github.com', - GOOGLE: 'google.com', - PASSWORD: 'password', - PHONE: 'phone', - TWITTER: 'twitter.com', -} as const; - -export const SignInMethod = { - EMAIL_LINK: 'emailLink', - EMAIL_PASSWORD: 'password', - FACEBOOK: 'facebook.com', - GITHUB: 'github.com', - GOOGLE: 'google.com', - PHONE: 'phone', - TWITTER: 'twitter.com', -} as const; +type ActionCodeOperationValue = + | 'EMAIL_SIGNIN' + | 'PASSWORD_RESET' + | 'RECOVER_EMAIL' + | 'REVERT_SECOND_FACTOR_ADDITION' + | 'VERIFY_AND_CHANGE_EMAIL' + | 'VERIFY_EMAIL'; + +type FactorIdValue = 'phone' | 'totp'; + +type OperationTypeValue = 'link' | 'reauthenticate' | 'signIn'; export interface Auth { readonly app: FirebaseApp; @@ -125,7 +98,7 @@ export interface OIDCProvider { } export interface MultiFactorError extends AuthError { readonly customData: AuthError['customData'] & { - readonly operationType: (typeof OperationType)[keyof typeof OperationType]; + readonly operationType: OperationTypeValue; }; } export interface PhoneAuthSnapshot { @@ -302,7 +275,7 @@ export interface User extends UserInfo { export interface UserCredential { user: User; providerId: string | null; - operationType: (typeof OperationType)[keyof typeof OperationType]; + operationType: OperationTypeValue; } export interface ConfirmationResult { @@ -331,18 +304,18 @@ export interface ActionCodeInfo { multiFactorInfo?: MultiFactorInfo | null; previousEmail?: string | null; }; - operation: (typeof ActionCodeOperation)[keyof typeof ActionCodeOperation]; + operation: ActionCodeOperationValue; } export interface MultiFactorAssertion { - readonly factorId: (typeof FactorId)[keyof typeof FactorId]; + readonly factorId: FactorIdValue; } export interface MultiFactorInfo { readonly uid: string; readonly displayName?: string | null; readonly enrollmentTime: string; - readonly factorId: (typeof FactorId)[keyof typeof FactorId]; + readonly factorId: FactorIdValue; } export interface MultiFactorSession {} diff --git a/packages/auth/type-test.ts b/packages/auth/type-test.ts index 1cad47cb8a..8446a3f06a 100644 --- a/packages/auth/type-test.ts +++ b/packages/auth/type-test.ts @@ -19,6 +19,7 @@ import auth, { getAdditionalUserInfo, getAuth, getCustomAuthDomain, + getIdTokenResult, getMultiFactorResolver, getRedirectResult, initializeAuth, @@ -56,6 +57,7 @@ import auth, { type Config, type ConfirmationResult, type Dependencies, + type FirebaseAuthTypes, type IdTokenResult, type MultiFactorError, type PasswordPolicy, @@ -142,38 +144,38 @@ namespacedAuth.sendSignInLinkToEmail('test@example.com', actionCodeSettings); namespacedAuth.verifyPasswordResetCode('oob-code').then((email: string) => console.log(email)); namespacedAuth .checkActionCode('oob-code') - .then((info: ActionCodeInfo) => console.log(info.operation)); + .then((info: FirebaseAuthTypes.ActionCodeInfo) => console.log(info.operation)); namespacedAuth.getCustomAuthDomain().then((domain: string) => console.log(domain)); const namespacedUnsubscribe: Unsubscribe = namespacedAuth.onAuthStateChanged( - (user: User | null) => { + (user: FirebaseAuthTypes.User | null) => { console.log(user?.uid); }, ); namespacedUnsubscribe(); -namespacedAuth.onIdTokenChanged((user: User | null) => { +namespacedAuth.onIdTokenChanged((user: FirebaseAuthTypes.User | null) => { console.log(user?.email); }); namespacedAuth .signInAnonymously() - .then((credential: UserCredential) => console.log(credential.user.uid)); + .then((credential: FirebaseAuthTypes.UserCredential) => console.log(credential.user.uid)); namespacedAuth .createUserWithEmailAndPassword('new@example.com', 'password123') - .then((credential: UserCredential) => console.log(credential.user.email)); + .then((credential: FirebaseAuthTypes.UserCredential) => console.log(credential.user.email)); namespacedAuth .signInWithEmailAndPassword('test@example.com', 'password123') - .then((credential: UserCredential) => console.log(credential.user.email)); + .then((credential: FirebaseAuthTypes.UserCredential) => console.log(credential.user.email)); namespacedAuth .signInWithCustomToken('custom-token') - .then((credential: UserCredential) => console.log(credential.user.uid)); + .then((credential: FirebaseAuthTypes.UserCredential) => console.log(credential.user.uid)); namespacedAuth .signInWithEmailLink('test@example.com', 'email-link') - .then((credential: UserCredential) => console.log(credential.user.email)); + .then((credential: FirebaseAuthTypes.UserCredential) => console.log(credential.user.email)); namespacedAuth .signInWithPhoneNumber('+1234567890') - .then((result: ConfirmationResult) => console.log(result.verificationId)); + .then((result: FirebaseAuthTypes.ConfirmationResult) => console.log(result.verificationId)); namespacedAuth.signOut(); const emailCredential = EmailAuthProvider.credential('test@example.com', 'password123'); @@ -258,13 +260,20 @@ const maybeUser = namespacedAuth.currentUser; if (maybeUser) { maybeUser.reload(); maybeUser.getIdToken().then((token: string) => console.log(token)); - maybeUser.getIdTokenResult().then((result: IdTokenResult) => console.log(result.claims)); + maybeUser + .getIdTokenResult() + .then((result: FirebaseAuthTypes.IdTokenResult) => console.log(result.claims)); maybeUser.sendEmailVerification(actionCodeSettings); maybeUser.updateEmail('new@example.com'); maybeUser.updatePassword('new-password'); maybeUser.updatePhoneNumber(phoneCredential); maybeUser.updateProfile({ displayName: 'New Name', photoURL: 'https://example.com/photo.png' }); - const mfaUser = multiFactor(maybeUser); - mfaUser.getSession(); + const namespacedMfaUser = namespacedAuth.multiFactor(maybeUser); + namespacedMfaUser.getSession(); } + +const modularUser = {} as User; +const modularMfaUser = multiFactor(modularUser); +modularMfaUser.getSession(); +getIdTokenResult(modularUser).then((result: IdTokenResult) => console.log(result.claims)); From 47a59eb9c8d2e0b7b38f9909576b405c026aaa58 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Thu, 30 Apr 2026 16:37:40 +0100 Subject: [PATCH 33/45] test: fix jest test coverage which inherited repo wide include causing problems --- tsconfig-jest.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tsconfig-jest.json b/tsconfig-jest.json index c1784cc877..ec0b6097ae 100644 --- a/tsconfig-jest.json +++ b/tsconfig-jest.json @@ -1,5 +1,12 @@ { "extends": "./tsconfig.json", + "include": [ + "jest.setup.ts", + "packages/app/lib/internal/global.d.ts", + "packages/app/lib/internal/web/memidb/index.d.ts", + "packages/**/__tests__/**/*.test.ts" + ], + "exclude": ["node_modules", "packages/**/dist"], "compilerOptions": { "baseUrl": ".", "paths": { From 01ff4154e6085d27152d7fa165cec7b9bdde31e0 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 1 May 2026 09:38:06 +0100 Subject: [PATCH 34/45] fix: deprecated modular arg breaking e2e tests --- packages/auth/__tests__/auth.test.ts | 22 ++++++++++++++++++++++ packages/auth/lib/modular.ts | 6 ++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/auth/__tests__/auth.test.ts b/packages/auth/__tests__/auth.test.ts index 0e87837566..68b398cbfe 100644 --- a/packages/auth/__tests__/auth.test.ts +++ b/packages/auth/__tests__/auth.test.ts @@ -287,10 +287,32 @@ describe('Auth', function () { expect(getAuth).toBeDefined(); }); + it('getAuth returns the shared namespaced auth instance', function () { + const previousSilenceValue = globalThis.RNFB_SILENCE_MODULAR_DEPRECATION_WARNINGS; + globalThis.RNFB_SILENCE_MODULAR_DEPRECATION_WARNINGS = true; + + try { + expect(getAuth()).toBe(firebase.auth()); + } finally { + globalThis.RNFB_SILENCE_MODULAR_DEPRECATION_WARNINGS = previousSilenceValue; + } + }); + it('`initializeAuth` function is properly exposed to end user', function () { expect(initializeAuth).toBeDefined(); }); + it('initializeAuth returns the shared namespaced auth instance', function () { + const previousSilenceValue = globalThis.RNFB_SILENCE_MODULAR_DEPRECATION_WARNINGS; + globalThis.RNFB_SILENCE_MODULAR_DEPRECATION_WARNINGS = true; + + try { + expect(initializeAuth(firebase.app())).toBe(firebase.auth()); + } finally { + globalThis.RNFB_SILENCE_MODULAR_DEPRECATION_WARNINGS = previousSilenceValue; + } + }); + it('`applyActionCode` function is properly exposed to end user', function () { expect(applyActionCode).toBeDefined(); }); diff --git a/packages/auth/lib/modular.ts b/packages/auth/lib/modular.ts index 3352c24ad6..30b94315c9 100644 --- a/packages/auth/lib/modular.ts +++ b/packages/auth/lib/modular.ts @@ -317,14 +317,16 @@ function callUserMethod( * Returns the Auth instance associated with the provided FirebaseApp. */ export function getAuth(app?: FirebaseApp): Auth { - return appWithAuth(app).auth(MODULAR_DEPRECATION_ARG); + // Keep getAuth() on the shared namespaced instance; method wrappers add the modular sentinel. + return appWithAuth(app).auth(); } /** * This function allows more control over the Auth instance than getAuth(). */ export function initializeAuth(app: FirebaseApp, _deps?: Dependencies): Auth { - return appWithAuth(app).auth(MODULAR_DEPRECATION_ARG); + // Keep initializeAuth() aligned with getAuth(); passing the sentinel here creates a second module. + return appWithAuth(app).auth(); } export function applyActionCode(auth: Auth, oobCode: string): Promise { From b4164ba07be151e5860e8626d2162561fe65c8b8 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 1 May 2026 11:39:47 +0100 Subject: [PATCH 35/45] fix: auth listener logic --- packages/auth/lib/modular.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/auth/lib/modular.ts b/packages/auth/lib/modular.ts index 30b94315c9..25f4d90007 100644 --- a/packages/auth/lib/modular.ts +++ b/packages/auth/lib/modular.ts @@ -281,12 +281,11 @@ function normalizeAuthListener( return nextOrObserver as AuthListenerCallbackInternal; } - return { - next: - typeof nextOrObserver.next === 'function' - ? (nextOrObserver.next as AuthListenerCallbackInternal) - : () => {}, - }; + if (typeof nextOrObserver.next !== 'function') { + return { next: () => {} }; + } + + return nextOrObserver as { next: AuthListenerCallbackInternal }; } function callAuthMethod( From 479e9414dcfdfa6c2a4a391db404aa1cea4fe1fd Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 1 May 2026 11:50:50 +0100 Subject: [PATCH 36/45] chore: update error message for e2e tests --- packages/auth/lib/modular.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/auth/lib/modular.ts b/packages/auth/lib/modular.ts index 25f4d90007..5137a2a449 100644 --- a/packages/auth/lib/modular.ts +++ b/packages/auth/lib/modular.ts @@ -404,7 +404,7 @@ export function getRedirectResult( _auth: Auth, _resolver?: PopupRedirectResolver, ): Promise { - throw new Error('getRedirectResult is unsupported by the native Firebase SDKs'); + throw new Error('getRedirectResult is unsupported by the native Firebase SDKs.'); } export function isSignInWithEmailLink(auth: Auth, emailLink: string): Promise { @@ -477,7 +477,7 @@ export function sendSignInLinkToEmail( } export function setPersistence(_auth: Auth, _persistence: Persistence): Promise { - throw new Error('setPersistence is unsupported by the native Firebase SDKs'); + throw new Error('setPersistence is unsupported by the native Firebase SDKs.'); } export function signInAnonymously(auth: Auth): Promise { From 1dd6f62f5b4a4a3f6636646d8d6eaf8483f6a365 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 1 May 2026 12:08:59 +0100 Subject: [PATCH 37/45] test: check that all user credential properties are available to consumer --- packages/auth/e2e/phone.e2e.js | 62 +++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/packages/auth/e2e/phone.e2e.js b/packages/auth/e2e/phone.e2e.js index 217f220589..f67c68eefa 100644 --- a/packages/auth/e2e/phone.e2e.js +++ b/packages/auth/e2e/phone.e2e.js @@ -3,6 +3,54 @@ const { clearAllUsers, getLastSmsCode, getRandomPhoneNumber } = require('./helpers'); +function assertPhoneUserPublicSurface(user, phoneNumber) { + user.should.be.an.Object(); + user.uid.should.be.a.String(); + user.uid.length.should.be.greaterThan(0); + user.phoneNumber.should.equal(phoneNumber); + user.providerId.should.equal('firebase'); + user.emailVerified.should.equal(false); + user.isAnonymous.should.equal(false); + should.equal(user.displayName, null); + should.equal(user.email, null); + should.equal(user.photoURL, null); + should.equal(user.tenantId, null); + + user.metadata.should.be.an.Object(); + user.metadata.creationTime.should.be.a.String(); + user.metadata.lastSignInTime.should.be.a.String(); + + user.multiFactor.should.be.an.Object(); + user.multiFactor.enrolledFactors.should.be.an.Array(); + + user.providerData.should.be.an.Array(); + user.providerData.length.should.equal(1); + user.providerData[0].providerId.should.equal('phone'); + user.providerData[0].phoneNumber.should.equal(phoneNumber); + should.equal(user.providerData[0].displayName, null); + should.equal(user.providerData[0].email, null); + should.equal(user.providerData[0].photoURL, null); + + user.delete.should.be.a.Function(); + user.getIdToken.should.be.a.Function(); + user.getIdTokenResult.should.be.a.Function(); + user.linkWithCredential.should.be.a.Function(); + user.linkWithPopup.should.be.a.Function(); + user.linkWithRedirect.should.be.a.Function(); + user.reauthenticateWithCredential.should.be.a.Function(); + user.reauthenticateWithPopup.should.be.a.Function(); + user.reauthenticateWithRedirect.should.be.a.Function(); + user.reload.should.be.a.Function(); + user.sendEmailVerification.should.be.a.Function(); + user.toJSON.should.be.a.Function(); + user.unlink.should.be.a.Function(); + user.updateEmail.should.be.a.Function(); + user.updatePassword.should.be.a.Function(); + user.updatePhoneNumber.should.be.a.Function(); + user.updateProfile.should.be.a.Function(); + user.verifyBeforeUpdateEmail.should.be.a.Function(); +} + describe('auth() => Phone', function () { // Other platforms don't support phone auth if (Platform.other) { @@ -46,12 +94,7 @@ describe('auth() => Phone', function () { confirmResult.confirm.should.be.a.Function(); const lastSmsCode = await getLastSmsCode(testPhone); const userCredential = await confirmResult.confirm(lastSmsCode); - userCredential.user.should.be.instanceOf( - require('@react-native-firebase/auth/lib/User').default, - ); - - // Broken check, phone number is undefined - // userCredential.user.phoneNumber.should.equal(TEST_PHONE_A); + assertPhoneUserPublicSurface(userCredential.user, testPhone); }); it('errors on invalid code', async function () { @@ -237,12 +280,7 @@ describe('auth() => Phone', function () { confirmResult.confirm.should.be.a.Function(); const lastSmsCode = await getLastSmsCode(testPhone); const userCredential = await confirmResult.confirm(lastSmsCode); - userCredential.user.should.be.instanceOf( - require('@react-native-firebase/auth/lib/User').default, - ); - - // Broken check, phone number is undefined - // userCredential.user.phoneNumber.should.equal(TEST_PHONE_A); + assertPhoneUserPublicSurface(userCredential.user, testPhone); }); it('errors on invalid code', async function () { From 2cb8bfe737465fb8fc54d9ed7cb71cd0cbab867c Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 1 May 2026 12:36:05 +0100 Subject: [PATCH 38/45] chore: update auth typedoc --- packages/auth/lib/types/namespaced.ts | 9 ++++----- packages/auth/typedoc.json | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/auth/lib/types/namespaced.ts b/packages/auth/lib/types/namespaced.ts index d86c37ad6e..0113aacedb 100644 --- a/packages/auth/lib/types/namespaced.ts +++ b/packages/auth/lib/types/namespaced.ts @@ -203,7 +203,7 @@ export declare namespace FirebaseAuthTypes { * * @returns {@link AuthCredential}. * @param oidcSuffix this is the "Provider ID" value from the firebase console fx `azure_test`. - * @param token A provider token. + * @param idToken A provider ID token. */ credential: (oidcSuffix: string, idToken: string) => AuthCredential; } @@ -1753,7 +1753,7 @@ export declare namespace FirebaseAuthTypes { * await firebase.auth().setLanguageCode('fr'); * ``` * - * @param code An ISO language code. + * @param languageCode An ISO language code. * 'null' value will set the language code to the app's current language. */ setLanguageCode(languageCode: string | null): Promise; @@ -1825,7 +1825,6 @@ export declare namespace FirebaseAuthTypes { * * > This is an experimental feature and is only part of React Native Firebase. * - * @react-native-firebase * @param listener A listener function which triggers when the users data changes. */ onUserChanged(listener: CallbackOrObserver): () => void; @@ -2306,13 +2305,13 @@ export declare namespace FirebaseAuthTypes { * If you want to use the emulator on a real android device, you will need to specify the actual host * computer IP address. * - * @param url: emulator URL, must have host and port (eg, 'http://localhost:9099') + * @param url emulator URL, must have host and port (eg, 'http://localhost:9099') */ useEmulator(url: string): void; /** * Provides a MultiFactorResolver suitable for completion of a multi-factor flow. * - * @param error: The MultiFactorError raised during a sign-in, or reauthentication operation. + * @param error The MultiFactorError raised during a sign-in, or reauthentication operation. */ getMultiFactorResolver(error: MultiFactorError): MultiFactorResolver; /** diff --git a/packages/auth/typedoc.json b/packages/auth/typedoc.json index 12fefc5cf3..a469f5a41a 100644 --- a/packages/auth/typedoc.json +++ b/packages/auth/typedoc.json @@ -1,5 +1,15 @@ { "$schema": "https://typedoc.org/schema.json", - "entryPoints": ["lib/index.d.ts"], - "intentionallyNotExported": ["AuthNamespace"] + "entryPoints": ["lib/index.ts"], + "tsconfig": "tsconfig.json", + "intentionallyNotExported": [ + "AuthNamespace", + "Observer", + "ActionCodeOperationValue", + "FactorIdValue", + "OperationTypeValue", + "PhoneAuthProviderAuth", + "SupportedPhoneInfoOptions", + "AuthInternal" + ] } From 8ced9239b8eb7738ba34924ad7470e04311edfbc Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 1 May 2026 12:37:47 +0100 Subject: [PATCH 39/45] chore: extend tsdoc to stop warnings --- packages/auth/tsdoc.json | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 packages/auth/tsdoc.json diff --git a/packages/auth/tsdoc.json b/packages/auth/tsdoc.json new file mode 100644 index 0000000000..50e975883b --- /dev/null +++ b/packages/auth/tsdoc.json @@ -0,0 +1,22 @@ +{ + "extends": ["typedoc/tsdoc.json"], + "tagDefinitions": [ + { + "tagName": "@error", + "syntaxKind": "block", + "allowMultiple": true + }, + { + "tagName": "@android", + "syntaxKind": "block" + }, + { + "tagName": "@salakar", + "syntaxKind": "block" + }, + { + "tagName": "@platform", + "syntaxKind": "block" + } + ] +} From 25f9d3a844c89a303016716c385c9785bda1da15 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 1 May 2026 12:43:04 +0100 Subject: [PATCH 40/45] chore: update auth config with more API with different shape --- .../compare-types/packages/auth/config.ts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.github/scripts/compare-types/packages/auth/config.ts b/.github/scripts/compare-types/packages/auth/config.ts index f0055a1ff0..6701b3b81a 100644 --- a/.github/scripts/compare-types/packages/auth/config.ts +++ b/.github/scripts/compare-types/packages/auth/config.ts @@ -170,6 +170,26 @@ const config: PackageConfig = { reason: 'RN Firebase models disableWarnings as an optional property, while the firebase-js-sdk emitted type text shows a required boolean property.', }, + { + name: 'ActionCodeInfo', + reason: + 'Semantically the same action-code operation string union; RN Firebase types spell `operation` as `ActionCodeOperationValue`, while the firebase-js-sdk snapshot uses `(typeof ActionCodeOperation)[keyof typeof ActionCodeOperation]`, which compare-types treats as a different shape string.', + }, + { + name: 'MultiFactorAssertion', + reason: + 'Same factor-id string union as the SDK; RN Firebase exposes `FactorIdValue` on `factorId`, while the firebase-js-sdk snapshot uses `(typeof FactorId)[keyof typeof FactorId]`, which differs only in emitted type text.', + }, + { + name: 'MultiFactorError', + reason: + 'Same operation-type string union as the SDK; RN Firebase narrows `customData.operationType` to `OperationTypeValue`, while the firebase-js-sdk snapshot uses `(typeof OperationType)[keyof typeof OperationType]`, which compare-types compares textually.', + }, + { + name: 'MultiFactorInfo', + reason: + 'Same factor-id string union as the SDK; RN Firebase exposes `FactorIdValue` on `factorId`, while the firebase-js-sdk snapshot uses `(typeof FactorId)[keyof typeof FactorId]`, which differs only in emitted type text.', + }, { name: 'EmailAuthProvider', reason: @@ -250,6 +270,11 @@ const config: PackageConfig = { reason: 'RN Firebase now exports TwitterAuthProvider from the modular surface, but its native helper class only exposes the credential factory used by RNFB and does not yet mirror the firebase-js-sdk static fields and credentialFromResult/credentialFromError helpers.', }, + { + name: 'UserCredential', + reason: + 'Same operation-type string union as the SDK; RN Firebase exposes `operationType` as `OperationTypeValue`, while the firebase-js-sdk snapshot uses `(typeof OperationType)[keyof typeof OperationType]`, which compare-types treats as a different shape string.', + }, ], }; From 43be2355815176a0074aa2769e864523a9fdfc69 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 1 May 2026 13:57:32 +0100 Subject: [PATCH 41/45] fix: validatePassword modular API type --- packages/auth/lib/modular.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/auth/lib/modular.ts b/packages/auth/lib/modular.ts index 5137a2a449..798bbac323 100644 --- a/packages/auth/lib/modular.ts +++ b/packages/auth/lib/modular.ts @@ -865,7 +865,7 @@ export function getCustomAuthDomain(auth: Auth): Promise { export function validatePassword(auth: Auth, password: string): Promise { if (!auth || !('app' in auth)) { throw new Error( - "firebase.auth().validatePassword(*) 'auth' must be a valid Auth instance with an 'app' property. Received: undefined", + `firebase.auth().validatePassword(*) 'auth' must be a valid Auth instance with an 'app' property`, ); } From 86bb09e0bc42c1193ac72197ebedfe9c19536607 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Fri, 1 May 2026 14:41:09 +0100 Subject: [PATCH 42/45] test: update error message contain --- packages/auth/e2e/validatePassword.e2e.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/auth/e2e/validatePassword.e2e.js b/packages/auth/e2e/validatePassword.e2e.js index 0cb82746ce..44d102d8a8 100644 --- a/packages/auth/e2e/validatePassword.e2e.js +++ b/packages/auth/e2e/validatePassword.e2e.js @@ -72,8 +72,7 @@ describe('auth() -> validatePassword()', function () { try { await validatePassword(undefined, 'Testing123$'); } catch (e) { - e.message.should.containEql('app'); - e.message.should.containEql('undefined'); + e.message.should.containEql("'auth' must be a valid Auth instance"); } }); }); From 60180358438b115bf0fc4ce1f2e82665fa333f70 Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Tue, 12 May 2026 18:02:01 +0100 Subject: [PATCH 43/45] chore: move auth config to latest implementation --- .../auth/config.ts => configs/auth.ts} | 0 .../packages/auth/auth-js-sdk.d.ts | 4067 ----------------- .github/scripts/compare-types/src/registry.ts | 1 + 3 files changed, 1 insertion(+), 4067 deletions(-) rename .github/scripts/compare-types/{packages/auth/config.ts => configs/auth.ts} (100%) delete mode 100644 .github/scripts/compare-types/packages/auth/auth-js-sdk.d.ts diff --git a/.github/scripts/compare-types/packages/auth/config.ts b/.github/scripts/compare-types/configs/auth.ts similarity index 100% rename from .github/scripts/compare-types/packages/auth/config.ts rename to .github/scripts/compare-types/configs/auth.ts diff --git a/.github/scripts/compare-types/packages/auth/auth-js-sdk.d.ts b/.github/scripts/compare-types/packages/auth/auth-js-sdk.d.ts deleted file mode 100644 index a237bcb009..0000000000 --- a/.github/scripts/compare-types/packages/auth/auth-js-sdk.d.ts +++ /dev/null @@ -1,4067 +0,0 @@ -/** - * Firebase Authentication - * - * @packageDocumentation - */ - -import { CompleteFn } from '@firebase/util'; -import { ErrorFactory } from '@firebase/util'; -import { ErrorFn } from '@firebase/util'; -import { FirebaseApp } from '@firebase/app'; -import { FirebaseError } from '@firebase/util'; -import { NextFn } from '@firebase/util'; -import { Observer } from '@firebase/util'; -import { Unsubscribe } from '@firebase/util'; - -/** - * A response from {@link checkActionCode}. - * - * @public - */ -export declare interface ActionCodeInfo { - /** - * The data associated with the action code. - * - * @remarks - * For the {@link ActionCodeOperation}.PASSWORD_RESET, {@link ActionCodeOperation}.VERIFY_EMAIL, and - * {@link ActionCodeOperation}.RECOVER_EMAIL actions, this object contains an email field with the address - * the email was sent to. - * - * For the {@link ActionCodeOperation}.RECOVER_EMAIL action, which allows a user to undo an email address - * change, this object also contains a `previousEmail` field with the user account's current - * email address. After the action completes, the user's email address will revert to the value - * in the `email` field from the value in `previousEmail` field. - * - * For the {@link ActionCodeOperation}.VERIFY_AND_CHANGE_EMAIL action, which allows a user to verify the - * email before updating it, this object contains a `previousEmail` field with the user account's - * email address before updating. After the action completes, the user's email address will be - * updated to the value in the `email` field from the value in `previousEmail` field. - * - * For the {@link ActionCodeOperation}.REVERT_SECOND_FACTOR_ADDITION action, which allows a user to - * unenroll a newly added second factor, this object contains a `multiFactorInfo` field with - * the information about the second factor. For phone second factor, the `multiFactorInfo` - * is a {@link MultiFactorInfo} object, which contains the phone number. - */ - data: { - email?: string | null; - multiFactorInfo?: MultiFactorInfo | null; - previousEmail?: string | null; - }; - /** - * The type of operation that generated the action code. - */ - operation: (typeof ActionCodeOperation)[keyof typeof ActionCodeOperation]; -} - -/** - * An enumeration of the possible email action types. - * - * @public - */ -export declare const ActionCodeOperation: { - /** The email link sign-in action. */ - readonly EMAIL_SIGNIN: "EMAIL_SIGNIN"; - /** The password reset action. */ - readonly PASSWORD_RESET: "PASSWORD_RESET"; - /** The email revocation action. */ - readonly RECOVER_EMAIL: "RECOVER_EMAIL"; - /** The revert second factor addition email action. */ - readonly REVERT_SECOND_FACTOR_ADDITION: "REVERT_SECOND_FACTOR_ADDITION"; - /** The revert second factor addition email action. */ - readonly VERIFY_AND_CHANGE_EMAIL: "VERIFY_AND_CHANGE_EMAIL"; - /** The email verification action. */ - readonly VERIFY_EMAIL: "VERIFY_EMAIL"; -}; - -/** - * An interface that defines the required continue/state URL with optional Android and iOS - * bundle identifiers. - * - * @public - */ -export declare interface ActionCodeSettings { - /** - * Sets the Android package name. - * - * @remarks - * This will try to open the link in an Android app if it is installed. - */ - android?: { - installApp?: boolean; - minimumVersion?: string; - packageName: string; - }; - /** - * When set to true, the action code link will be be sent as a Universal Link or Android App - * Link and will be opened by the app if installed. - * - * @remarks - * In the false case, the code will be sent to the web widget first and then on continue will - * redirect to the app if installed. - * - * @defaultValue false - */ - handleCodeInApp?: boolean; - /** - * Sets the iOS bundle ID. - * - * @remarks - * This will try to open the link in an iOS app if it is installed. - */ - iOS?: { - bundleId: string; - }; - /** - * Sets the link continue/state URL. - * - * @remarks - * This has different meanings in different contexts: - * - When the link is handled in the web action widgets, this is the deep link in the - * `continueUrl` query parameter. - * - When the link is handled in the app directly, this is the `continueUrl` query parameter in - * the deep link of the Dynamic Link or Hosting link. - */ - url: string; - /** - * When multiple custom dynamic link domains are defined for a project, specify which one to use - * when the link is to be opened via a specified mobile app (for example, `example.page.link`). - * - * - * @defaultValue The first domain is automatically selected. - * - * @deprecated Firebase Dynamic Links is deprecated and will be shut down as early as August - * 2025. Instead, use {@link ActionCodeSettings.linkDomain} to set a custom domain for mobile - * links. Learn more in the {@link https://firebase.google.com/support/dynamic-links-faq | Dynamic Links deprecation FAQ}. - */ - dynamicLinkDomain?: string; - /** - * The optional custom Firebase Hosting domain to use when the link is to be opened via - * a specified mobile app. The domain must be configured in Firebase Hosting and owned - * by the project. This cannot be a default Hosting domain (`web.app` or `firebaseapp.com`). - * - * @defaultValue The default Hosting domain will be used (for example, `example.firebaseapp.com`). - */ - linkDomain?: string; -} - -/** - * @license - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * A utility class to parse email action URLs such as password reset, email verification, - * email link sign in, etc. - * - * @public - */ -export declare class ActionCodeURL { - /** - * The API key of the email action link. - */ - readonly apiKey: string; - /** - * The action code of the email action link. - */ - readonly code: string; - /** - * The continue URL of the email action link. Null if not provided. - */ - readonly continueUrl: string | null; - /** - * The language code of the email action link. Null if not provided. - */ - readonly languageCode: string | null; - /** - * The action performed by the email action link. It returns from one of the types from - * {@link ActionCodeInfo} - */ - readonly operation: string; - /** - * The tenant ID of the email action link. Null if the email action is from the parent project. - */ - readonly tenantId: string | null; - /* Excluded from this release type: __constructor */ - /** - * Parses the email action link string and returns an {@link ActionCodeURL} if the link is valid, - * otherwise returns null. - * - * @param link - The email action link string. - * @returns The {@link ActionCodeURL} object, or null if the link is invalid. - * - * @public - */ - static parseLink(link: string): ActionCodeURL | null; -} - -/** - * A structure containing additional user information from a federated identity provider. - * - * @public - */ -export declare interface AdditionalUserInfo { - /** - * Whether the user is new (created via sign-up) or existing (authenticated using sign-in). - */ - readonly isNewUser: boolean; - /** - * Map containing IDP-specific user data. - */ - readonly profile: Record | null; - /** - * Identifier for the provider used to authenticate this user. - */ - readonly providerId: string | null; - /** - * The username if the provider is GitHub or Twitter. - */ - readonly username?: string | null; -} - -declare interface APIUserInfo { - localId?: string; - displayName?: string; - photoUrl?: string; - email?: string; - emailVerified?: boolean; - phoneNumber?: string; - lastLoginAt?: number; - createdAt?: number; - tenantId?: string; - passwordHash?: string; - providerUserInfo?: ProviderUserInfo[]; - mfaInfo?: MfaEnrollment[]; -} - -/** - * A verifier for domain verification and abuse prevention. - * - * @remarks - * Currently, the only implementation is {@link RecaptchaVerifier}. - * - * @public - */ -export declare interface ApplicationVerifier { - /** - * Identifies the type of application verifier (e.g. "recaptcha"). - */ - readonly type: string; - /** - * Executes the verification process. - * - * @returns A Promise for a token that can be used to assert the validity of a request. - */ - verify(): Promise; -} - -declare interface ApplicationVerifierInternal extends ApplicationVerifier { - /* Excluded from this release type: _reset */ -} - -/** - * Applies a verification code sent to the user by email or other out-of-band mechanism. - * - * @param auth - The {@link Auth} instance. - * @param oobCode - A verification code sent to the user. - * - * @public - */ -export declare function applyActionCode(auth: Auth, oobCode: string): Promise; - -declare type AppName = string; - -/** - * Interface representing Firebase Auth service. - * - * @remarks - * See {@link https://firebase.google.com/docs/auth/ | Firebase Authentication} for a full guide - * on how to use the Firebase Auth service. - * - * @public - */ -export declare interface Auth { - /** The {@link @firebase/app#FirebaseApp} associated with the `Auth` service instance. */ - readonly app: FirebaseApp; - /** The name of the app associated with the `Auth` service instance. */ - readonly name: string; - /** The {@link Config} used to initialize this instance. */ - readonly config: Config; - /** - * Changes the type of persistence on the `Auth` instance. - * - * @remarks - * This will affect the currently saved Auth session and applies this type of persistence for - * future sign-in requests, including sign-in with redirect requests. - * - * This makes it easy for a user signing in to specify whether their session should be - * remembered or not. It also makes it easier to never persist the Auth state for applications - * that are shared by other users or have sensitive data. - * - * This method does not work in a Node.js environment. - * - * @example - * ```javascript - * auth.setPersistence(browserSessionPersistence); - * ``` - * - * @param persistence - The {@link Persistence} to use. - */ - setPersistence(persistence: Persistence): Promise; - /** - * The {@link Auth} instance's language code. - * - * @remarks - * This is a readable/writable property. When set to null, the default Firebase Console language - * setting is applied. The language code will propagate to email action templates (password - * reset, email verification and email change revocation), SMS templates for phone authentication, - * reCAPTCHA verifier and OAuth popup/redirect operations provided the specified providers support - * localization with the language code specified. - */ - languageCode: string | null; - /** - * The {@link Auth} instance's tenant ID. - * - * @remarks - * This is a readable/writable property. When you set the tenant ID of an {@link Auth} instance, all - * future sign-in/sign-up operations will pass this tenant ID and sign in or sign up users to - * the specified tenant project. When set to null, users are signed in to the parent project. - * - * @example - * ```javascript - * // Set the tenant ID on Auth instance. - * auth.tenantId = 'TENANT_PROJECT_ID'; - * - * // All future sign-in request now include tenant ID. - * const result = await signInWithEmailAndPassword(auth, email, password); - * // result.user.tenantId should be 'TENANT_PROJECT_ID'. - * ``` - * - * @defaultValue null - */ - tenantId: string | null; - /** - * The {@link Auth} instance's settings. - * - * @remarks - * This is used to edit/read configuration related options such as app verification mode for - * phone authentication. - */ - readonly settings: AuthSettings; - /** - * Adds an observer for changes to the user's sign-in state. - * - * @remarks - * To keep the old behavior, see {@link Auth.onIdTokenChanged}. - * - * @param nextOrObserver - callback triggered on change. - * @param error - Deprecated. This callback is never triggered. Errors - * on signing in/out can be caught in promises returned from - * sign-in/sign-out functions. - * @param completed - Deprecated. This callback is never triggered. - */ - onAuthStateChanged(nextOrObserver: NextOrObserver, error?: ErrorFn, completed?: CompleteFn): Unsubscribe; - /** - * Adds a blocking callback that runs before an auth state change - * sets a new user. - * - * @param callback - callback triggered before new user value is set. - * If this throws, it blocks the user from being set. - * @param onAbort - callback triggered if a later `beforeAuthStateChanged()` - * callback throws, allowing you to undo any side effects. - */ - beforeAuthStateChanged(callback: (user: User | null) => void | Promise, onAbort?: () => void): Unsubscribe; - /** - * Adds an observer for changes to the signed-in user's ID token. - * - * @remarks - * This includes sign-in, sign-out, and token refresh events. - * - * @param nextOrObserver - callback triggered on change. - * @param error - Deprecated. This callback is never triggered. Errors - * on signing in/out can be caught in promises returned from - * sign-in/sign-out functions. - * @param completed - Deprecated. This callback is never triggered. - */ - onIdTokenChanged(nextOrObserver: NextOrObserver, error?: ErrorFn, completed?: CompleteFn): Unsubscribe; - /** - * returns a promise that resolves immediately when the initial - * auth state is settled. When the promise resolves, the current user might be a valid user - * or `null` if the user signed out. - */ - authStateReady(): Promise; - /** The currently signed-in user (or null). */ - readonly currentUser: User | null; - /** The current emulator configuration (or null). */ - readonly emulatorConfig: EmulatorConfig | null; - /** - * Asynchronously sets the provided user as {@link Auth.currentUser} on the {@link Auth} instance. - * - * @remarks - * A new instance copy of the user provided will be made and set as currentUser. - * - * This will trigger {@link Auth.onAuthStateChanged} and {@link Auth.onIdTokenChanged} listeners - * like other sign in methods. - * - * The operation fails with an error if the user to be updated belongs to a different Firebase - * project. - * - * @param user - The new {@link User}. - */ - updateCurrentUser(user: User | null): Promise; - /** - * Sets the current language to the default device/browser preference. - */ - useDeviceLanguage(): void; - /** - * Signs out the current user. This does not automatically revoke the user's ID token. - * - * @remarks - * This method is not supported by {@link Auth} instances created with a - * {@link @firebase/app#FirebaseServerApp}. - */ - signOut(): Promise; -} - -/** - * Interface that represents the credentials returned by an {@link AuthProvider}. - * - * @remarks - * Implementations specify the details about each auth provider's credential requirements. - * - * @public - */ -export declare class AuthCredential { - /** - * The authentication provider ID for the credential. - * - * @remarks - * For example, 'facebook.com', or 'google.com'. - */ - readonly providerId: string; - /** - * The authentication sign in method for the credential. - * - * @remarks - * For example, {@link SignInMethod}.EMAIL_PASSWORD, or - * {@link SignInMethod}.EMAIL_LINK. This corresponds to the sign-in method - * identifier as returned in {@link fetchSignInMethodsForEmail}. - */ - readonly signInMethod: string; - /* Excluded from this release type: __constructor */ - /** - * Returns a JSON-serializable representation of this object. - * - * @returns a JSON-serializable representation of this object. - */ - toJSON(): object; - /* Excluded from this release type: _getIdTokenResponse */ - /* Excluded from this release type: _linkToIdToken */ - /* Excluded from this release type: _getReauthenticationResolver */ -} - -/** - * Interface for an `Auth` error. - * - * @public - */ -export declare interface AuthError extends FirebaseError { - /** Details about the Firebase Auth error. */ - readonly customData: { - /** The name of the Firebase App which triggered this error. */ - readonly appName: string; - /** The email address of the user's account, used for sign-in and linking. */ - readonly email?: string; - /** The phone number of the user's account, used for sign-in and linking. */ - readonly phoneNumber?: string; - /** - * The tenant ID being used for sign-in and linking. - * - * @remarks - * If you use {@link signInWithRedirect} to sign in, - * you have to set the tenant ID on the {@link Auth} instance again as the tenant ID is not persisted - * after redirection. - */ - readonly tenantId?: string; - }; -} - -/* Excluded from this release type: AuthErrorCode */ - -/** - * A map of potential `Auth` error codes, for easier comparison with errors - * thrown by the SDK. - * - * @remarks - * Note that you can't tree-shake individual keys - * in the map, so by using the map you might substantially increase your - * bundle size. - * - * @public - */ -export declare const AuthErrorCodes: { - readonly ADMIN_ONLY_OPERATION: "auth/admin-restricted-operation"; - readonly ARGUMENT_ERROR: "auth/argument-error"; - readonly APP_NOT_AUTHORIZED: "auth/app-not-authorized"; - readonly APP_NOT_INSTALLED: "auth/app-not-installed"; - readonly CAPTCHA_CHECK_FAILED: "auth/captcha-check-failed"; - readonly CODE_EXPIRED: "auth/code-expired"; - readonly CORDOVA_NOT_READY: "auth/cordova-not-ready"; - readonly CORS_UNSUPPORTED: "auth/cors-unsupported"; - readonly CREDENTIAL_ALREADY_IN_USE: "auth/credential-already-in-use"; - readonly CREDENTIAL_MISMATCH: "auth/custom-token-mismatch"; - readonly CREDENTIAL_TOO_OLD_LOGIN_AGAIN: "auth/requires-recent-login"; - readonly DEPENDENT_SDK_INIT_BEFORE_AUTH: "auth/dependent-sdk-initialized-before-auth"; - readonly DYNAMIC_LINK_NOT_ACTIVATED: "auth/dynamic-link-not-activated"; - readonly EMAIL_CHANGE_NEEDS_VERIFICATION: "auth/email-change-needs-verification"; - readonly EMAIL_EXISTS: "auth/email-already-in-use"; - readonly EMULATOR_CONFIG_FAILED: "auth/emulator-config-failed"; - readonly EXPIRED_OOB_CODE: "auth/expired-action-code"; - readonly EXPIRED_POPUP_REQUEST: "auth/cancelled-popup-request"; - readonly INTERNAL_ERROR: "auth/internal-error"; - readonly INVALID_API_KEY: "auth/invalid-api-key"; - readonly INVALID_APP_CREDENTIAL: "auth/invalid-app-credential"; - readonly INVALID_APP_ID: "auth/invalid-app-id"; - readonly INVALID_AUTH: "auth/invalid-user-token"; - readonly INVALID_AUTH_EVENT: "auth/invalid-auth-event"; - readonly INVALID_CERT_HASH: "auth/invalid-cert-hash"; - readonly INVALID_CODE: "auth/invalid-verification-code"; - readonly INVALID_CONTINUE_URI: "auth/invalid-continue-uri"; - readonly INVALID_CORDOVA_CONFIGURATION: "auth/invalid-cordova-configuration"; - readonly INVALID_CUSTOM_TOKEN: "auth/invalid-custom-token"; - readonly INVALID_DYNAMIC_LINK_DOMAIN: "auth/invalid-dynamic-link-domain"; - readonly INVALID_EMAIL: "auth/invalid-email"; - readonly INVALID_EMULATOR_SCHEME: "auth/invalid-emulator-scheme"; - readonly INVALID_IDP_RESPONSE: "auth/invalid-credential"; - readonly INVALID_LOGIN_CREDENTIALS: "auth/invalid-credential"; - readonly INVALID_MESSAGE_PAYLOAD: "auth/invalid-message-payload"; - readonly INVALID_MFA_SESSION: "auth/invalid-multi-factor-session"; - readonly INVALID_OAUTH_CLIENT_ID: "auth/invalid-oauth-client-id"; - readonly INVALID_OAUTH_PROVIDER: "auth/invalid-oauth-provider"; - readonly INVALID_OOB_CODE: "auth/invalid-action-code"; - readonly INVALID_ORIGIN: "auth/unauthorized-domain"; - readonly INVALID_PASSWORD: "auth/wrong-password"; - readonly INVALID_PERSISTENCE: "auth/invalid-persistence-type"; - readonly INVALID_PHONE_NUMBER: "auth/invalid-phone-number"; - readonly INVALID_PROVIDER_ID: "auth/invalid-provider-id"; - readonly INVALID_RECIPIENT_EMAIL: "auth/invalid-recipient-email"; - readonly INVALID_SENDER: "auth/invalid-sender"; - readonly INVALID_SESSION_INFO: "auth/invalid-verification-id"; - readonly INVALID_TENANT_ID: "auth/invalid-tenant-id"; - readonly MFA_INFO_NOT_FOUND: "auth/multi-factor-info-not-found"; - readonly MFA_REQUIRED: "auth/multi-factor-auth-required"; - readonly MISSING_ANDROID_PACKAGE_NAME: "auth/missing-android-pkg-name"; - readonly MISSING_APP_CREDENTIAL: "auth/missing-app-credential"; - readonly MISSING_AUTH_DOMAIN: "auth/auth-domain-config-required"; - readonly MISSING_CODE: "auth/missing-verification-code"; - readonly MISSING_CONTINUE_URI: "auth/missing-continue-uri"; - readonly MISSING_IFRAME_START: "auth/missing-iframe-start"; - readonly MISSING_IOS_BUNDLE_ID: "auth/missing-ios-bundle-id"; - readonly MISSING_OR_INVALID_NONCE: "auth/missing-or-invalid-nonce"; - readonly MISSING_MFA_INFO: "auth/missing-multi-factor-info"; - readonly MISSING_MFA_SESSION: "auth/missing-multi-factor-session"; - readonly MISSING_PHONE_NUMBER: "auth/missing-phone-number"; - readonly MISSING_PASSWORD: "auth/missing-password"; - readonly MISSING_SESSION_INFO: "auth/missing-verification-id"; - readonly MODULE_DESTROYED: "auth/app-deleted"; - readonly NEED_CONFIRMATION: "auth/account-exists-with-different-credential"; - readonly NETWORK_REQUEST_FAILED: "auth/network-request-failed"; - readonly NULL_USER: "auth/null-user"; - readonly NO_AUTH_EVENT: "auth/no-auth-event"; - readonly NO_SUCH_PROVIDER: "auth/no-such-provider"; - readonly OPERATION_NOT_ALLOWED: "auth/operation-not-allowed"; - readonly OPERATION_NOT_SUPPORTED: "auth/operation-not-supported-in-this-environment"; - readonly POPUP_BLOCKED: "auth/popup-blocked"; - readonly POPUP_CLOSED_BY_USER: "auth/popup-closed-by-user"; - readonly PROVIDER_ALREADY_LINKED: "auth/provider-already-linked"; - readonly QUOTA_EXCEEDED: "auth/quota-exceeded"; - readonly REDIRECT_CANCELLED_BY_USER: "auth/redirect-cancelled-by-user"; - readonly REDIRECT_OPERATION_PENDING: "auth/redirect-operation-pending"; - readonly REJECTED_CREDENTIAL: "auth/rejected-credential"; - readonly SECOND_FACTOR_ALREADY_ENROLLED: "auth/second-factor-already-in-use"; - readonly SECOND_FACTOR_LIMIT_EXCEEDED: "auth/maximum-second-factor-count-exceeded"; - readonly TENANT_ID_MISMATCH: "auth/tenant-id-mismatch"; - readonly TIMEOUT: "auth/timeout"; - readonly TOKEN_EXPIRED: "auth/user-token-expired"; - readonly TOO_MANY_ATTEMPTS_TRY_LATER: "auth/too-many-requests"; - readonly UNAUTHORIZED_DOMAIN: "auth/unauthorized-continue-uri"; - readonly UNSUPPORTED_FIRST_FACTOR: "auth/unsupported-first-factor"; - readonly UNSUPPORTED_PERSISTENCE: "auth/unsupported-persistence-type"; - readonly UNSUPPORTED_TENANT_OPERATION: "auth/unsupported-tenant-operation"; - readonly UNVERIFIED_EMAIL: "auth/unverified-email"; - readonly USER_CANCELLED: "auth/user-cancelled"; - readonly USER_DELETED: "auth/user-not-found"; - readonly USER_DISABLED: "auth/user-disabled"; - readonly USER_MISMATCH: "auth/user-mismatch"; - readonly USER_SIGNED_OUT: "auth/user-signed-out"; - readonly WEAK_PASSWORD: "auth/weak-password"; - readonly WEB_STORAGE_UNSUPPORTED: "auth/web-storage-unsupported"; - readonly ALREADY_INITIALIZED: "auth/already-initialized"; - readonly RECAPTCHA_NOT_ENABLED: "auth/recaptcha-not-enabled"; - readonly MISSING_RECAPTCHA_TOKEN: "auth/missing-recaptcha-token"; - readonly INVALID_RECAPTCHA_TOKEN: "auth/invalid-recaptcha-token"; - readonly INVALID_RECAPTCHA_ACTION: "auth/invalid-recaptcha-action"; - readonly MISSING_CLIENT_TYPE: "auth/missing-client-type"; - readonly MISSING_RECAPTCHA_VERSION: "auth/missing-recaptcha-version"; - readonly INVALID_RECAPTCHA_VERSION: "auth/invalid-recaptcha-version"; - readonly INVALID_REQ_TYPE: "auth/invalid-req-type"; - readonly INVALID_HOSTING_LINK_DOMAIN: "auth/invalid-hosting-link-domain"; -}; - -/** - * A mapping of error codes to error messages. - * - * @remarks - * - * While error messages are useful for debugging (providing verbose textual - * context around what went wrong), these strings take up a lot of space in the - * compiled code. When deploying code in production, using {@link prodErrorMap} - * will save you roughly 10k compressed/gzipped over {@link debugErrorMap}. You - * can select the error map during initialization: - * - * ```javascript - * initializeAuth(app, {errorMap: debugErrorMap}) - * ``` - * - * When initializing Auth, {@link prodErrorMap} is default. - * - * @public - */ -export declare interface AuthErrorMap { -} - -/* Excluded from this release type: AuthErrorParams */ - -/* Excluded from this release type: AuthEvent */ - -/* Excluded from this release type: AuthEventConsumer */ - -declare interface AuthEventError extends Error { - code: string; - message: string; -} - -/* Excluded from this release type: AuthEventType */ - -/* Excluded from this release type: AuthInternal */ - -declare class AuthPopup { - readonly window: Window | null; - associatedEvent: string | null; - constructor(window: Window | null); - close(): void; -} - -/** - * Interface that represents an auth provider, used to facilitate creating {@link AuthCredential}. - * - * @public - */ -export declare interface AuthProvider { - /** - * Provider for which credentials can be constructed. - */ - readonly providerId: string; -} - -/** - * Interface representing an {@link Auth} instance's settings. - * - * @remarks Currently used for enabling/disabling app verification for phone Auth testing. - * - * @public - */ -export declare interface AuthSettings { - /** - * When set, this property disables app verification for the purpose of testing phone - * authentication. For this property to take effect, it needs to be set before rendering a - * reCAPTCHA app verifier. When this is disabled, a mock reCAPTCHA is rendered instead. This is - * useful for manual testing during development or for automated integration tests. - * - * In order to use this feature, you will need to - * {@link https://firebase.google.com/docs/auth/web/phone-auth#test-with-whitelisted-phone-numbers | whitelist your phone number} - * via the Firebase Console. - * - * The default value is false (app verification is enabled). - */ - appVerificationDisabledForTesting: boolean; -} - -/** - * MFA Info as returned by the API. - */ -declare interface BaseMfaEnrollment { - mfaEnrollmentId: string; - enrolledAt: number; - displayName?: string; -} - -/** - * Common code to all OAuth providers. This is separate from the - * {@link OAuthProvider} so that child providers (like - * {@link GoogleAuthProvider}) don't inherit the `credential` instance method. - * Instead, they rely on a static `credential` method. - */ -declare abstract class BaseOAuthProvider extends FederatedAuthProvider implements AuthProvider { - /* Excluded from this release type: scopes */ - /** - * Add an OAuth scope to the credential. - * - * @param scope - Provider OAuth scope to add. - */ - addScope(scope: string): AuthProvider; - /** - * Retrieve the current list of OAuth scopes. - */ - getScopes(): string[]; -} - -/** - * Adds a blocking callback that runs before an auth state change - * sets a new user. - * - * @param auth - The {@link Auth} instance. - * @param callback - callback triggered before new user value is set. - * If this throws, it blocks the user from being set. - * @param onAbort - callback triggered if a later `beforeAuthStateChanged()` - * callback throws, allowing you to undo any side effects. - */ -export declare function beforeAuthStateChanged(auth: Auth, callback: (user: User | null) => void | Promise, onAbort?: () => void): Unsubscribe; - -/** - * An implementation of {@link Persistence} of type `COOKIE`, for use on the client side in - * applications leveraging hybrid rendering and middleware. - * - * @remarks This persistence method requires companion middleware to function, such as that provided - * by {@link https://firebaseopensource.com/projects/firebaseextended/reactfire/ | ReactFire} for - * NextJS. - * @beta - */ -export declare const browserCookiePersistence: Persistence; - -/** - * An implementation of {@link Persistence} of type `LOCAL` using `localStorage` - * for the underlying storage. - * - * @public - */ -export declare const browserLocalPersistence: Persistence; - -/** - * An implementation of {@link PopupRedirectResolver} suitable for browser - * based applications. - * - * @remarks - * This method does not work in a Node.js environment. - * - * @public - */ -export declare const browserPopupRedirectResolver: PopupRedirectResolver; - -/** - * An implementation of {@link Persistence} of `SESSION` using `sessionStorage` - * for the underlying storage. - * - * @public - */ -export declare const browserSessionPersistence: Persistence; - -/** - * Checks a verification code sent to the user by email or other out-of-band mechanism. - * - * @returns metadata about the code. - * - * @param auth - The {@link Auth} instance. - * @param oobCode - A verification code sent to the user. - * - * @public - */ -export declare function checkActionCode(auth: Auth, oobCode: string): Promise; - -/* Excluded from this release type: ClientPlatform */ -export { CompleteFn } - -/** - * Interface representing the `Auth` config. - * - * @public - */ -export declare interface Config { - /** - * The API Key used to communicate with the Firebase Auth backend. - */ - apiKey: string; - /** - * The host at which the Firebase Auth backend is running. - */ - apiHost: string; - /** - * The scheme used to communicate with the Firebase Auth backend. - */ - apiScheme: string; - /** - * The host at which the Secure Token API is running. - */ - tokenApiHost: string; - /** - * The SDK Client Version. - */ - sdkClientVersion: string; - /** - * The domain at which the web widgets are hosted (provided via Firebase Config). - */ - authDomain?: string; -} - -/* Excluded from this release type: ConfigInternal */ - -/** - * A result from a phone number sign-in, link, or reauthenticate call. - * - * @public - */ -export declare interface ConfirmationResult { - /** - * The phone number authentication operation's verification ID. - * - * @remarks - * This can be used along with the verification code to initialize a - * {@link PhoneAuthCredential}. - */ - readonly verificationId: string; - /** - * Finishes a phone number sign-in, link, or reauthentication. - * - * @example - * ```javascript - * const confirmationResult = await signInWithPhoneNumber(auth, phoneNumber, applicationVerifier); - * // Obtain verificationCode from the user. - * const userCredential = await confirmationResult.confirm(verificationCode); - * ``` - * - * @param verificationCode - The code that was sent to the user's mobile device. - */ - confirm(verificationCode: string): Promise; -} - -/** - * Completes the password reset process, given a confirmation code and new password. - * - * @param auth - The {@link Auth} instance. - * @param oobCode - A confirmation code sent to the user. - * @param newPassword - The new password. - * - * @public - */ -export declare function confirmPasswordReset(auth: Auth, oobCode: string, newPassword: string): Promise; - -/** - * Changes the {@link Auth} instance to communicate with the Firebase Auth Emulator, instead of production - * Firebase Auth services. - * - * @remarks - * This must be called synchronously immediately following the first call to - * {@link initializeAuth}. Do not use with production credentials as emulator - * traffic is not encrypted. - * - * - * @example - * ```javascript - * connectAuthEmulator(auth, 'http://127.0.0.1:9099', { disableWarnings: true }); - * ``` - * - * @param auth - The {@link Auth} instance. - * @param url - The URL at which the emulator is running (eg, 'http://localhost:9099'). - * @param options - Optional. `options.disableWarnings` defaults to `false`. Set it to - * `true` to disable the warning banner attached to the DOM. - * - * @public - */ -export declare function connectAuthEmulator(auth: Auth, url: string, options?: { - disableWarnings: boolean; -}): void; - -/** - * Creates a new user account associated with the specified email address and password. - * - * @remarks - * On successful creation of the user account, this user will also be signed in to your application. - * - * User account creation can fail if the account already exists or the password is invalid. - * - * This method is not supported on {@link Auth} instances created with a - * {@link @firebase/app#FirebaseServerApp}. - * - * Note: The email address acts as a unique identifier for the user and enables an email-based - * password reset. This function will create a new user account and set the initial user password. - * - * @param auth - The {@link Auth} instance. - * @param email - The user's email address. - * @param password - The user's chosen password. - * - * @public - */ -export declare function createUserWithEmailAndPassword(auth: Auth, email: string, password: string): Promise; - -/** - * Map of OAuth Custom Parameters. - * - * @public - */ -export declare type CustomParameters = Record; - -/** - * A verbose error map with detailed descriptions for most error codes. - * - * See discussion at {@link AuthErrorMap} - * - * @public - */ -export declare const debugErrorMap: AuthErrorMap; - -/** - * Deletes and signs out the user. - * - * @remarks - * Important: this is a security-sensitive operation that requires the user to have recently - * signed in. If this requirement isn't met, ask the user to authenticate again and then call - * {@link reauthenticateWithCredential}. - * - * @param user - The user. - * - * @public - */ -export declare function deleteUser(user: User): Promise; - -/** - * The dependencies that can be used to initialize an {@link Auth} instance. - * - * @remarks - * - * The modular SDK enables tree shaking by allowing explicit declarations of - * dependencies. For example, a web app does not need to include code that - * enables Cordova redirect sign in. That functionality is therefore split into - * {@link browserPopupRedirectResolver} and - * {@link cordovaPopupRedirectResolver}. The dependencies object is how Auth is - * configured to reduce bundle sizes. - * - * There are two ways to initialize an {@link Auth} instance: {@link getAuth} and - * {@link initializeAuth}. `getAuth` initializes everything using - * platform-specific configurations, while `initializeAuth` takes a - * `Dependencies` object directly, giving you more control over what is used. - * - * @public - */ -export declare interface Dependencies { - /** - * Which {@link Persistence} to use. If this is an array, the first - * `Persistence` that the device supports is used. The SDK searches for an - * existing account in order and, if one is found in a secondary - * `Persistence`, the account is moved to the primary `Persistence`. - * - * If no persistence is provided, the SDK falls back on - * {@link inMemoryPersistence}. - */ - persistence?: Persistence | Persistence[]; - /** - * The {@link PopupRedirectResolver} to use. This value depends on the - * platform. Options are {@link browserPopupRedirectResolver} and - * {@link cordovaPopupRedirectResolver}. This field is optional if neither - * {@link signInWithPopup} or {@link signInWithRedirect} are being used. - */ - popupRedirectResolver?: PopupRedirectResolver; - /** - * Which {@link AuthErrorMap} to use. - */ - errorMap?: AuthErrorMap; -} - -/** - * Interface that represents the credentials returned by {@link EmailAuthProvider} for - * {@link ProviderId}.PASSWORD - * - * @remarks - * Covers both {@link SignInMethod}.EMAIL_PASSWORD and - * {@link SignInMethod}.EMAIL_LINK. - * - * @public - */ -export declare class EmailAuthCredential extends AuthCredential { - /* Excluded from this release type: _email */ - /* Excluded from this release type: _password */ - /* Excluded from this release type: _tenantId */ - /* Excluded from this release type: __constructor */ - /* Excluded from this release type: _fromEmailAndPassword */ - /* Excluded from this release type: _fromEmailAndCode */ - /** {@inheritdoc AuthCredential.toJSON} */ - toJSON(): object; - /** - * Static method to deserialize a JSON representation of an object into an {@link AuthCredential}. - * - * @param json - Either `object` or the stringified representation of the object. When string is - * provided, `JSON.parse` would be called first. - * - * @returns If the JSON input does not represent an {@link AuthCredential}, null is returned. - */ - static fromJSON(json: object | string): EmailAuthCredential | null; - /* Excluded from this release type: _getIdTokenResponse */ - /* Excluded from this release type: _linkToIdToken */ - /* Excluded from this release type: _getReauthenticationResolver */ -} - -/** - * Provider for generating {@link EmailAuthCredential}. - * - * @public - */ -export declare class EmailAuthProvider implements AuthProvider { - /** - * Always set to {@link ProviderId}.PASSWORD, even for email link. - */ - static readonly PROVIDER_ID: 'password'; - /** - * Always set to {@link SignInMethod}.EMAIL_PASSWORD. - */ - static readonly EMAIL_PASSWORD_SIGN_IN_METHOD: 'password'; - /** - * Always set to {@link SignInMethod}.EMAIL_LINK. - */ - static readonly EMAIL_LINK_SIGN_IN_METHOD: 'emailLink'; - /** - * Always set to {@link ProviderId}.PASSWORD, even for email link. - */ - readonly providerId: "password"; - /** - * Initialize an {@link AuthCredential} using an email and password. - * - * @example - * ```javascript - * const authCredential = EmailAuthProvider.credential(email, password); - * const userCredential = await signInWithCredential(auth, authCredential); - * ``` - * - * @example - * ```javascript - * const userCredential = await signInWithEmailAndPassword(auth, email, password); - * ``` - * - * @param email - Email address. - * @param password - User account password. - * @returns The auth provider credential. - */ - static credential(email: string, password: string): EmailAuthCredential; - /** - * Initialize an {@link AuthCredential} using an email and an email link after a sign in with - * email link operation. - * - * @example - * ```javascript - * const authCredential = EmailAuthProvider.credentialWithLink(auth, email, emailLink); - * const userCredential = await signInWithCredential(auth, authCredential); - * ``` - * - * @example - * ```javascript - * await sendSignInLinkToEmail(auth, email); - * // Obtain emailLink from user. - * const userCredential = await signInWithEmailLink(auth, email, emailLink); - * ``` - * - * @param auth - The {@link Auth} instance used to verify the link. - * @param email - Email address. - * @param emailLink - Sign-in email link. - * @returns - The auth provider credential. - */ - static credentialWithLink(email: string, emailLink: string): EmailAuthCredential; -} - -/** - * Configuration of Firebase Authentication Emulator. - * @public - */ -export declare interface EmulatorConfig { - /** - * The protocol used to communicate with the emulator ("http"/"https"). - */ - readonly protocol: string; - /** - * The hostname of the emulator, which may be a domain ("localhost"), IPv4 address ("127.0.0.1") - * or quoted IPv6 address ("[::1]"). - */ - readonly host: string; - /** - * The port of the emulator, or null if port isn't specified (i.e. protocol default). - */ - readonly port: number | null; - /** - * The emulator-specific options. - */ - readonly options: { - /** - * Whether the warning banner attached to the DOM was disabled. - */ - readonly disableWarnings: boolean; - }; -} - -declare const enum EnforcementState { - ENFORCE = "ENFORCE", - AUDIT = "AUDIT", - OFF = "OFF", - ENFORCEMENT_STATE_UNSPECIFIED = "ENFORCEMENT_STATE_UNSPECIFIED" -} -export { ErrorFn } - -/* Excluded from this release type: EventManager */ - -/** - * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.FACEBOOK. - * - * @example - * ```javascript - * // Sign in using a redirect. - * const provider = new FacebookAuthProvider(); - * // Start a sign in process for an unauthenticated user. - * provider.addScope('user_birthday'); - * await signInWithRedirect(auth, provider); - * // This will trigger a full page redirect away from your app - * - * // After returning from the redirect when your app initializes you can obtain the result - * const result = await getRedirectResult(auth); - * if (result) { - * // This is the signed-in user - * const user = result.user; - * // This gives you a Facebook Access Token. - * const credential = FacebookAuthProvider.credentialFromResult(result); - * const token = credential.accessToken; - * } - * ``` - * - * @example - * ```javascript - * // Sign in using a popup. - * const provider = new FacebookAuthProvider(); - * provider.addScope('user_birthday'); - * const result = await signInWithPopup(auth, provider); - * - * // The signed-in user info. - * const user = result.user; - * // This gives you a Facebook Access Token. - * const credential = FacebookAuthProvider.credentialFromResult(result); - * const token = credential.accessToken; - * ``` - * - * @public - */ -export declare class FacebookAuthProvider extends BaseOAuthProvider { - /** Always set to {@link SignInMethod}.FACEBOOK. */ - static readonly FACEBOOK_SIGN_IN_METHOD: 'facebook.com'; - /** Always set to {@link ProviderId}.FACEBOOK. */ - static readonly PROVIDER_ID: 'facebook.com'; - constructor(); - /** - * Creates a credential for Facebook. - * - * @example - * ```javascript - * // `event` from the Facebook auth.authResponseChange callback. - * const credential = FacebookAuthProvider.credential(event.authResponse.accessToken); - * const result = await signInWithCredential(credential); - * ``` - * - * @param accessToken - Facebook access token. - */ - static credential(accessToken: string): OAuthCredential; - /** - * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}. - * - * @param userCredential - The user credential. - */ - static credentialFromResult(userCredential: UserCredential): OAuthCredential | null; - /** - * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was - * thrown during a sign-in, link, or reauthenticate operation. - * - * @param userCredential - The user credential. - */ - static credentialFromError(error: FirebaseError): OAuthCredential | null; - private static credentialFromTaggedObject; -} - -/** - * An enum of factors that may be used for multifactor authentication. - * - * @public - */ -export declare const FactorId: { - /** Phone as second factor */ - readonly PHONE: "phone"; - readonly TOTP: "totp"; -}; - -/** - * The base class for all Federated providers (OAuth (including OIDC), SAML). - * - * This class is not meant to be instantiated directly. - * - * @public - */ -declare abstract class FederatedAuthProvider implements AuthProvider { - readonly providerId: string; - /* Excluded from this release type: defaultLanguageCode */ - /* Excluded from this release type: customParameters */ - /** - * Constructor for generic OAuth providers. - * - * @param providerId - Provider for which credentials should be generated. - */ - constructor(providerId: string); - /** - * Set the language gode. - * - * @param languageCode - language code - */ - setDefaultLanguage(languageCode: string | null): void; - /** - * Sets the OAuth custom parameters to pass in an OAuth request for popup and redirect sign-in - * operations. - * - * @remarks - * For a detailed list, check the reserved required OAuth 2.0 parameters such as `client_id`, - * `redirect_uri`, `scope`, `response_type`, and `state` are not allowed and will be ignored. - * - * @param customOAuthParameters - The custom OAuth parameters to pass in the OAuth request. - */ - setCustomParameters(customOAuthParameters: CustomParameters): AuthProvider; - /** - * Retrieve the current list of {@link CustomParameters}. - */ - getCustomParameters(): CustomParameters; -} - -/** - * Gets the list of possible sign in methods for the given email address. This method returns an - * empty list when - * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection} - * is enabled, irrespective of the number of authentication methods available for the given email. - * - * @remarks - * This is useful to differentiate methods of sign-in for the same provider, eg. - * {@link EmailAuthProvider} which has 2 methods of sign-in, - * {@link SignInMethod}.EMAIL_PASSWORD and - * {@link SignInMethod}.EMAIL_LINK. - * - * @param auth - The {@link Auth} instance. - * @param email - The user's email address. - * - * Deprecated. Migrating off of this method is recommended as a security best-practice. - * Learn more in the Identity Platform documentation for - * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection}. - * @public - */ -export declare function fetchSignInMethodsForEmail(auth: Auth, email: string): Promise; - -declare interface FinalizeMfaResponse { - idToken: string; - refreshToken: string; -} - -/* Excluded from this release type: GenericAuthErrorParams */ - -/** - * Extracts provider specific {@link AdditionalUserInfo} for the given credential. - * - * @param userCredential - The user credential. - * - * @public - */ -export declare function getAdditionalUserInfo(userCredential: UserCredential): AdditionalUserInfo | null; - -/** - * Returns the Auth instance associated with the provided {@link @firebase/app#FirebaseApp}. - * If no instance exists, initializes an Auth instance with platform-specific default dependencies. - * - * @param app - The Firebase App. - * - * @public - */ -export declare function getAuth(app?: FirebaseApp): Auth; - -/** - * Returns a JSON Web Token (JWT) used to identify the user to a Firebase service. - * - * @remarks - * Returns the current token if it has not expired or if it will not expire in the next five - * minutes. Otherwise, this will refresh the token and return a new one. - * - * @param user - The user. - * @param forceRefresh - Force refresh regardless of token expiration. - * - * @public - */ -export declare function getIdToken(user: User, forceRefresh?: boolean): Promise; - -/** - * Returns a deserialized JSON Web Token (JWT) used to identify the user to a Firebase service. - * - * @remarks - * Returns the current token if it has not expired or if it will not expire in the next five - * minutes. Otherwise, this will refresh the token and return a new one. - * - * @param user - The user. - * @param forceRefresh - Force refresh regardless of token expiration. - * - * @public - */ -export declare function getIdTokenResult(user: User, forceRefresh?: boolean): Promise; - -/** - * Provides a {@link MultiFactorResolver} suitable for completion of a - * multi-factor flow. - * - * @param auth - The {@link Auth} instance. - * @param error - The {@link MultiFactorError} raised during a sign-in, or - * reauthentication operation. - * - * @public - */ -export declare function getMultiFactorResolver(auth: Auth, error: MultiFactorError): MultiFactorResolver; - -declare interface GetRecaptchaConfigResponse { - recaptchaKey: string; - recaptchaEnforcementState: RecaptchaEnforcementProviderState[]; -} - -/** - * Returns a {@link UserCredential} from the redirect-based sign-in flow. - * - * @remarks - * If sign-in succeeded, returns the signed in user. If sign-in was unsuccessful, fails with an - * error. If no redirect operation was called, returns `null`. - * - * This method does not work in a Node.js environment or with {@link Auth} instances created with a - * {@link @firebase/app#FirebaseServerApp}. - * - * @example - * ```javascript - * // Sign in using a redirect. - * const provider = new FacebookAuthProvider(); - * // You can add additional scopes to the provider: - * provider.addScope('user_birthday'); - * // Start a sign in process for an unauthenticated user. - * await signInWithRedirect(auth, provider); - * // This will trigger a full page redirect away from your app - * - * // After returning from the redirect when your app initializes you can obtain the result - * const result = await getRedirectResult(auth); - * if (result) { - * // This is the signed-in user - * const user = result.user; - * // This gives you a Facebook Access Token. - * const credential = provider.credentialFromResult(auth, result); - * const token = credential.accessToken; - * } - * // As this API can be used for sign-in, linking and reauthentication, - * // check the operationType to determine what triggered this redirect - * // operation. - * const operationType = result.operationType; - * ``` - * - * @param auth - The {@link Auth} instance. - * @param resolver - An instance of {@link PopupRedirectResolver}, optional - * if already supplied to {@link initializeAuth} or provided by {@link getAuth}. - * - * @public - */ -export declare function getRedirectResult(auth: Auth, resolver?: PopupRedirectResolver): Promise; - -/** - * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.GITHUB. - * - * @remarks - * GitHub requires an OAuth 2.0 redirect, so you can either handle the redirect directly, or use - * the {@link signInWithPopup} handler: - * - * @example - * ```javascript - * // Sign in using a redirect. - * const provider = new GithubAuthProvider(); - * // Start a sign in process for an unauthenticated user. - * provider.addScope('repo'); - * await signInWithRedirect(auth, provider); - * // This will trigger a full page redirect away from your app - * - * // After returning from the redirect when your app initializes you can obtain the result - * const result = await getRedirectResult(auth); - * if (result) { - * // This is the signed-in user - * const user = result.user; - * // This gives you a GitHub Access Token. - * const credential = GithubAuthProvider.credentialFromResult(result); - * const token = credential.accessToken; - * } - * ``` - * - * @example - * ```javascript - * // Sign in using a popup. - * const provider = new GithubAuthProvider(); - * provider.addScope('repo'); - * const result = await signInWithPopup(auth, provider); - * - * // The signed-in user info. - * const user = result.user; - * // This gives you a GitHub Access Token. - * const credential = GithubAuthProvider.credentialFromResult(result); - * const token = credential.accessToken; - * ``` - * @public - */ -export declare class GithubAuthProvider extends BaseOAuthProvider { - /** Always set to {@link SignInMethod}.GITHUB. */ - static readonly GITHUB_SIGN_IN_METHOD: 'github.com'; - /** Always set to {@link ProviderId}.GITHUB. */ - static readonly PROVIDER_ID: 'github.com'; - constructor(); - /** - * Creates a credential for GitHub. - * - * @param accessToken - GitHub access token. - */ - static credential(accessToken: string): OAuthCredential; - /** - * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}. - * - * @param userCredential - The user credential. - */ - static credentialFromResult(userCredential: UserCredential): OAuthCredential | null; - /** - * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was - * thrown during a sign-in, link, or reauthenticate operation. - * - * @param userCredential - The user credential. - */ - static credentialFromError(error: FirebaseError): OAuthCredential | null; - private static credentialFromTaggedObject; -} - -/** - * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.GOOGLE. - * - * @example - * ```javascript - * // Sign in using a redirect. - * const provider = new GoogleAuthProvider(); - * // Start a sign in process for an unauthenticated user. - * provider.addScope('profile'); - * provider.addScope('email'); - * await signInWithRedirect(auth, provider); - * // This will trigger a full page redirect away from your app - * - * // After returning from the redirect when your app initializes you can obtain the result - * const result = await getRedirectResult(auth); - * if (result) { - * // This is the signed-in user - * const user = result.user; - * // This gives you a Google Access Token. - * const credential = GoogleAuthProvider.credentialFromResult(result); - * const token = credential.accessToken; - * } - * ``` - * - * @example - * ```javascript - * // Sign in using a popup. - * const provider = new GoogleAuthProvider(); - * provider.addScope('profile'); - * provider.addScope('email'); - * const result = await signInWithPopup(auth, provider); - * - * // The signed-in user info. - * const user = result.user; - * // This gives you a Google Access Token. - * const credential = GoogleAuthProvider.credentialFromResult(result); - * const token = credential.accessToken; - * ``` - * - * @public - */ -export declare class GoogleAuthProvider extends BaseOAuthProvider { - /** Always set to {@link SignInMethod}.GOOGLE. */ - static readonly GOOGLE_SIGN_IN_METHOD: 'google.com'; - /** Always set to {@link ProviderId}.GOOGLE. */ - static readonly PROVIDER_ID: 'google.com'; - constructor(); - /** - * Creates a credential for Google. At least one of ID token and access token is required. - * - * @example - * ```javascript - * // \`googleUser\` from the onsuccess Google Sign In callback. - * const credential = GoogleAuthProvider.credential(googleUser.getAuthResponse().id_token); - * const result = await signInWithCredential(credential); - * ``` - * - * @param idToken - Google ID token. - * @param accessToken - Google access token. - */ - static credential(idToken?: string | null, accessToken?: string | null): OAuthCredential; - /** - * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}. - * - * @param userCredential - The user credential. - */ - static credentialFromResult(userCredential: UserCredential): OAuthCredential | null; - /** - * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was - * thrown during a sign-in, link, or reauthenticate operation. - * - * @param userCredential - The user credential. - */ - static credentialFromError(error: FirebaseError): OAuthCredential | null; - private static credentialFromTaggedObject; -} - -/** - * Raw encoded JWT - * - */ -declare type IdToken = string; - -/* Excluded from this release type: IdTokenMfaResponse */ - -/* Excluded from this release type: IdTokenResponse */ - -/* Excluded from this release type: IdTokenResponseKind */ - -/** - * Interface representing ID token result obtained from {@link User.getIdTokenResult}. - * - * @remarks - * `IdTokenResult` contains the ID token JWT string and other helper properties for getting different data - * associated with the token as well as all the decoded payload claims. - * - * Note that these claims are not to be trusted as they are parsed client side. Only server side - * verification can guarantee the integrity of the token claims. - * - * @public - */ -export declare interface IdTokenResult { - /** - * The authentication time formatted as a UTC string. - * - * @remarks - * This is the time the user authenticated (signed in) and not the time the token was refreshed. - */ - authTime: string; - /** The ID token expiration time formatted as a UTC string. */ - expirationTime: string; - /** The ID token issuance time formatted as a UTC string. */ - issuedAtTime: string; - /** - * The sign-in provider through which the ID token was obtained (anonymous, custom, phone, - * password, etc). - * - * @remarks - * Note, this does not map to provider IDs. - */ - signInProvider: string | null; - /** - * The type of second factor associated with this session, provided the user was multi-factor - * authenticated (eg. phone, etc). - */ - signInSecondFactor: string | null; - /** The Firebase Auth ID token JWT string. */ - token: string; - /** - * The entire payload claims of the ID token including the standard reserved claims as well as - * the custom claims. - */ - claims: ParsedToken; -} - -/** - * An implementation of {@link Persistence} of type `LOCAL` using `indexedDB` - * for the underlying storage. - * - * @public - */ -export declare const indexedDBLocalPersistence: Persistence; - -/** - * Initializes an {@link Auth} instance with fine-grained control over - * {@link Dependencies}. - * - * @remarks - * - * This function allows more control over the {@link Auth} instance than - * {@link getAuth}. `getAuth` uses platform-specific defaults to supply - * the {@link Dependencies}. In general, `getAuth` is the easiest way to - * initialize Auth and works for most use cases. Use `initializeAuth` if you - * need control over which persistence layer is used, or to minimize bundle - * size if you're not using either `signInWithPopup` or `signInWithRedirect`. - * - * For example, if your app only uses anonymous accounts and you only want - * accounts saved for the current session, initialize `Auth` with: - * - * ```js - * const auth = initializeAuth(app, { - * persistence: browserSessionPersistence, - * popupRedirectResolver: undefined, - * }); - * ``` - * - * @public - */ -export declare function initializeAuth(app: FirebaseApp, deps?: Dependencies): Auth; - -/** - * Loads the reCAPTCHA configuration into the `Auth` instance. - * - * @remarks - * This will load the reCAPTCHA config, which indicates whether the reCAPTCHA - * verification flow should be triggered for each auth provider, into the - * current Auth session. - * - * If initializeRecaptchaConfig() is not invoked, the auth flow will always start - * without reCAPTCHA verification. If the provider is configured to require reCAPTCHA - * verification, the SDK will transparently load the reCAPTCHA config and restart the - * auth flows. - * - * Thus, by calling this optional method, you will reduce the latency of future auth flows. - * Loading the reCAPTCHA config early will also enhance the signal collected by reCAPTCHA. - * - * This method does not work in a Node.js environment. - * - * @example - * ```javascript - * initializeRecaptchaConfig(auth); - * ``` - * - * @param auth - The {@link Auth} instance. - * - * @public - */ -export declare function initializeRecaptchaConfig(auth: Auth): Promise; - -/** - * An implementation of {@link Persistence} of type 'NONE'. - * - * @public - */ -export declare const inMemoryPersistence: Persistence; - -/** - * Checks if an incoming link is a sign-in with email link suitable for {@link signInWithEmailLink}. - * - * @param auth - The {@link Auth} instance. - * @param emailLink - The link sent to the user's email address. - * - * @public - */ -export declare function isSignInWithEmailLink(auth: Auth, emailLink: string): boolean; - -/** - * Links the user account with the given credentials. - * - * @remarks - * An {@link AuthProvider} can be used to generate the credential. - * - * @param user - The user. - * @param credential - The auth credential. - * - * @public - */ -export declare function linkWithCredential(user: User, credential: AuthCredential): Promise; - -/** - * Links the user account with the given phone number. - * - * @remarks - * This method does not work in a Node.js environment. - * - * @param user - The user. - * @param phoneNumber - The user's phone number in E.164 format (e.g. +16505550101). - * @param appVerifier - The {@link ApplicationVerifier}. - * - * @public - */ -export declare function linkWithPhoneNumber(user: User, phoneNumber: string, appVerifier?: ApplicationVerifier): Promise; - -/** - * Links the authenticated provider to the user account using a pop-up based OAuth flow. - * - * @remarks - * If the linking is successful, the returned result will contain the user and the provider's credential. - * - * This method does not work in a Node.js environment. - * - * @example - * ```javascript - * // Sign in using some other provider. - * const result = await signInWithEmailAndPassword(auth, email, password); - * // Link using a popup. - * const provider = new FacebookAuthProvider(); - * await linkWithPopup(result.user, provider); - * ``` - * - * @param user - The user. - * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}. - * Non-OAuth providers like {@link EmailAuthProvider} will throw an error. - * @param resolver - An instance of {@link PopupRedirectResolver}, optional - * if already supplied to {@link initializeAuth} or provided by {@link getAuth}. - * - * @public - */ -export declare function linkWithPopup(user: User, provider: AuthProvider, resolver?: PopupRedirectResolver): Promise; - -/** - * Links the {@link OAuthProvider} to the user account using a full-page redirect flow. - * @remarks - * To handle the results and errors for this operation, refer to {@link getRedirectResult}. - * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices - * | best practices} when using {@link linkWithRedirect}. - * - * This method does not work in a Node.js environment or with {@link Auth} instances - * created with a {@link @firebase/app#FirebaseServerApp}. - * - * @example - * ```javascript - * // Sign in using some other provider. - * const result = await signInWithEmailAndPassword(auth, email, password); - * // Link using a redirect. - * const provider = new FacebookAuthProvider(); - * await linkWithRedirect(result.user, provider); - * // This will trigger a full page redirect away from your app - * - * // After returning from the redirect when your app initializes you can obtain the result - * const result = await getRedirectResult(auth); - * ``` - * - * @param user - The user. - * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}. - * Non-OAuth providers like {@link EmailAuthProvider} will throw an error. - * @param resolver - An instance of {@link PopupRedirectResolver}, optional - * if already supplied to {@link initializeAuth} or provided by {@link getAuth}. - * - * @public - */ -export declare function linkWithRedirect(user: User, provider: AuthProvider, resolver?: PopupRedirectResolver): Promise; - -/** - * MfaEnrollment can be any subtype of BaseMfaEnrollment, currently only PhoneMfaEnrollment and TotpMfaEnrollment are supported. - */ -declare type MfaEnrollment = PhoneMfaEnrollment | TotpMfaEnrollment; - -/** - * The {@link MultiFactorUser} corresponding to the user. - * - * @remarks - * This is used to access all multi-factor properties and operations related to the user. - * - * @param user - The user. - * - * @public - */ -export declare function multiFactor(user: User): MultiFactorUser; - -/** - * The base class for asserting ownership of a second factor. - * - * @remarks - * This is used to facilitate enrollment of a second factor on an existing user or sign-in of a - * user who already verified the first factor. - * - * @public - */ -export declare interface MultiFactorAssertion { - /** The identifier of the second factor. */ - readonly factorId: (typeof FactorId)[keyof typeof FactorId]; -} - -/** - * The error thrown when the user needs to provide a second factor to sign in successfully. - * - * @remarks - * The error code for this error is `auth/multi-factor-auth-required`. - * - * @example - * ```javascript - * let resolver; - * let multiFactorHints; - * - * signInWithEmailAndPassword(auth, email, password) - * .then((result) => { - * // User signed in. No 2nd factor challenge is needed. - * }) - * .catch((error) => { - * if (error.code == 'auth/multi-factor-auth-required') { - * resolver = getMultiFactorResolver(auth, error); - * multiFactorHints = resolver.hints; - * } else { - * // Handle other errors. - * } - * }); - * - * // Obtain a multiFactorAssertion by verifying the second factor. - * - * const userCredential = await resolver.resolveSignIn(multiFactorAssertion); - * ``` - * - * @public - */ -export declare interface MultiFactorError extends AuthError { - /** Details about the MultiFactorError. */ - readonly customData: AuthError['customData'] & { - /** - * The type of operation (sign-in, linking, or re-authentication) that raised the error. - */ - readonly operationType: (typeof OperationType)[keyof typeof OperationType]; - }; -} - -/** - * A structure containing the information of a second factor entity. - * - * @public - */ -export declare interface MultiFactorInfo { - /** The multi-factor enrollment ID. */ - readonly uid: string; - /** The user friendly name of the current second factor. */ - readonly displayName?: string | null; - /** The enrollment date of the second factor formatted as a UTC string. */ - readonly enrollmentTime: string; - /** The identifier of the second factor. */ - readonly factorId: (typeof FactorId)[keyof typeof FactorId]; -} - -/** - * The class used to facilitate recovery from {@link MultiFactorError} when a user needs to - * provide a second factor to sign in. - * - * @example - * ```javascript - * let resolver; - * let multiFactorHints; - * - * signInWithEmailAndPassword(auth, email, password) - * .then((result) => { - * // User signed in. No 2nd factor challenge is needed. - * }) - * .catch((error) => { - * if (error.code == 'auth/multi-factor-auth-required') { - * resolver = getMultiFactorResolver(auth, error); - * // Show UI to let user select second factor. - * multiFactorHints = resolver.hints; - * } else { - * // Handle other errors. - * } - * }); - * - * // The enrolled second factors that can be used to complete - * // sign-in are returned in the `MultiFactorResolver.hints` list. - * // UI needs to be presented to allow the user to select a second factor - * // from that list. - * - * const selectedHint = // ; selected from multiFactorHints - * const phoneAuthProvider = new PhoneAuthProvider(auth); - * const phoneInfoOptions = { - * multiFactorHint: selectedHint, - * session: resolver.session - * }; - * const verificationId = phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, appVerifier); - * // Store `verificationId` and show UI to let user enter verification code. - * - * // UI to enter verification code and continue. - * // Continue button click handler - * const phoneAuthCredential = PhoneAuthProvider.credential(verificationId, verificationCode); - * const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(phoneAuthCredential); - * const userCredential = await resolver.resolveSignIn(multiFactorAssertion); - * ``` - * - * @public - */ -export declare interface MultiFactorResolver { - /** - * The list of hints for the second factors needed to complete the sign-in for the current - * session. - */ - readonly hints: MultiFactorInfo[]; - /** - * The session identifier for the current sign-in flow, which can be used to complete the second - * factor sign-in. - */ - readonly session: MultiFactorSession; - /** - * A helper function to help users complete sign in with a second factor using an - * {@link MultiFactorAssertion} confirming the user successfully completed the second factor - * challenge. - * - * @example - * ```javascript - * const phoneAuthCredential = PhoneAuthProvider.credential(verificationId, verificationCode); - * const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(phoneAuthCredential); - * const userCredential = await resolver.resolveSignIn(multiFactorAssertion); - * ``` - * - * @param assertion - The multi-factor assertion to resolve sign-in with. - * @returns The promise that resolves with the user credential object. - */ - resolveSignIn(assertion: MultiFactorAssertion): Promise; -} - -/** - * An interface defining the multi-factor session object used for enrolling a second factor on a - * user or helping sign in an enrolled user with a second factor. - * - * @public - */ -export declare interface MultiFactorSession { -} - -/** - * An interface that defines the multi-factor related properties and operations pertaining - * to a {@link User}. - * - * @public - */ -export declare interface MultiFactorUser { - /** Returns a list of the user's enrolled second factors. */ - readonly enrolledFactors: MultiFactorInfo[]; - /** - * Returns the session identifier for a second factor enrollment operation. This is used to - * identify the user trying to enroll a second factor. - * - * @example - * ```javascript - * const multiFactorUser = multiFactor(auth.currentUser); - * const multiFactorSession = await multiFactorUser.getSession(); - * - * // Send verification code. - * const phoneAuthProvider = new PhoneAuthProvider(auth); - * const phoneInfoOptions = { - * phoneNumber: phoneNumber, - * session: multiFactorSession - * }; - * const verificationId = await phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, appVerifier); - * - * // Obtain verification code from user. - * const phoneAuthCredential = PhoneAuthProvider.credential(verificationId, verificationCode); - * const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(phoneAuthCredential); - * await multiFactorUser.enroll(multiFactorAssertion); - * ``` - * - * @returns The promise that resolves with the {@link MultiFactorSession}. - */ - getSession(): Promise; - /** - * - * Enrolls a second factor as identified by the {@link MultiFactorAssertion} for the - * user. - * - * @remarks - * On resolution, the user tokens are updated to reflect the change in the JWT payload. - * Accepts an additional display name parameter used to identify the second factor to the end - * user. Recent re-authentication is required for this operation to succeed. On successful - * enrollment, existing Firebase sessions (refresh tokens) are revoked. When a new factor is - * enrolled, an email notification is sent to the user’s email. - * - * @example - * ```javascript - * const multiFactorUser = multiFactor(auth.currentUser); - * const multiFactorSession = await multiFactorUser.getSession(); - * - * // Send verification code. - * const phoneAuthProvider = new PhoneAuthProvider(auth); - * const phoneInfoOptions = { - * phoneNumber: phoneNumber, - * session: multiFactorSession - * }; - * const verificationId = await phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, appVerifier); - * - * // Obtain verification code from user. - * const phoneAuthCredential = PhoneAuthProvider.credential(verificationId, verificationCode); - * const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(phoneAuthCredential); - * await multiFactorUser.enroll(multiFactorAssertion); - * // Second factor enrolled. - * ``` - * - * @param assertion - The multi-factor assertion to enroll with. - * @param displayName - The display name of the second factor. - */ - enroll(assertion: MultiFactorAssertion, displayName?: string | null): Promise; - /** - * Unenrolls the specified second factor. - * - * @remarks - * To specify the factor to remove, pass a {@link MultiFactorInfo} object (retrieved from - * {@link MultiFactorUser.enrolledFactors}) or the - * factor's UID string. Sessions are not revoked when the account is unenrolled. An email - * notification is likely to be sent to the user notifying them of the change. Recent - * re-authentication is required for this operation to succeed. When an existing factor is - * unenrolled, an email notification is sent to the user’s email. - * - * @example - * ```javascript - * const multiFactorUser = multiFactor(auth.currentUser); - * // Present user the option to choose which factor to unenroll. - * await multiFactorUser.unenroll(multiFactorUser.enrolledFactors[i]) - * ``` - * - * @param option - The multi-factor option to unenroll. - * @returns - A `Promise` which resolves when the unenroll operation is complete. - */ - unenroll(option: MultiFactorInfo | string): Promise; -} - -declare type MutableUserInfo = { - -readonly [K in keyof UserInfo]: UserInfo[K]; -}; -export { NextFn } - -/** - * Type definition for an event callback. - * - * @privateRemarks TODO(avolkovi): should we consolidate with Subscribe since we're changing the API anyway? - * - * @public - */ -export declare type NextOrObserver = NextFn | Observer; - -/** - * Represents the OAuth credentials returned by an {@link OAuthProvider}. - * - * @remarks - * Implementations specify the details about each auth provider's credential requirements. - * - * @public - */ -export declare class OAuthCredential extends AuthCredential { - /** - * The OAuth ID token associated with the credential if it belongs to an OIDC provider, - * such as `google.com`. - * @readonly - */ - idToken?: string; - /** - * The OAuth access token associated with the credential if it belongs to an - * {@link OAuthProvider}, such as `facebook.com`, `twitter.com`, etc. - * @readonly - */ - accessToken?: string; - /** - * The OAuth access token secret associated with the credential if it belongs to an OAuth 1.0 - * provider, such as `twitter.com`. - * @readonly - */ - secret?: string; - private nonce?; - private pendingToken; - /* Excluded from this release type: _fromParams */ - /** {@inheritdoc AuthCredential.toJSON} */ - toJSON(): object; - /** - * Static method to deserialize a JSON representation of an object into an - * {@link AuthCredential}. - * - * @param json - Input can be either Object or the stringified representation of the object. - * When string is provided, JSON.parse would be called first. - * - * @returns If the JSON input does not represent an {@link AuthCredential}, null is returned. - */ - static fromJSON(json: string | object): OAuthCredential | null; - /* Excluded from this release type: _getIdTokenResponse */ - /* Excluded from this release type: _linkToIdToken */ - /* Excluded from this release type: _getReauthenticationResolver */ - private buildRequest; -} - -/** - * Defines the options for initializing an {@link OAuthCredential}. - * - * @remarks - * For ID tokens with nonce claim, the raw nonce has to also be provided. - * - * @public - */ -export declare interface OAuthCredentialOptions { - /** - * The OAuth ID token used to initialize the {@link OAuthCredential}. - */ - idToken?: string; - /** - * The OAuth access token used to initialize the {@link OAuthCredential}. - */ - accessToken?: string; - /** - * The raw nonce associated with the ID token. - * - * @remarks - * It is required when an ID token with a nonce field is provided. The SHA-256 hash of the - * raw nonce must match the nonce field in the ID token. - */ - rawNonce?: string; -} - -declare interface OAuthCredentialParams { - idToken?: string | null; - accessToken?: string | null; - oauthToken?: string; - secret?: string; - oauthTokenSecret?: string; - nonce?: string; - pendingToken?: string; - providerId: string; - signInMethod: string; -} - -/** - * Provider for generating generic {@link OAuthCredential}. - * - * @example - * ```javascript - * // Sign in using a redirect. - * const provider = new OAuthProvider('google.com'); - * // Start a sign in process for an unauthenticated user. - * provider.addScope('profile'); - * provider.addScope('email'); - * await signInWithRedirect(auth, provider); - * // This will trigger a full page redirect away from your app - * - * // After returning from the redirect when your app initializes you can obtain the result - * const result = await getRedirectResult(auth); - * if (result) { - * // This is the signed-in user - * const user = result.user; - * // This gives you a OAuth Access Token for the provider. - * const credential = provider.credentialFromResult(auth, result); - * const token = credential.accessToken; - * } - * ``` - * - * @example - * ```javascript - * // Sign in using a popup. - * const provider = new OAuthProvider('google.com'); - * provider.addScope('profile'); - * provider.addScope('email'); - * const result = await signInWithPopup(auth, provider); - * - * // The signed-in user info. - * const user = result.user; - * // This gives you a OAuth Access Token for the provider. - * const credential = provider.credentialFromResult(auth, result); - * const token = credential.accessToken; - * ``` - * @public - */ -export declare class OAuthProvider extends BaseOAuthProvider { - /** - * Creates an {@link OAuthCredential} from a JSON string or a plain object. - * @param json - A plain object or a JSON string - */ - static credentialFromJSON(json: object | string): OAuthCredential; - /** - * Creates a {@link OAuthCredential} from a generic OAuth provider's access token or ID token. - * - * @remarks - * The raw nonce is required when an ID token with a nonce field is provided. The SHA-256 hash of - * the raw nonce must match the nonce field in the ID token. - * - * @example - * ```javascript - * // `googleUser` from the onsuccess Google Sign In callback. - * // Initialize a generate OAuth provider with a `google.com` providerId. - * const provider = new OAuthProvider('google.com'); - * const credential = provider.credential({ - * idToken: googleUser.getAuthResponse().id_token, - * }); - * const result = await signInWithCredential(credential); - * ``` - * - * @param params - Either the options object containing the ID token, access token and raw nonce - * or the ID token string. - */ - credential(params: OAuthCredentialOptions): OAuthCredential; - /** An internal credential method that accepts more permissive options */ - private _credential; - /** - * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}. - * - * @param userCredential - The user credential. - */ - static credentialFromResult(userCredential: UserCredential): OAuthCredential | null; - /** - * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was - * thrown during a sign-in, link, or reauthenticate operation. - * - * @param userCredential - The user credential. - */ - static credentialFromError(error: FirebaseError): OAuthCredential | null; - private static oauthCredentialFromTaggedObject; -} - -/** - * Adds an observer for changes to the user's sign-in state. - * - * @remarks - * To keep the old behavior, see {@link onIdTokenChanged}. - * - * @param auth - The {@link Auth} instance. - * @param nextOrObserver - callback triggered on change. - * @param error - Deprecated. This callback is never triggered. Errors - * on signing in/out can be caught in promises returned from - * sign-in/sign-out functions. - * @param completed - Deprecated. This callback is never triggered. - * - * @public - */ -export declare function onAuthStateChanged(auth: Auth, nextOrObserver: NextOrObserver, error?: ErrorFn, completed?: CompleteFn): Unsubscribe; - -/** - * Adds an observer for changes to the signed-in user's ID token. - * - * @remarks - * This includes sign-in, sign-out, and token refresh events. - * This will not be triggered automatically upon ID token expiration. Use {@link User.getIdToken} to refresh the ID token. - * - * @param auth - The {@link Auth} instance. - * @param nextOrObserver - callback triggered on change. - * @param error - Deprecated. This callback is never triggered. Errors - * on signing in/out can be caught in promises returned from - * sign-in/sign-out functions. - * @param completed - Deprecated. This callback is never triggered. - * - * @public - */ -export declare function onIdTokenChanged(auth: Auth, nextOrObserver: NextOrObserver, error?: ErrorFn, completed?: CompleteFn): Unsubscribe; - -/** - * Enumeration of supported operation types. - * - * @public - */ -export declare const OperationType: { - /** Operation involving linking an additional provider to an already signed-in user. */ - readonly LINK: "link"; - /** Operation involving using a provider to reauthenticate an already signed-in user. */ - readonly REAUTHENTICATE: "reauthenticate"; - /** Operation involving signing in a user. */ - readonly SIGN_IN: "signIn"; -}; - -/** - * Parses the email action link string and returns an {@link ActionCodeURL} if - * the link is valid, otherwise returns null. - * - * @public - */ -export declare function parseActionCodeURL(link: string): ActionCodeURL | null; - -/** - * Interface representing a parsed ID token. - * - * @privateRemarks TODO(avolkovi): consolidate with parsed_token in implementation. - * - * @public - */ -export declare interface ParsedToken { - /** Expiration time of the token. */ - 'exp'?: string; - /** UID of the user. */ - 'sub'?: string; - /** Time at which authentication was performed. */ - 'auth_time'?: string; - /** Issuance time of the token. */ - 'iat'?: string; - /** Firebase specific claims, containing the provider(s) used to authenticate the user. */ - 'firebase'?: { - 'sign_in_provider'?: string; - 'sign_in_second_factor'?: string; - 'identities'?: Record; - }; - /** Map of any additional custom claims. */ - [key: string]: unknown; -} - -/** - * A structure specifying password policy requirements. - * - * @public - */ -export declare interface PasswordPolicy { - /** - * Requirements enforced by this password policy. - */ - readonly customStrengthOptions: { - /** - * Minimum password length, or undefined if not configured. - */ - readonly minPasswordLength?: number; - /** - * Maximum password length, or undefined if not configured. - */ - readonly maxPasswordLength?: number; - /** - * Whether the password should contain a lowercase letter, or undefined if not configured. - */ - readonly containsLowercaseLetter?: boolean; - /** - * Whether the password should contain an uppercase letter, or undefined if not configured. - */ - readonly containsUppercaseLetter?: boolean; - /** - * Whether the password should contain a numeric character, or undefined if not configured. - */ - readonly containsNumericCharacter?: boolean; - /** - * Whether the password should contain a non-alphanumeric character, or undefined if not configured. - */ - readonly containsNonAlphanumericCharacter?: boolean; - }; - /** - * List of characters that are considered non-alphanumeric during validation. - */ - readonly allowedNonAlphanumericCharacters: string; - /** - * The enforcement state of the policy. Can be 'OFF' or 'ENFORCE'. - */ - readonly enforcementState: string; - /** - * Whether existing passwords must meet the policy. - */ - readonly forceUpgradeOnSignin: boolean; -} - -/* Excluded from this release type: PasswordPolicyCustomStrengthOptions */ - -/* Excluded from this release type: PasswordPolicyInternal */ - -/** - * A structure indicating which password policy requirements were met or violated and what the - * requirements are. - * - * @public - */ -export declare interface PasswordValidationStatus { - /** - * Whether the password meets all requirements. - */ - readonly isValid: boolean; - /** - * Whether the password meets the minimum password length, or undefined if not required. - */ - readonly meetsMinPasswordLength?: boolean; - /** - * Whether the password meets the maximum password length, or undefined if not required. - */ - readonly meetsMaxPasswordLength?: boolean; - /** - * Whether the password contains a lowercase letter, or undefined if not required. - */ - readonly containsLowercaseLetter?: boolean; - /** - * Whether the password contains an uppercase letter, or undefined if not required. - */ - readonly containsUppercaseLetter?: boolean; - /** - * Whether the password contains a numeric character, or undefined if not required. - */ - readonly containsNumericCharacter?: boolean; - /** - * Whether the password contains a non-alphanumeric character, or undefined if not required. - */ - readonly containsNonAlphanumericCharacter?: boolean; - /** - * The policy used to validate the password. - */ - readonly passwordPolicy: PasswordPolicy; -} - -declare type PersistedBlob = Record; - -/** - * An interface covering the possible persistence mechanism types. - * - * @public - */ -export declare interface Persistence { - /** - * Type of Persistence. - * - 'SESSION' is used for temporary persistence such as `sessionStorage`. - * - 'LOCAL' is used for long term persistence such as `localStorage` or `IndexedDB`. - * - 'NONE' is used for in-memory, or no persistence. - * - 'COOKIE' is used for cookie persistence, useful for server-side rendering. - */ - readonly type: 'SESSION' | 'LOCAL' | 'NONE' | 'COOKIE'; -} - -declare interface PersistenceInternal extends Persistence { - type: PersistenceType; - _isAvailable(): Promise; - _set(key: string, value: PersistenceValue): Promise; - _get(key: string): Promise; - _remove(key: string): Promise; - _addListener(key: string, listener: StorageEventListener): void; - _removeListener(key: string, listener: StorageEventListener): void; - _shouldAllowMigration?: boolean; -} - -declare const enum PersistenceType { - SESSION = "SESSION", - LOCAL = "LOCAL", - NONE = "NONE", - COOKIE = "COOKIE" -} - -declare type PersistenceValue = PersistedBlob | string; - -/** - * Represents the credentials returned by {@link PhoneAuthProvider}. - * - * @public - */ -export declare class PhoneAuthCredential extends AuthCredential { - private readonly params; - private constructor(); - /* Excluded from this release type: _fromVerification */ - /* Excluded from this release type: _fromTokenResponse */ - /* Excluded from this release type: _getIdTokenResponse */ - /* Excluded from this release type: _linkToIdToken */ - /* Excluded from this release type: _getReauthenticationResolver */ - /* Excluded from this release type: _makeVerificationRequest */ - /** {@inheritdoc AuthCredential.toJSON} */ - toJSON(): object; - /** Generates a phone credential based on a plain object or a JSON string. */ - static fromJSON(json: object | string): PhoneAuthCredential | null; -} - -/** - * Provider for generating an {@link PhoneAuthCredential}. - * - * @remarks - * `PhoneAuthProvider` does not work in a Node.js environment. - * - * @example - * ```javascript - * // 'recaptcha-container' is the ID of an element in the DOM. - * const applicationVerifier = new RecaptchaVerifier('recaptcha-container'); - * const provider = new PhoneAuthProvider(auth); - * const verificationId = await provider.verifyPhoneNumber('+16505550101', applicationVerifier); - * // Obtain the verificationCode from the user. - * const phoneCredential = PhoneAuthProvider.credential(verificationId, verificationCode); - * const userCredential = await signInWithCredential(auth, phoneCredential); - * ``` - * - * @public - */ -export declare class PhoneAuthProvider { - /** Always set to {@link ProviderId}.PHONE. */ - static readonly PROVIDER_ID: 'phone'; - /** Always set to {@link SignInMethod}.PHONE. */ - static readonly PHONE_SIGN_IN_METHOD: 'phone'; - /** Always set to {@link ProviderId}.PHONE. */ - readonly providerId: "phone"; - private readonly auth; - /** - * @param auth - The Firebase {@link Auth} instance in which sign-ins should occur. - * - */ - constructor(auth: Auth); - /** - * - * Starts a phone number authentication flow by sending a verification code to the given phone - * number. - * - * @example - * ```javascript - * const provider = new PhoneAuthProvider(auth); - * const verificationId = await provider.verifyPhoneNumber(phoneNumber, applicationVerifier); - * // Obtain verificationCode from the user. - * const authCredential = PhoneAuthProvider.credential(verificationId, verificationCode); - * const userCredential = await signInWithCredential(auth, authCredential); - * ``` - * - * @example - * An alternative flow is provided using the `signInWithPhoneNumber` method. - * ```javascript - * const confirmationResult = signInWithPhoneNumber(auth, phoneNumber, applicationVerifier); - * // Obtain verificationCode from the user. - * const userCredential = confirmationResult.confirm(verificationCode); - * ``` - * - * @param phoneInfoOptions - The user's {@link PhoneInfoOptions}. The phone number should be in - * E.164 format (e.g. +16505550101). - * @param applicationVerifier - An {@link ApplicationVerifier}, which prevents - * requests from unauthorized clients. This SDK includes an implementation - * based on reCAPTCHA v2, {@link RecaptchaVerifier}. If you've enabled - * reCAPTCHA Enterprise bot protection in Enforce mode, this parameter is - * optional; in all other configurations, the parameter is required. - * - * @returns A Promise for a verification ID that can be passed to - * {@link PhoneAuthProvider.credential} to identify this flow. - */ - verifyPhoneNumber(phoneOptions: PhoneInfoOptions | string, applicationVerifier?: ApplicationVerifier): Promise; - /** - * Creates a phone auth credential, given the verification ID from - * {@link PhoneAuthProvider.verifyPhoneNumber} and the code that was sent to the user's - * mobile device. - * - * @example - * ```javascript - * const provider = new PhoneAuthProvider(auth); - * const verificationId = provider.verifyPhoneNumber(phoneNumber, applicationVerifier); - * // Obtain verificationCode from the user. - * const authCredential = PhoneAuthProvider.credential(verificationId, verificationCode); - * const userCredential = signInWithCredential(auth, authCredential); - * ``` - * - * @example - * An alternative flow is provided using the `signInWithPhoneNumber` method. - * ```javascript - * const confirmationResult = await signInWithPhoneNumber(auth, phoneNumber, applicationVerifier); - * // Obtain verificationCode from the user. - * const userCredential = await confirmationResult.confirm(verificationCode); - * ``` - * - * @param verificationId - The verification ID returned from {@link PhoneAuthProvider.verifyPhoneNumber}. - * @param verificationCode - The verification code sent to the user's mobile device. - * - * @returns The auth provider credential. - */ - static credential(verificationId: string, verificationCode: string): PhoneAuthCredential; - /** - * Generates an {@link AuthCredential} from a {@link UserCredential}. - * @param userCredential - The user credential. - */ - static credentialFromResult(userCredential: UserCredential): AuthCredential | null; - /** - * Returns an {@link AuthCredential} when passed an error. - * - * @remarks - * - * This method works for errors like - * `auth/account-exists-with-different-credentials`. This is useful for - * recovering when attempting to set a user's phone number but the number - * in question is already tied to another account. For example, the following - * code tries to update the current user's phone number, and if that - * fails, links the user with the account associated with that number: - * - * ```js - * const provider = new PhoneAuthProvider(auth); - * const verificationId = await provider.verifyPhoneNumber(number, verifier); - * try { - * const code = ''; // Prompt the user for the verification code - * await updatePhoneNumber( - * auth.currentUser, - * PhoneAuthProvider.credential(verificationId, code)); - * } catch (e) { - * if ((e as FirebaseError)?.code === 'auth/account-exists-with-different-credential') { - * const cred = PhoneAuthProvider.credentialFromError(e); - * await linkWithCredential(auth.currentUser, cred); - * } - * } - * - * // At this point, auth.currentUser.phoneNumber === number. - * ``` - * - * @param error - The error to generate a credential from. - */ - static credentialFromError(error: FirebaseError): AuthCredential | null; - private static credentialFromTaggedObject; -} - -/** - * The information required to verify the ownership of a phone number. - * - * @remarks - * The information that's required depends on whether you are doing single-factor sign-in, - * multi-factor enrollment or multi-factor sign-in. - * - * @public - */ -export declare type PhoneInfoOptions = PhoneSingleFactorInfoOptions | PhoneMultiFactorEnrollInfoOptions | PhoneMultiFactorSignInInfoOptions; - -/** - * An MFA provided by SMS verification. - */ -declare interface PhoneMfaEnrollment extends BaseMfaEnrollment { - phoneInfo: string; -} - -/** - * The class for asserting ownership of a phone second factor. Provided by - * {@link PhoneMultiFactorGenerator.assertion}. - * - * @public - */ -export declare interface PhoneMultiFactorAssertion extends MultiFactorAssertion { -} - -/** - * Options used for enrolling a second factor. - * - * @public - */ -export declare interface PhoneMultiFactorEnrollInfoOptions { - /** Phone number to send a verification code to. */ - phoneNumber: string; - /** The {@link MultiFactorSession} obtained via {@link MultiFactorUser.getSession}. */ - session: MultiFactorSession; -} - -/** - * Provider for generating a {@link PhoneMultiFactorAssertion}. - * - * @public - */ -export declare class PhoneMultiFactorGenerator { - private constructor(); - /** - * Provides a {@link PhoneMultiFactorAssertion} to confirm ownership of the phone second factor. - * - * @remarks - * This method does not work in a Node.js environment. - * - * @param phoneAuthCredential - A credential provided by {@link PhoneAuthProvider.credential}. - * @returns A {@link PhoneMultiFactorAssertion} which can be used with - * {@link MultiFactorResolver.resolveSignIn} - */ - static assertion(credential: PhoneAuthCredential): PhoneMultiFactorAssertion; - /** - * The identifier of the phone second factor: `phone`. - */ - static FACTOR_ID: string; -} - -/** - * The subclass of the {@link MultiFactorInfo} interface for phone number - * second factors. The `factorId` of this second factor is {@link FactorId}.PHONE. - * @public - */ -export declare interface PhoneMultiFactorInfo extends MultiFactorInfo { - /** The phone number associated with the current second factor. */ - readonly phoneNumber: string; -} - -/** - * Options used for signing in with a second factor. - * - * @public - */ -export declare interface PhoneMultiFactorSignInInfoOptions { - /** - * The {@link MultiFactorInfo} obtained via {@link MultiFactorResolver.hints}. - * - * One of `multiFactorHint` or `multiFactorUid` is required. - */ - multiFactorHint?: MultiFactorInfo; - /** - * The uid of the second factor. - * - * One of `multiFactorHint` or `multiFactorUid` is required. - */ - multiFactorUid?: string; - /** The {@link MultiFactorSession} obtained via {@link MultiFactorResolver.session}. */ - session: MultiFactorSession; -} - -/* Excluded from this release type: PhoneOrOauthTokenResponse */ - -/** - * Options used for single-factor sign-in. - * - * @public - */ -export declare interface PhoneSingleFactorInfoOptions { - /** Phone number to send a verification code to. */ - phoneNumber: string; -} - -/** - * A resolver used for handling DOM specific operations like {@link signInWithPopup} - * or {@link signInWithRedirect}. - * - * @public - */ -export declare interface PopupRedirectResolver { -} - -/* Excluded from this release type: PopupRedirectResolverInternal */ - -/** - * A minimal error map with all verbose error messages stripped. - * - * See discussion at {@link AuthErrorMap} - * - * @public - */ -export declare const prodErrorMap: AuthErrorMap; - -/** - * Enumeration of supported providers. - * - * @public - */ -export declare const ProviderId: { - /** Facebook provider ID */ - readonly FACEBOOK: "facebook.com"; - /** GitHub provider ID */ - readonly GITHUB: "github.com"; - /** Google provider ID */ - readonly GOOGLE: "google.com"; - /** Password provider */ - readonly PASSWORD: "password"; - /** Phone provider */ - readonly PHONE: "phone"; - /** Twitter provider ID */ - readonly TWITTER: "twitter.com"; -}; - -/* Excluded from this release type: ProviderId_2 */ - -declare interface ProviderUserInfo { - providerId: string; - rawId?: string; - email?: string; - displayName?: string; - photoUrl?: string; - phoneNumber?: string; -} - -/** - * Interface for a supplied `AsyncStorage`. - * - * @public - */ -export declare interface ReactNativeAsyncStorage { - /** - * Persist an item in storage. - * - * @param key - storage key. - * @param value - storage value. - */ - setItem(key: string, value: string): Promise; - /** - * Retrieve an item from storage. - * - * @param key - storage key. - */ - getItem(key: string): Promise; - /** - * Remove an item from storage. - * - * @param key - storage key. - */ - removeItem(key: string): Promise; -} - -/** - * Re-authenticates a user using a fresh credential. - * - * @remarks - * Use before operations such as {@link updatePassword} that require tokens from recent sign-in - * attempts. This method can be used to recover from a `CREDENTIAL_TOO_OLD_LOGIN_AGAIN` error - * or a `TOKEN_EXPIRED` error. - * - * This method is not supported on any {@link User} signed in by {@link Auth} instances - * created with a {@link @firebase/app#FirebaseServerApp}. - * - * @param user - The user. - * @param credential - The auth credential. - * - * @public - */ -export declare function reauthenticateWithCredential(user: User, credential: AuthCredential): Promise; - -/** - * Re-authenticates a user using a fresh phone credential. - * - * @remarks - * Use before operations such as {@link updatePassword} that require tokens from recent sign-in attempts. - * - * This method does not work in a Node.js environment or on any {@link User} signed in by - * {@link Auth} instances created with a {@link @firebase/app#FirebaseServerApp}. - * - * @param user - The user. - * @param phoneNumber - The user's phone number in E.164 format (e.g. +16505550101). - * @param appVerifier - The {@link ApplicationVerifier}. - * - * @public - */ -export declare function reauthenticateWithPhoneNumber(user: User, phoneNumber: string, appVerifier?: ApplicationVerifier): Promise; - -/** - * Reauthenticates the current user with the specified {@link OAuthProvider} using a pop-up based - * OAuth flow. - * - * @remarks - * If the reauthentication is successful, the returned result will contain the user and the - * provider's credential. - * - * This method does not work in a Node.js environment or on any {@link User} signed in by - * {@link Auth} instances created with a {@link @firebase/app#FirebaseServerApp}. - * - * @example - * ```javascript - * // Sign in using a popup. - * const provider = new FacebookAuthProvider(); - * const result = await signInWithPopup(auth, provider); - * // Reauthenticate using a popup. - * await reauthenticateWithPopup(result.user, provider); - * ``` - * - * @param user - The user. - * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}. - * Non-OAuth providers like {@link EmailAuthProvider} will throw an error. - * @param resolver - An instance of {@link PopupRedirectResolver}, optional - * if already supplied to {@link initializeAuth} or provided by {@link getAuth}. - * - * @public - */ -export declare function reauthenticateWithPopup(user: User, provider: AuthProvider, resolver?: PopupRedirectResolver): Promise; - -/** - * Reauthenticates the current user with the specified {@link OAuthProvider} using a full-page redirect flow. - * @remarks - * To handle the results and errors for this operation, refer to {@link getRedirectResult}. - * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices - * | best practices} when using {@link reauthenticateWithRedirect}. - * - * This method does not work in a Node.js environment or with {@link Auth} instances - * created with a {@link @firebase/app#FirebaseServerApp}. - * - * @example - * ```javascript - * // Sign in using a redirect. - * const provider = new FacebookAuthProvider(); - * const result = await signInWithRedirect(auth, provider); - * // This will trigger a full page redirect away from your app - * - * // After returning from the redirect when your app initializes you can obtain the result - * const result = await getRedirectResult(auth); - * // Reauthenticate using a redirect. - * await reauthenticateWithRedirect(result.user, provider); - * // This will again trigger a full page redirect away from your app - * - * // After returning from the redirect when your app initializes you can obtain the result - * const result = await getRedirectResult(auth); - * ``` - * - * @param user - The user. - * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}. - * Non-OAuth providers like {@link EmailAuthProvider} will throw an error. - * @param resolver - An instance of {@link PopupRedirectResolver}, optional - * if already supplied to {@link initializeAuth} or provided by {@link getAuth}. - * - * @public - */ -export declare function reauthenticateWithRedirect(user: User, provider: AuthProvider, resolver?: PopupRedirectResolver): Promise; - -declare interface Recaptcha { - render: (container: HTMLElement, parameters: RecaptchaParameters) => number; - getResponse: (id: number) => string; - execute: (id: number) => unknown; - reset: (id: number) => unknown; -} - -declare class RecaptchaConfig { - /** - * The reCAPTCHA site key. - */ - siteKey: string; - /** - * The list of providers and their enablement status for reCAPTCHA Enterprise. - */ - recaptchaEnforcementState: RecaptchaEnforcementProviderState[]; - constructor(response: GetRecaptchaConfigResponse); - /** - * Returns the reCAPTCHA Enterprise enforcement state for the given provider. - * - * @param providerStr - The provider whose enforcement state is to be returned. - * @returns The reCAPTCHA Enterprise enforcement state for the given provider. - */ - getProviderEnforcementState(providerStr: string): EnforcementState | null; - /** - * Returns true if the reCAPTCHA Enterprise enforcement state for the provider is set to ENFORCE or AUDIT. - * - * @param providerStr - The provider whose enablement state is to be returned. - * @returns Whether or not reCAPTCHA Enterprise protection is enabled for the given provider. - */ - isProviderEnabled(providerStr: string): boolean; - /** - * Returns true if reCAPTCHA Enterprise protection is enabled in at least one provider, otherwise - * returns false. - * - * @returns Whether or not reCAPTCHA Enterprise protection is enabled for at least one provider. - */ - isAnyProviderEnabled(): boolean; -} - -declare interface RecaptchaEnforcementProviderState { - provider: string; - enforcementState: string; -} - -/* Excluded from this release type: ReCaptchaLoader */ - -/** - * Interface representing reCAPTCHA parameters. - * - * See the {@link https://developers.google.com/recaptcha/docs/display#render_param | reCAPTCHA docs} - * for the list of accepted parameters. All parameters are accepted except for `sitekey`: Firebase Auth - * provisions a reCAPTCHA for each project and will configure the site key upon rendering. - * - * For an invisible reCAPTCHA, set the `size` key to `invisible`. - * - * @public - */ -export declare interface RecaptchaParameters { - [key: string]: any; -} - -/** - * An {@link https://www.google.com/recaptcha/ | reCAPTCHA}-based application verifier. - * - * @remarks - * `RecaptchaVerifier` does not work in a Node.js environment. - * - * @public - */ -export declare class RecaptchaVerifier implements ApplicationVerifierInternal { - private readonly parameters; - /** - * The application verifier type. - * - * @remarks - * For a reCAPTCHA verifier, this is 'recaptcha'. - */ - readonly type = "recaptcha"; - private destroyed; - private widgetId; - private readonly container; - private readonly isInvisible; - private readonly tokenChangeListeners; - private renderPromise; - private readonly auth; - /* Excluded from this release type: _recaptchaLoader */ - private recaptcha; - /** - * @param authExtern - The corresponding Firebase {@link Auth} instance. - * - * @param containerOrId - The reCAPTCHA container parameter. - * - * @remarks - * This has different meaning depending on whether the reCAPTCHA is hidden or visible. For a - * visible reCAPTCHA the container must be empty. If a string is used, it has to correspond to - * an element ID. The corresponding element must also must be in the DOM at the time of - * initialization. - * - * @param parameters - The optional reCAPTCHA parameters. - * - * @remarks - * Check the reCAPTCHA docs for a comprehensive list. All parameters are accepted except for - * the sitekey. Firebase Auth backend provisions a reCAPTCHA for each project and will - * configure this upon rendering. For an invisible reCAPTCHA, a size key must have the value - * 'invisible'. - */ - constructor(authExtern: Auth, containerOrId: HTMLElement | string, parameters?: RecaptchaParameters); - /** - * Waits for the user to solve the reCAPTCHA and resolves with the reCAPTCHA token. - * - * @returns A Promise for the reCAPTCHA token. - */ - verify(): Promise; - /** - * Renders the reCAPTCHA widget on the page. - * - * @returns A Promise that resolves with the reCAPTCHA widget ID. - */ - render(): Promise; - /* Excluded from this release type: _reset */ - /** - * Clears the reCAPTCHA widget from the page and destroys the instance. - */ - clear(): void; - private validateStartingState; - private makeTokenCallback; - private assertNotDestroyed; - private makeRenderPromise; - private init; - private getAssertedRecaptcha; -} - -/** - * Reloads user account data, if signed in. - * - * @param user - The user. - * - * @public - */ -export declare function reload(user: User): Promise; - -/** - * Revokes the given access token. Currently only supports Apple OAuth access tokens. - * - * @param auth - The {@link Auth} instance. - * @param token - The Apple OAuth access token. - * - * @public - */ -export declare function revokeAccessToken(auth: Auth, token: string): Promise; - -/** - * An {@link AuthProvider} for SAML. - * - * @public - */ -export declare class SAMLAuthProvider extends FederatedAuthProvider { - /** - * Constructor. The providerId must start with "saml." - * @param providerId - SAML provider ID. - */ - constructor(providerId: string); - /** - * Generates an {@link AuthCredential} from a {@link UserCredential} after a - * successful SAML flow completes. - * - * @remarks - * - * For example, to get an {@link AuthCredential}, you could write the - * following code: - * - * ```js - * const userCredential = await signInWithPopup(auth, samlProvider); - * const credential = SAMLAuthProvider.credentialFromResult(userCredential); - * ``` - * - * @param userCredential - The user credential. - */ - static credentialFromResult(userCredential: UserCredential): AuthCredential | null; - /** - * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was - * thrown during a sign-in, link, or reauthenticate operation. - * - * @param userCredential - The user credential. - */ - static credentialFromError(error: FirebaseError): AuthCredential | null; - /** - * Creates an {@link AuthCredential} from a JSON string or a plain object. - * @param json - A plain object or a JSON string - */ - static credentialFromJSON(json: string | object): AuthCredential; - private static samlCredentialFromTaggedObject; -} - -/** - * Sends a verification email to a user. - * - * @remarks - * The verification process is completed by calling {@link applyActionCode}. - * - * @example - * ```javascript - * const 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 - * }; - * await sendEmailVerification(user, actionCodeSettings); - * // Obtain code from the user. - * await applyActionCode(auth, code); - * ``` - * - * @param user - The user. - * @param actionCodeSettings - The {@link ActionCodeSettings}. - * - * @public - */ -export declare function sendEmailVerification(user: User, actionCodeSettings?: ActionCodeSettings | null): Promise; - -/** - * Sends a password reset email to the given email address. This method does not throw an error when - * there's no user account with the given email address and - * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection} - * is enabled. - * - * @remarks - * To complete the password reset, call {@link confirmPasswordReset} with the code supplied in - * the email sent to the user, along with the new password specified by the user. - * - * @example - * ```javascript - * const 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 - * }; - * await sendPasswordResetEmail(auth, 'user@example.com', actionCodeSettings); - * // Obtain code from user. - * await confirmPasswordReset('user@example.com', code); - * ``` - * - * @param auth - The {@link Auth} instance. - * @param email - The user's email address. - * @param actionCodeSettings - The {@link ActionCodeSettings}. - * - * @public - */ -export declare function sendPasswordResetEmail(auth: Auth, email: string, actionCodeSettings?: ActionCodeSettings): Promise; - -/** - * Sends a sign-in email link to the user with the specified email. - * - * @remarks - * The sign-in operation has to always be completed in the app unlike other out of band email - * actions (password reset and email verifications). This is because, at the end of the flow, - * the user is expected to be signed in and their Auth state persisted within the app. - * - * To complete sign in with the email link, call {@link signInWithEmailLink} with the email - * address and the email link supplied in the email sent to the user. - * - * @example - * ```javascript - * const 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 - * }; - * await sendSignInLinkToEmail(auth, 'user@example.com', actionCodeSettings); - * // Obtain emailLink from the user. - * if(isSignInWithEmailLink(auth, emailLink)) { - * await signInWithEmailLink(auth, 'user@example.com', emailLink); - * } - * ``` - * - * @param authInternal - The {@link Auth} instance. - * @param email - The user's email address. - * @param actionCodeSettings - The {@link ActionCodeSettings}. - * - * @public - */ -export declare function sendSignInLinkToEmail(auth: Auth, email: string, actionCodeSettings: ActionCodeSettings): Promise; - -/** - * Changes the type of persistence on the {@link Auth} instance for the currently saved - * `Auth` session and applies this type of persistence for future sign-in requests, including - * sign-in with redirect requests. - * - * @remarks - * This makes it easy for a user signing in to specify whether their session should be - * remembered or not. It also makes it easier to never persist the `Auth` state for applications - * that are shared by other users or have sensitive data. - * - * This method does not work in a Node.js environment or with {@link Auth} instances created with a - * {@link @firebase/app#FirebaseServerApp}. - * - * @example - * ```javascript - * setPersistence(auth, browserSessionPersistence); - * ``` - * - * @param auth - The {@link Auth} instance. - * @param persistence - The {@link Persistence} to use. - * @returns A `Promise` that resolves once the persistence change has completed - * - * @public - */ -export declare function setPersistence(auth: Auth, persistence: Persistence): Promise; - -/** - * Asynchronously signs in as an anonymous user. - * - * @remarks - * If there is already an anonymous user signed in, that user will be returned; otherwise, a - * new anonymous user identity will be created and returned. - * - * This method is not supported by {@link Auth} instances created with a - * {@link @firebase/app#FirebaseServerApp}. - * - * @param auth - The {@link Auth} instance. - * - * @public - */ -export declare function signInAnonymously(auth: Auth): Promise; - -/** - * Enumeration of supported sign-in methods. - * - * @public - */ -export declare const SignInMethod: { - /** Email link sign in method */ - readonly EMAIL_LINK: "emailLink"; - /** Email/password sign in method */ - readonly EMAIL_PASSWORD: "password"; - /** Facebook sign in method */ - readonly FACEBOOK: "facebook.com"; - /** GitHub sign in method */ - readonly GITHUB: "github.com"; - /** Google sign in method */ - readonly GOOGLE: "google.com"; - /** Phone sign in method */ - readonly PHONE: "phone"; - /** Twitter sign in method */ - readonly TWITTER: "twitter.com"; -}; - -/** - * Asynchronously signs in with the given credentials. - * - * @remarks - * An {@link AuthProvider} can be used to generate the credential. - * - * This method is not supported by {@link Auth} instances created with a - * {@link @firebase/app#FirebaseServerApp}. - * - * @param auth - The {@link Auth} instance. - * @param credential - The auth credential. - * - * @public - */ -export declare function signInWithCredential(auth: Auth, credential: AuthCredential): Promise; - -/** - * Asynchronously signs in using a custom token. - * - * @remarks - * Custom tokens are used to integrate Firebase Auth with existing auth systems, and must - * be generated by an auth backend using the - * {@link https://firebase.google.com/docs/reference/admin/node/admin.auth.Auth#createcustomtoken | createCustomToken} - * method in the {@link https://firebase.google.com/docs/auth/admin | Admin SDK} . - * - * Fails with an error if the token is invalid, expired, or not accepted by the Firebase Auth service. - * - * This method is not supported by {@link Auth} instances created with a - * {@link @firebase/app#FirebaseServerApp}. - * - * @param auth - The {@link Auth} instance. - * @param customToken - The custom token to sign in with. - * - * @public - */ -export declare function signInWithCustomToken(auth: Auth, customToken: string): Promise; - -/** - * Asynchronously signs in using an email and password. - * - * @remarks - * Fails with an error if the email address and password do not match. When - * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection} - * is enabled, this method fails with "auth/invalid-credential" in case of an invalid - * email/password. - * - * This method is not supported on {@link Auth} instances created with a - * {@link @firebase/app#FirebaseServerApp}. - * - * Note: The user's password is NOT the password used to access the user's email account. The - * email address serves as a unique identifier for the user, and the password is used to access - * the user's account in your Firebase project. See also: {@link createUserWithEmailAndPassword}. - * - * - * @param auth - The {@link Auth} instance. - * @param email - The users email address. - * @param password - The users password. - * - * @public - */ -export declare function signInWithEmailAndPassword(auth: Auth, email: string, password: string): Promise; - -/** - * Asynchronously signs in using an email and sign-in email link. - * - * @remarks - * If no link is passed, the link is inferred from the current URL. - * - * Fails with an error if the email address is invalid or OTP in email link expires. - * - * This method is not supported by {@link Auth} instances created with a - * {@link @firebase/app#FirebaseServerApp}. - * - * Note: Confirm the link is a sign-in email link before calling this method firebase.auth.Auth.isSignInWithEmailLink. - * - * @example - * ```javascript - * const 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 - * }; - * await sendSignInLinkToEmail(auth, 'user@example.com', actionCodeSettings); - * // Obtain emailLink from the user. - * if(isSignInWithEmailLink(auth, emailLink)) { - * await signInWithEmailLink(auth, 'user@example.com', emailLink); - * } - * ``` - * - * - * @param auth - The {@link Auth} instance. - * @param email - The user's email address. - * @param emailLink - The link sent to the user's email address. - * - * @public - */ -export declare function signInWithEmailLink(auth: Auth, email: string, emailLink?: string): Promise; - -/* Excluded from this release type: SignInWithIdpResponse */ - -/** - * Asynchronously signs in using a phone number. - * - * @remarks - * This method sends a code via SMS to the given - * phone number, and returns a {@link ConfirmationResult}. After the user - * provides the code sent to their phone, call {@link ConfirmationResult.confirm} - * with the code to sign the user in. - * - * For abuse prevention, this method requires a {@link ApplicationVerifier}. - * This SDK includes an implementation based on reCAPTCHA v2, {@link RecaptchaVerifier}. - * This function can work on other platforms that do not support the - * {@link RecaptchaVerifier} (like React Native), but you need to use a - * third-party {@link ApplicationVerifier} implementation. - * - * If you've enabled project-level reCAPTCHA Enterprise bot protection in - * Enforce mode, you can omit the {@link ApplicationVerifier}. - * - * This method does not work in a Node.js environment or with {@link Auth} instances created with a - * {@link @firebase/app#FirebaseServerApp}. - * - * @example - * ```javascript - * // 'recaptcha-container' is the ID of an element in the DOM. - * const applicationVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container'); - * const confirmationResult = await signInWithPhoneNumber(auth, phoneNumber, applicationVerifier); - * // Obtain a verificationCode from the user. - * const credential = await confirmationResult.confirm(verificationCode); - * ``` - * - * @param auth - The {@link Auth} instance. - * @param phoneNumber - The user's phone number in E.164 format (e.g. +16505550101). - * @param appVerifier - The {@link ApplicationVerifier}. - * - * @public - */ -export declare function signInWithPhoneNumber(auth: Auth, phoneNumber: string, appVerifier?: ApplicationVerifier): Promise; - -/* Excluded from this release type: SignInWithPhoneNumberRequest */ - -/* Excluded from this release type: SignInWithPhoneNumberResponse */ - -/** - * Authenticates a Firebase client using a popup-based OAuth authentication flow. - * - * @remarks - * If succeeds, returns the signed in user along with the provider's credential. If sign in was - * unsuccessful, returns an error object containing additional information about the error. - * - * This method does not work in a Node.js environment or with {@link Auth} instances created with a - * {@link @firebase/app#FirebaseServerApp}. - * - * @example - * ```javascript - * // Sign in using a popup. - * const provider = new FacebookAuthProvider(); - * const result = await signInWithPopup(auth, provider); - * - * // The signed-in user info. - * const user = result.user; - * // This gives you a Facebook Access Token. - * const credential = provider.credentialFromResult(auth, result); - * const token = credential.accessToken; - * ``` - * - * @param auth - The {@link Auth} instance. - * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}. - * Non-OAuth providers like {@link EmailAuthProvider} will throw an error. - * @param resolver - An instance of {@link PopupRedirectResolver}, optional - * if already supplied to {@link initializeAuth} or provided by {@link getAuth}. - * - * @public - */ -export declare function signInWithPopup(auth: Auth, provider: AuthProvider, resolver?: PopupRedirectResolver): Promise; - -/** - * Authenticates a Firebase client using a full-page redirect flow. - * - * @remarks - * To handle the results and errors for this operation, refer to {@link getRedirectResult}. - * Follow the {@link https://firebase.google.com/docs/auth/web/redirect-best-practices - * | best practices} when using {@link signInWithRedirect}. - * - * This method does not work in a Node.js environment or with {@link Auth} instances created with a - * {@link @firebase/app#FirebaseServerApp}. - * - * @example - * ```javascript - * // Sign in using a redirect. - * const provider = new FacebookAuthProvider(); - * // You can add additional scopes to the provider: - * provider.addScope('user_birthday'); - * // Start a sign in process for an unauthenticated user. - * await signInWithRedirect(auth, provider); - * // This will trigger a full page redirect away from your app - * - * // After returning from the redirect when your app initializes you can obtain the result - * const result = await getRedirectResult(auth); - * if (result) { - * // This is the signed-in user - * const user = result.user; - * // This gives you a Facebook Access Token. - * const credential = provider.credentialFromResult(auth, result); - * const token = credential.accessToken; - * } - * // As this API can be used for sign-in, linking and reauthentication, - * // check the operationType to determine what triggered this redirect - * // operation. - * const operationType = result.operationType; - * ``` - * - * @param auth - The {@link Auth} instance. - * @param provider - The provider to authenticate. The provider has to be an {@link OAuthProvider}. - * Non-OAuth providers like {@link EmailAuthProvider} will throw an error. - * @param resolver - An instance of {@link PopupRedirectResolver}, optional - * if already supplied to {@link initializeAuth} or provided by {@link getAuth}. - * - * @public - */ -export declare function signInWithRedirect(auth: Auth, provider: AuthProvider, resolver?: PopupRedirectResolver): Promise; - -/** - * Signs out the current user. - * - * @remarks - * This method is not supported by {@link Auth} instances created with a - * {@link @firebase/app#FirebaseServerApp}. - * - * @param auth - The {@link Auth} instance. - * - * @public - */ -export declare function signOut(auth: Auth): Promise; - -declare interface StartTotpMfaEnrollmentResponse { - totpSessionInfo: { - sharedSecretKey: string; - verificationCodeLength: number; - hashingAlgorithm: string; - periodSec: number; - sessionInfo: string; - finalizeEnrollmentTime: number; - }; -} - -declare interface StorageEventListener { - (value: PersistenceValue | null): void; -} - -/* Excluded from this release type: StsTokenManager */ - -/* Excluded from this release type: TaggedWithTokenResponse */ - -/** - * An MFA provided by TOTP (Time-based One Time Password). - */ -declare interface TotpMfaEnrollment extends BaseMfaEnrollment { -} - -/** - * The class for asserting ownership of a TOTP second factor. Provided by - * {@link TotpMultiFactorGenerator.assertionForEnrollment} and - * {@link TotpMultiFactorGenerator.assertionForSignIn}. - * - * @public - */ -export declare interface TotpMultiFactorAssertion extends MultiFactorAssertion { -} - -/** - * Provider for generating a {@link TotpMultiFactorAssertion}. - * - * @public - */ -export declare class TotpMultiFactorGenerator { - /** - * Provides a {@link TotpMultiFactorAssertion} to confirm ownership of - * the TOTP (time-based one-time password) second factor. - * This assertion is used to complete enrollment in TOTP second factor. - * - * @param secret A {@link TotpSecret} containing the shared secret key and other TOTP parameters. - * @param oneTimePassword One-time password from TOTP App. - * @returns A {@link TotpMultiFactorAssertion} which can be used with - * {@link MultiFactorUser.enroll}. - */ - static assertionForEnrollment(secret: TotpSecret, oneTimePassword: string): TotpMultiFactorAssertion; - /** - * Provides a {@link TotpMultiFactorAssertion} to confirm ownership of the TOTP second factor. - * This assertion is used to complete signIn with TOTP as the second factor. - * - * @param enrollmentId identifies the enrolled TOTP second factor. - * @param oneTimePassword One-time password from TOTP App. - * @returns A {@link TotpMultiFactorAssertion} which can be used with - * {@link MultiFactorResolver.resolveSignIn}. - */ - static assertionForSignIn(enrollmentId: string, oneTimePassword: string): TotpMultiFactorAssertion; - /** - * Returns a promise to {@link TotpSecret} which contains the TOTP shared secret key and other parameters. - * Creates a TOTP secret as part of enrolling a TOTP second factor. - * Used for generating a QR code URL or inputting into a TOTP app. - * This method uses the auth instance corresponding to the user in the multiFactorSession. - * - * @param session The {@link MultiFactorSession} that the user is part of. - * @returns A promise to {@link TotpSecret}. - */ - static generateSecret(session: MultiFactorSession): Promise; - /** - * The identifier of the TOTP second factor: `totp`. - */ - static FACTOR_ID: 'totp'; -} - -/** - * The subclass of the {@link MultiFactorInfo} interface for TOTP - * second factors. The `factorId` of this second factor is {@link FactorId}.TOTP. - * @public - */ -export declare interface TotpMultiFactorInfo extends MultiFactorInfo { -} - -/** - * Provider for generating a {@link TotpMultiFactorAssertion}. - * - * Stores the shared secret key and other parameters to generate time-based OTPs. - * Implements methods to retrieve the shared secret key and generate a QR code URL. - * @public - */ -export declare class TotpSecret { - private readonly sessionInfo; - private readonly auth; - /** - * Shared secret key/seed used for enrolling in TOTP MFA and generating OTPs. - */ - readonly secretKey: string; - /** - * Hashing algorithm used. - */ - readonly hashingAlgorithm: string; - /** - * Length of the one-time passwords to be generated. - */ - readonly codeLength: number; - /** - * The interval (in seconds) when the OTP codes should change. - */ - readonly codeIntervalSeconds: number; - /** - * The timestamp (UTC string) by which TOTP enrollment should be completed. - */ - readonly enrollmentCompletionDeadline: string; - private constructor(); - /* Excluded from this release type: _fromStartTotpMfaEnrollmentResponse */ - /* Excluded from this release type: _makeTotpVerificationInfo */ - /** - * Returns a QR code URL as described in - * https://github.com/google/google-authenticator/wiki/Key-Uri-Format - * This can be displayed to the user as a QR code to be scanned into a TOTP app like Google Authenticator. - * If the optional parameters are unspecified, an accountName of and issuer of are used. - * - * @param accountName the name of the account/app along with a user identifier. - * @param issuer issuer of the TOTP (likely the app name). - * @returns A QR code URL string. - */ - generateQrCodeUrl(accountName?: string, issuer?: string): string; -} - -declare interface TotpVerificationInfo { - sessionInfo: string; - verificationCode: string; -} - -/** - * Provider for generating an {@link OAuthCredential} for {@link ProviderId}.TWITTER. - * - * @example - * ```javascript - * // Sign in using a redirect. - * const provider = new TwitterAuthProvider(); - * // Start a sign in process for an unauthenticated user. - * await signInWithRedirect(auth, provider); - * // This will trigger a full page redirect away from your app - * - * // After returning from the redirect when your app initializes you can obtain the result - * const result = await getRedirectResult(auth); - * if (result) { - * // This is the signed-in user - * const user = result.user; - * // This gives you a Twitter Access Token and Secret. - * const credential = TwitterAuthProvider.credentialFromResult(result); - * const token = credential.accessToken; - * const secret = credential.secret; - * } - * ``` - * - * @example - * ```javascript - * // Sign in using a popup. - * const provider = new TwitterAuthProvider(); - * const result = await signInWithPopup(auth, provider); - * - * // The signed-in user info. - * const user = result.user; - * // This gives you a Twitter Access Token and Secret. - * const credential = TwitterAuthProvider.credentialFromResult(result); - * const token = credential.accessToken; - * const secret = credential.secret; - * ``` - * - * @public - */ -export declare class TwitterAuthProvider extends BaseOAuthProvider { - /** Always set to {@link SignInMethod}.TWITTER. */ - static readonly TWITTER_SIGN_IN_METHOD: 'twitter.com'; - /** Always set to {@link ProviderId}.TWITTER. */ - static readonly PROVIDER_ID: 'twitter.com'; - constructor(); - /** - * Creates a credential for Twitter. - * - * @param token - Twitter access token. - * @param secret - Twitter secret. - */ - static credential(token: string, secret: string): OAuthCredential; - /** - * Used to extract the underlying {@link OAuthCredential} from a {@link UserCredential}. - * - * @param userCredential - The user credential. - */ - static credentialFromResult(userCredential: UserCredential): OAuthCredential | null; - /** - * Used to extract the underlying {@link OAuthCredential} from a {@link AuthError} which was - * thrown during a sign-in, link, or reauthenticate operation. - * - * @param userCredential - The user credential. - */ - static credentialFromError(error: FirebaseError): OAuthCredential | null; - private static credentialFromTaggedObject; -} - -/** - * Unlinks a provider from a user account. - * - * @param user - The user. - * @param providerId - The provider to unlink. - * - * @public - */ -export declare function unlink(user: User, providerId: string): Promise; -export { Unsubscribe } - -/** - * Asynchronously sets the provided user as {@link Auth.currentUser} on the - * {@link Auth} instance. - * - * @remarks - * A new instance copy of the user provided will be made and set as currentUser. - * - * This will trigger {@link onAuthStateChanged} and {@link onIdTokenChanged} listeners - * like other sign in methods. - * - * The operation fails with an error if the user to be updated belongs to a different Firebase - * project. - * - * This method is not supported by {@link Auth} instances created with a - * {@link @firebase/app#FirebaseServerApp}. - * - * @param auth - The {@link Auth} instance. - * @param user - The new {@link User}. - * - * @public - */ -export declare function updateCurrentUser(auth: Auth, user: User | null): Promise; - -/** - * Updates the user's email address. - * - * @remarks - * An email will be sent to the original email address (if it was set) that allows to revoke the - * email address change, in order to protect them from account hijacking. - * - * This method is not supported on any {@link User} signed in by {@link Auth} instances - * created with a {@link @firebase/app#FirebaseServerApp}. - * - * Important: this is a security sensitive operation that requires the user to have recently signed - * in. If this requirement isn't met, ask the user to authenticate again and then call - * {@link reauthenticateWithCredential}. - * - * @param user - The user. - * @param newEmail - The new email address. - * - * Throws "auth/operation-not-allowed" error when - * {@link https://cloud.google.com/identity-platform/docs/admin/email-enumeration-protection | Email Enumeration Protection} - * is enabled. - * Deprecated - Use {@link verifyBeforeUpdateEmail} instead. - * - * @public - */ -export declare function updateEmail(user: User, newEmail: string): Promise; - -/** - * Updates the user's password. - * - * @remarks - * Important: this is a security sensitive operation that requires the user to have recently signed - * in. If this requirement isn't met, ask the user to authenticate again and then call - * {@link reauthenticateWithCredential}. - * - * @param user - The user. - * @param newPassword - The new password. - * - * @public - */ -export declare function updatePassword(user: User, newPassword: string): Promise; - -/** - * Updates the user's phone number. - * - * @remarks - * This method does not work in a Node.js environment or on any {@link User} signed in by - * {@link Auth} instances created with a {@link @firebase/app#FirebaseServerApp}. - * - * @example - * ``` - * // 'recaptcha-container' is the ID of an element in the DOM. - * const applicationVerifier = new RecaptchaVerifier('recaptcha-container'); - * const provider = new PhoneAuthProvider(auth); - * const verificationId = await provider.verifyPhoneNumber('+16505550101', applicationVerifier); - * // Obtain the verificationCode from the user. - * const phoneCredential = PhoneAuthProvider.credential(verificationId, verificationCode); - * await updatePhoneNumber(user, phoneCredential); - * ``` - * - * @param user - The user. - * @param credential - A credential authenticating the new phone number. - * - * @public - */ -export declare function updatePhoneNumber(user: User, credential: PhoneAuthCredential): Promise; - -/** - * Updates a user's profile data. - * - * @param user - The user. - * @param profile - The profile's `displayName` and `photoURL` to update. - * - * @public - */ -export declare function updateProfile(user: User, { displayName, photoURL: photoUrl }: { - displayName?: string | null; - photoURL?: string | null; -}): Promise; - -/** - * Sets the current language to the default device/browser preference. - * - * @param auth - The {@link Auth} instance. - * - * @public - */ -export declare function useDeviceLanguage(auth: Auth): void; - -/** - * A user account. - * - * @public - */ -export declare interface User extends UserInfo { - /** - * Whether the email has been verified with {@link sendEmailVerification} and - * {@link applyActionCode}. - */ - readonly emailVerified: boolean; - /** - * Whether the user is authenticated using the {@link ProviderId}.ANONYMOUS provider. - */ - readonly isAnonymous: boolean; - /** - * Additional metadata around user creation and sign-in times. - */ - readonly metadata: UserMetadata; - /** - * Additional per provider such as displayName and profile information. - */ - readonly providerData: UserInfo[]; - /** - * Refresh token used to reauthenticate the user. Avoid using this directly and prefer - * {@link User.getIdToken} to refresh the ID token instead. - */ - readonly refreshToken: string; - /** - * The user's tenant ID. - * - * @remarks - * This is a read-only property, which indicates the tenant ID - * used to sign in the user. This is null if the user is signed in from the parent - * project. - * - * @example - * ```javascript - * // Set the tenant ID on Auth instance. - * auth.tenantId = 'TENANT_PROJECT_ID'; - * - * // All future sign-in request now include tenant ID. - * const result = await signInWithEmailAndPassword(auth, email, password); - * // result.user.tenantId should be 'TENANT_PROJECT_ID'. - * ``` - */ - readonly tenantId: string | null; - /** - * Deletes and signs out the user. - * - * @remarks - * Important: this is a security-sensitive operation that requires the user to have recently - * signed in. If this requirement isn't met, ask the user to authenticate again and then call - * one of the reauthentication methods like {@link reauthenticateWithCredential}. - * - * This method is not supported on any {@link User} signed in by {@link Auth} instances - * created with a {@link @firebase/app#FirebaseServerApp}. - */ - delete(): Promise; - /** - * Returns a JSON Web Token (JWT) used to identify the user to a Firebase service. - * - * @remarks - * Returns the current token if it has not expired or if it will not expire in the next five - * minutes. Otherwise, this will refresh the token and return a new one. - * - * @param forceRefresh - Force refresh regardless of token expiration. - */ - getIdToken(forceRefresh?: boolean): Promise; - /** - * Returns a deserialized JSON Web Token (JWT) used to identify the user to a Firebase service. - * - * @remarks - * Returns the current token if it has not expired or if it will not expire in the next five - * minutes. Otherwise, this will refresh the token and return a new one. - * - * @param forceRefresh - Force refresh regardless of token expiration. - */ - getIdTokenResult(forceRefresh?: boolean): Promise; - /** - * Refreshes the user, if signed in. - */ - reload(): Promise; - /** - * Returns a JSON-serializable representation of this object. - * - * @returns A JSON-serializable representation of this object. - */ - toJSON(): object; -} - -/** - * A structure containing a {@link User}, the {@link OperationType}, and the provider ID. - * - * @remarks - * `operationType` could be {@link OperationType}.SIGN_IN for a sign-in operation, - * {@link OperationType}.LINK for a linking operation and {@link OperationType}.REAUTHENTICATE for - * a reauthentication operation. - * - * @public - */ -export declare interface UserCredential { - /** - * The user authenticated by this credential. - */ - user: User; - /** - * The provider which was used to authenticate the user. - */ - providerId: string | null; - /** - * The type of operation which was used to authenticate the user (such as sign-in or link). - */ - operationType: (typeof OperationType)[keyof typeof OperationType]; -} - -/* Excluded from this release type: UserCredentialInternal */ - -/** - * User profile information, visible only to the Firebase project's apps. - * - * @public - */ -export declare interface UserInfo { - /** - * The display name of the user. - */ - readonly displayName: string | null; - /** - * The email of the user. - */ - readonly email: string | null; - /** - * The phone number normalized based on the E.164 standard (e.g. +16505550101) for the - * user. - * - * @remarks - * This is null if the user has no phone credential linked to the account. - */ - readonly phoneNumber: string | null; - /** - * The profile photo URL of the user. - */ - readonly photoURL: string | null; - /** - * The provider used to authenticate the user. - */ - readonly providerId: string; - /** - * The user's unique ID, scoped to the project. - */ - readonly uid: string; -} - -/* Excluded from this release type: UserInternal */ - -/** - * Interface representing a user's metadata. - * - * @public - */ -export declare interface UserMetadata { - /** Time the user was created. */ - readonly creationTime?: string; - /** Time the user last signed in. */ - readonly lastSignInTime?: string; -} - -declare class UserMetadata_2 implements UserMetadata { - private createdAt?; - private lastLoginAt?; - creationTime?: string; - lastSignInTime?: string; - constructor(createdAt?: (string | number) | undefined, lastLoginAt?: (string | number) | undefined); - private _initializeTime; - _copy(metadata: UserMetadata_2): void; - toJSON(): object; -} - -/** - * User profile used in {@link AdditionalUserInfo}. - * - * @public - */ -export declare type UserProfile = Record; - -/** - * Validates the password against the password policy configured for the project or tenant. - * - * @remarks - * If no tenant ID is set on the `Auth` instance, then this method will use the password - * policy configured for the project. Otherwise, this method will use the policy configured - * for the tenant. If a password policy has not been configured, then the default policy - * configured for all projects will be used. - * - * If an auth flow fails because a submitted password does not meet the password policy - * requirements and this method has previously been called, then this method will use the - * most recent policy available when called again. - * - * @example - * ```javascript - * validatePassword(auth, 'some-password'); - * ``` - * - * @param auth The {@link Auth} instance. - * @param password The password to validate. - * - * @public - */ -export declare function validatePassword(auth: Auth, password: string): Promise; - -/** - * Sends a verification email to a new email address. - * - * @remarks - * The user's email will be updated to the new one after being verified. - * - * If you have a custom email action handler, you can complete the verification process by calling - * {@link applyActionCode}. - * - * @example - * ```javascript - * const 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 - * }; - * await verifyBeforeUpdateEmail(user, 'newemail@example.com', actionCodeSettings); - * // Obtain code from the user. - * await applyActionCode(auth, code); - * ``` - * - * @param user - The user. - * @param newEmail - The new email address to be verified before update. - * @param actionCodeSettings - The {@link ActionCodeSettings}. - * - * @public - */ -export declare function verifyBeforeUpdateEmail(user: User, newEmail: string, actionCodeSettings?: ActionCodeSettings | null): Promise; - -/** - * Checks a password reset code sent to the user by email or other out-of-band mechanism. - * - * @returns the user's email address if valid. - * - * @param auth - The {@link Auth} instance. - * @param code - A verification code sent to the user. - * - * @public - */ -export declare function verifyPasswordResetCode(auth: Auth, code: string): Promise; - -export { } diff --git a/.github/scripts/compare-types/src/registry.ts b/.github/scripts/compare-types/src/registry.ts index a9df676966..af63df8d07 100644 --- a/.github/scripts/compare-types/src/registry.ts +++ b/.github/scripts/compare-types/src/registry.ts @@ -18,6 +18,7 @@ import appCheckConfig from '../configs/app-check'; import firestoreConfig from '../configs/firestore'; import firestorePipelinesConfig from '../configs/firestore-pipelines'; import remoteConfigConfig from '../configs/remote-config'; +import authConfig from '../configs/auth'; const SCRIPT_DIR = path.resolve(__dirname, '..'); const REPO_ROOT = path.resolve(SCRIPT_DIR, '..', '..', '..'); From 1c265d6b9464aa364af5031cdd406d9525c3d69c Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Tue, 12 May 2026 18:03:09 +0100 Subject: [PATCH 44/45] yarn.lock --- yarn.lock | 269 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 232 insertions(+), 37 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4832e300ed..dd53bd492c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1233,7 +1233,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-flow-strip-types@npm:^7.25.2, @babel/plugin-transform-flow-strip-types@npm:^7.27.1": +"@babel/plugin-transform-flow-strip-types@npm:^7.25.2, @babel/plugin-transform-flow-strip-types@npm:^7.26.5, @babel/plugin-transform-flow-strip-types@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-flow-strip-types@npm:7.27.1" dependencies: @@ -1375,6 +1375,20 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-modules-systemjs@npm:^7.29.4": + version: 7.29.4 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.29.4" + dependencies: + "@babel/helper-module-transforms": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-validator-identifier": "npm:^7.28.5" + "@babel/traverse": "npm:^7.29.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/79269e6ec8ec831bb63bf1c7cc1a980e28da785e92b36d42612f0139e4044499b99aa109fca849e1a156c092aabf6c24d145f4cabf2ac9ea84ef468852fe4c03 + languageName: node + linkType: hard + "@babel/plugin-transform-modules-umd@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-modules-umd@npm:7.27.1" @@ -1804,7 +1818,7 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-strict-mode@npm:^7.27.1": +"@babel/plugin-transform-strict-mode@npm:^7.24.7, @babel/plugin-transform-strict-mode@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-strict-mode@npm:7.27.1" dependencies: @@ -1899,6 +1913,87 @@ __metadata: languageName: node linkType: hard +"@babel/preset-env@npm:^7.25.2": + version: 7.29.5 + resolution: "@babel/preset-env@npm:7.29.5" + dependencies: + "@babel/compat-data": "npm:^7.29.3" + "@babel/helper-compilation-targets": "npm:^7.28.6" + "@babel/helper-plugin-utils": "npm:^7.28.6" + "@babel/helper-validator-option": "npm:^7.27.1" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "npm:^7.28.5" + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "npm:^7.27.1" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.27.1" + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "npm:^7.29.3" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.27.1" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.28.6" + "@babel/plugin-proposal-private-property-in-object": "npm:7.21.0-placeholder-for-preset-env.2" + "@babel/plugin-syntax-import-assertions": "npm:^7.28.6" + "@babel/plugin-syntax-import-attributes": "npm:^7.28.6" + "@babel/plugin-syntax-unicode-sets-regex": "npm:^7.18.6" + "@babel/plugin-transform-arrow-functions": "npm:^7.27.1" + "@babel/plugin-transform-async-generator-functions": "npm:^7.29.0" + "@babel/plugin-transform-async-to-generator": "npm:^7.28.6" + "@babel/plugin-transform-block-scoped-functions": "npm:^7.27.1" + "@babel/plugin-transform-block-scoping": "npm:^7.28.6" + "@babel/plugin-transform-class-properties": "npm:^7.28.6" + "@babel/plugin-transform-class-static-block": "npm:^7.28.6" + "@babel/plugin-transform-classes": "npm:^7.28.6" + "@babel/plugin-transform-computed-properties": "npm:^7.28.6" + "@babel/plugin-transform-destructuring": "npm:^7.28.5" + "@babel/plugin-transform-dotall-regex": "npm:^7.28.6" + "@babel/plugin-transform-duplicate-keys": "npm:^7.27.1" + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "npm:^7.29.0" + "@babel/plugin-transform-dynamic-import": "npm:^7.27.1" + "@babel/plugin-transform-explicit-resource-management": "npm:^7.28.6" + "@babel/plugin-transform-exponentiation-operator": "npm:^7.28.6" + "@babel/plugin-transform-export-namespace-from": "npm:^7.27.1" + "@babel/plugin-transform-for-of": "npm:^7.27.1" + "@babel/plugin-transform-function-name": "npm:^7.27.1" + "@babel/plugin-transform-json-strings": "npm:^7.28.6" + "@babel/plugin-transform-literals": "npm:^7.27.1" + "@babel/plugin-transform-logical-assignment-operators": "npm:^7.28.6" + "@babel/plugin-transform-member-expression-literals": "npm:^7.27.1" + "@babel/plugin-transform-modules-amd": "npm:^7.27.1" + "@babel/plugin-transform-modules-commonjs": "npm:^7.28.6" + "@babel/plugin-transform-modules-systemjs": "npm:^7.29.4" + "@babel/plugin-transform-modules-umd": "npm:^7.27.1" + "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.29.0" + "@babel/plugin-transform-new-target": "npm:^7.27.1" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.28.6" + "@babel/plugin-transform-numeric-separator": "npm:^7.28.6" + "@babel/plugin-transform-object-rest-spread": "npm:^7.28.6" + "@babel/plugin-transform-object-super": "npm:^7.27.1" + "@babel/plugin-transform-optional-catch-binding": "npm:^7.28.6" + "@babel/plugin-transform-optional-chaining": "npm:^7.28.6" + "@babel/plugin-transform-parameters": "npm:^7.27.7" + "@babel/plugin-transform-private-methods": "npm:^7.28.6" + "@babel/plugin-transform-private-property-in-object": "npm:^7.28.6" + "@babel/plugin-transform-property-literals": "npm:^7.27.1" + "@babel/plugin-transform-regenerator": "npm:^7.29.0" + "@babel/plugin-transform-regexp-modifiers": "npm:^7.28.6" + "@babel/plugin-transform-reserved-words": "npm:^7.27.1" + "@babel/plugin-transform-shorthand-properties": "npm:^7.27.1" + "@babel/plugin-transform-spread": "npm:^7.28.6" + "@babel/plugin-transform-sticky-regex": "npm:^7.27.1" + "@babel/plugin-transform-template-literals": "npm:^7.27.1" + "@babel/plugin-transform-typeof-symbol": "npm:^7.27.1" + "@babel/plugin-transform-unicode-escapes": "npm:^7.27.1" + "@babel/plugin-transform-unicode-property-regex": "npm:^7.28.6" + "@babel/plugin-transform-unicode-regex": "npm:^7.27.1" + "@babel/plugin-transform-unicode-sets-regex": "npm:^7.28.6" + "@babel/preset-modules": "npm:0.1.6-no-external-plugins" + babel-plugin-polyfill-corejs2: "npm:^0.4.15" + babel-plugin-polyfill-corejs3: "npm:^0.14.0" + babel-plugin-polyfill-regenerator: "npm:^0.6.6" + core-js-compat: "npm:^3.48.0" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10/2e54630764b6650d81df5ce5a47fa260acd3695dc95a6b989b713bf6c0713fb320e3ae3f76f0c636bfda058ee5c582a3de7f5d58d691c68ca566129c7d3d0f0a + languageName: node + linkType: hard + "@babel/preset-env@npm:^7.29.2, @babel/preset-env@npm:^7.29.3": version: 7.29.3 resolution: "@babel/preset-env@npm:7.29.3" @@ -2006,7 +2101,7 @@ __metadata: languageName: node linkType: hard -"@babel/preset-react@npm:^7.22.15, @babel/preset-react@npm:^7.28.5": +"@babel/preset-react@npm:^7.22.15, @babel/preset-react@npm:^7.24.7, @babel/preset-react@npm:^7.28.5": version: 7.28.5 resolution: "@babel/preset-react@npm:7.28.5" dependencies: @@ -5952,6 +6047,7 @@ __metadata: "@types/plist": "npm:^3.0.5" expo: "npm:^55.0.18" plist: "npm:^3.1.1" + react-native-builder-bob: "npm:^0.40.13" peerDependencies: "@react-native-firebase/app": 24.0.0 expo: ">=47.0.0" @@ -8139,7 +8235,7 @@ __metadata: languageName: node linkType: hard -"arktype@npm:^2.2.0": +"arktype@npm:^2.1.15, arktype@npm:^2.2.0": version: 2.2.0 resolution: "arktype@npm:2.2.0" dependencies: @@ -8204,6 +8300,13 @@ __metadata: languageName: node linkType: hard +"array-union@npm:^2.1.0": + version: 2.1.0 + resolution: "array-union@npm:2.1.0" + checksum: 10/5bee12395cba82da674931df6d0fea23c4aa4660cb3b338ced9f828782a65caa232573e6bf3968f23e0c5eb301764a382cef2f128b170a9dc59de0e36c39f98d + languageName: node + linkType: hard + "array.prototype.findlast@npm:^1.2.5": version: 1.2.5 resolution: "array.prototype.findlast@npm:1.2.5" @@ -8599,7 +8702,7 @@ __metadata: languageName: node linkType: hard -"babel-plugin-syntax-hermes-parser@npm:0.28.1": +"babel-plugin-syntax-hermes-parser@npm:0.28.1, babel-plugin-syntax-hermes-parser@npm:^0.28.0": version: 0.28.1 resolution: "babel-plugin-syntax-hermes-parser@npm:0.28.1" dependencies: @@ -9043,6 +9146,21 @@ __metadata: languageName: node linkType: hard +"browserslist@npm:^4.20.4, browserslist@npm:^4.28.1, browserslist@npm:^4.28.2": + version: 4.28.2 + resolution: "browserslist@npm:4.28.2" + dependencies: + baseline-browser-mapping: "npm:^2.10.12" + caniuse-lite: "npm:^1.0.30001782" + electron-to-chromium: "npm:^1.5.328" + node-releases: "npm:^2.0.36" + update-browserslist-db: "npm:^1.2.3" + bin: + browserslist: cli.js + checksum: 10/cff88386e5b5ba5614c9063bd32ef94865bba22b6a381844c7d09ea1eea62a2247e7106e516abdbfda6b75b9986044c991dfe45f92f10add5ad63dccc07589ec + languageName: node + linkType: hard + "browserslist@npm:^4.24.0, browserslist@npm:^4.25.0, browserslist@npm:^4.28.0": version: 4.28.1 resolution: "browserslist@npm:4.28.1" @@ -9058,21 +9176,6 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.28.1, browserslist@npm:^4.28.2": - version: 4.28.2 - resolution: "browserslist@npm:4.28.2" - dependencies: - baseline-browser-mapping: "npm:^2.10.12" - caniuse-lite: "npm:^1.0.30001782" - electron-to-chromium: "npm:^1.5.328" - node-releases: "npm:^2.0.36" - update-browserslist-db: "npm:^1.2.3" - bin: - browserslist: cli.js - checksum: 10/cff88386e5b5ba5614c9063bd32ef94865bba22b6a381844c7d09ea1eea62a2247e7106e516abdbfda6b75b9986044c991dfe45f92f10add5ad63dccc07589ec - languageName: node - linkType: hard - "bs-logger@npm:^0.2.6": version: 0.2.6 resolution: "bs-logger@npm:0.2.6" @@ -10763,6 +10866,13 @@ __metadata: languageName: node linkType: hard +"dedent@npm:^0.7.0": + version: 0.7.0 + resolution: "dedent@npm:0.7.0" + checksum: 10/87de191050d9a40dd70cad01159a0bcf05ecb59750951242070b6abf9569088684880d00ba92a955b4058804f16eeaf91d604f283929b4f614d181cd7ae633d2 + languageName: node + linkType: hard + "dedent@npm:^1.6.0": version: 1.7.0 resolution: "dedent@npm:1.7.0" @@ -10883,6 +10993,22 @@ __metadata: languageName: node linkType: hard +"del@npm:^6.1.1": + version: 6.1.1 + resolution: "del@npm:6.1.1" + dependencies: + globby: "npm:^11.0.1" + graceful-fs: "npm:^4.2.4" + is-glob: "npm:^4.0.1" + is-path-cwd: "npm:^2.2.0" + is-path-inside: "npm:^3.0.2" + p-map: "npm:^4.0.0" + rimraf: "npm:^3.0.2" + slash: "npm:^3.0.0" + checksum: 10/563288b73b8b19a7261c47fd21a330eeab6e2acd7c6208c49790dfd369127120dd7836cdf0c1eca216b77c94782a81507eac6b4734252d3bef2795cb366996b6 + languageName: node + linkType: hard + "del@npm:^8.0.1": version: 8.0.1 resolution: "del@npm:8.0.1" @@ -11123,6 +11249,15 @@ __metadata: languageName: node linkType: hard +"dir-glob@npm:^3.0.1": + version: 3.0.1 + resolution: "dir-glob@npm:3.0.1" + dependencies: + path-type: "npm:^4.0.0" + checksum: 10/fa05e18324510d7283f55862f3161c6759a3f2f8dbce491a2fc14c8324c498286c54282c1f0e933cb930da8419b30679389499b919122952a4f8592362ef4615 + languageName: node + linkType: hard + "discontinuous-range@npm:1.0.0": version: 1.0.0 resolution: "discontinuous-range@npm:1.0.0" @@ -12416,29 +12551,29 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.3.2": - version: 3.3.2 - resolution: "fast-glob@npm:3.3.2" +"fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.3": + version: 3.3.3 + resolution: "fast-glob@npm:3.3.3" dependencies: "@nodelib/fs.stat": "npm:^2.0.2" "@nodelib/fs.walk": "npm:^1.2.3" glob-parent: "npm:^5.1.2" merge2: "npm:^1.3.0" - micromatch: "npm:^4.0.4" - checksum: 10/222512e9315a0efca1276af9adb2127f02105d7288fa746145bf45e2716383fb79eb983c89601a72a399a56b7c18d38ce70457c5466218c5f13fad957cee16df + micromatch: "npm:^4.0.8" + checksum: 10/dcc6432b269762dd47381d8b8358bf964d8f4f60286ac6aa41c01ade70bda459ff2001b516690b96d5365f68a49242966112b5d5cc9cd82395fa8f9d017c90ad languageName: node linkType: hard -"fast-glob@npm:^3.3.3": - version: 3.3.3 - resolution: "fast-glob@npm:3.3.3" +"fast-glob@npm:^3.3.2": + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" dependencies: "@nodelib/fs.stat": "npm:^2.0.2" "@nodelib/fs.walk": "npm:^1.2.3" glob-parent: "npm:^5.1.2" merge2: "npm:^1.3.0" - micromatch: "npm:^4.0.8" - checksum: 10/dcc6432b269762dd47381d8b8358bf964d8f4f60286ac6aa41c01ade70bda459ff2001b516690b96d5365f68a49242966112b5d5cc9cd82395fa8f9d017c90ad + micromatch: "npm:^4.0.4" + checksum: 10/222512e9315a0efca1276af9adb2127f02105d7288fa746145bf45e2716383fb79eb983c89601a72a399a56b7c18d38ce70457c5466218c5f13fad957cee16df languageName: node linkType: hard @@ -13650,6 +13785,20 @@ __metadata: languageName: node linkType: hard +"globby@npm:^11.0.1": + version: 11.1.0 + resolution: "globby@npm:11.1.0" + dependencies: + array-union: "npm:^2.1.0" + dir-glob: "npm:^3.0.1" + fast-glob: "npm:^3.2.9" + ignore: "npm:^5.2.0" + merge2: "npm:^1.4.1" + slash: "npm:^3.0.0" + checksum: 10/288e95e310227bbe037076ea81b7c2598ccbc3122d87abc6dab39e1eec309aa14f0e366a98cdc45237ffcfcbad3db597778c0068217dcb1950fef6249104e1b1 + languageName: node + linkType: hard + "globby@npm:^14.0.2": version: 14.1.0 resolution: "globby@npm:14.1.0" @@ -14948,7 +15097,7 @@ __metadata: languageName: node linkType: hard -"is-git-dirty@npm:^2.0.2": +"is-git-dirty@npm:^2.0.1, is-git-dirty@npm:^2.0.2": version: 2.0.2 resolution: "is-git-dirty@npm:2.0.2" dependencies: @@ -15056,6 +15205,13 @@ __metadata: languageName: node linkType: hard +"is-path-cwd@npm:^2.2.0": + version: 2.2.0 + resolution: "is-path-cwd@npm:2.2.0" + checksum: 10/46a840921bb8cc0dc7b5b423a14220e7db338072a4495743a8230533ce78812dc152548c86f4b828411fe98c5451959f07cf841c6a19f611e46600bd699e8048 + languageName: node + linkType: hard + "is-path-cwd@npm:^3.0.0": version: 3.0.0 resolution: "is-path-cwd@npm:3.0.0" @@ -16433,7 +16589,7 @@ __metadata: languageName: node linkType: hard -"json5@npm:^2.2.2, json5@npm:^2.2.3": +"json5@npm:^2.2.1, json5@npm:^2.2.2, json5@npm:^2.2.3": version: 2.2.3 resolution: "json5@npm:2.2.3" bin: @@ -16617,7 +16773,7 @@ __metadata: languageName: node linkType: hard -"kleur@npm:^4.1.5": +"kleur@npm:^4.1.4, kleur@npm:^4.1.5": version: 4.1.5 resolution: "kleur@npm:4.1.5" checksum: 10/44d84cc4eedd4311099402ef6d4acd9b2d16e08e499d6ef3bb92389bd4692d7ef09e35248c26e27f98acac532122acb12a1bfee645994ae3af4f0a37996da7df @@ -17726,7 +17882,7 @@ __metadata: languageName: node linkType: hard -"merge2@npm:^1.3.0": +"merge2@npm:^1.3.0, merge2@npm:^1.4.1": version: 1.4.1 resolution: "merge2@npm:1.4.1" checksum: 10/7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2 @@ -20673,7 +20829,7 @@ __metadata: languageName: node linkType: hard -"p-map@npm:4.0.0": +"p-map@npm:4.0.0, p-map@npm:^4.0.0": version: 4.0.0 resolution: "p-map@npm:4.0.0" dependencies: @@ -21161,6 +21317,13 @@ __metadata: languageName: node linkType: hard +"path-type@npm:^4.0.0": + version: 4.0.0 + resolution: "path-type@npm:4.0.0" + checksum: 10/5b1e2daa247062061325b8fdbfd1fb56dde0a448fb1455453276ea18c60685bdad23a445dc148cf87bc216be1573357509b7d4060494a6fd768c7efad833ee45 + languageName: node + linkType: hard + "path-type@npm:^6.0.0": version: 6.0.0 resolution: "path-type@npm:6.0.0" @@ -21976,6 +22139,38 @@ __metadata: languageName: node linkType: hard +"react-native-builder-bob@npm:^0.40.13": + version: 0.40.18 + resolution: "react-native-builder-bob@npm:0.40.18" + dependencies: + "@babel/core": "npm:^7.25.2" + "@babel/plugin-transform-flow-strip-types": "npm:^7.26.5" + "@babel/plugin-transform-strict-mode": "npm:^7.24.7" + "@babel/preset-env": "npm:^7.25.2" + "@babel/preset-react": "npm:^7.24.7" + "@babel/preset-typescript": "npm:^7.24.7" + arktype: "npm:^2.1.15" + babel-plugin-syntax-hermes-parser: "npm:^0.28.0" + browserslist: "npm:^4.20.4" + cross-spawn: "npm:^7.0.3" + dedent: "npm:^0.7.0" + del: "npm:^6.1.1" + escape-string-regexp: "npm:^4.0.0" + fs-extra: "npm:^10.1.0" + glob: "npm:^10.5.0" + is-git-dirty: "npm:^2.0.1" + json5: "npm:^2.2.1" + kleur: "npm:^4.1.4" + prompts: "npm:^2.4.2" + react-native-monorepo-config: "npm:^0.3.3" + which: "npm:^2.0.2" + yargs: "npm:^17.5.1" + bin: + bob: bin/bob + checksum: 10/06eddba046a508dff0aa322c823fa57a280e2ed6a6f586de2114ebc11b6bb7863714eaaff8e93d681bb851fb4f9e792b102541211847f0e546f4e9546df6c3de + languageName: node + linkType: hard + "react-native-builder-bob@npm:^0.41.0": version: 0.41.0 resolution: "react-native-builder-bob@npm:0.41.0" @@ -26230,7 +26425,7 @@ __metadata: languageName: node linkType: hard -"which@npm:^2.0.1": +"which@npm:^2.0.1, which@npm:^2.0.2": version: 2.0.2 resolution: "which@npm:2.0.2" dependencies: @@ -26637,7 +26832,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:17.7.2, yargs@npm:^17.0.0, yargs@npm:^17.6.2, yargs@npm:^17.7.2": +"yargs@npm:17.7.2, yargs@npm:^17.0.0, yargs@npm:^17.5.1, yargs@npm:^17.6.2, yargs@npm:^17.7.2": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: From ecb6b65e48d4bf3e8dea3d1e398688296c2eadfe Mon Sep 17 00:00:00 2001 From: russellwheatley Date: Tue, 12 May 2026 18:03:21 +0100 Subject: [PATCH 45/45] chore: auth remove baseUrl from tsconfig.json --- packages/auth/tsconfig.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/auth/tsconfig.json b/packages/auth/tsconfig.json index 0e79144fc2..5d659d3389 100644 --- a/packages/auth/tsconfig.json +++ b/packages/auth/tsconfig.json @@ -1,7 +1,6 @@ { "extends": "../../tsconfig.packages.base.json", "compilerOptions": { - "baseUrl": ".", "rootDir": ".", "paths": { "@react-native-firebase/app/dist/module/common/*": ["../app/dist/typescript/lib/common/*"],