From 357094e4b7504165081ffda0c4105569480f5b79 Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Fri, 11 Nov 2022 20:45:15 -0500 Subject: [PATCH] fix(auth, multifactor): put multiFactor and getMultiFactorResolver on auth() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this resolves some fidelity issues with the firebase-js-sdk API this is non-breaking, the previous style from original implementation is still valid, but it will emit a warning now. Types and docs are updated Co-authored-by: Ferenc Züllich --- docs/auth/multi-factor-auth.md | 6 +++--- packages/auth/e2e/helpers.js | 4 ++-- packages/auth/e2e/multiFactor.e2e.js | 28 ++++++++++++++-------------- packages/auth/lib/index.d.ts | 13 +++++++++++++ packages/auth/lib/index.js | 13 ++++++++++++- packages/auth/lib/multiFactor.js | 11 ++++++++--- 6 files changed, 52 insertions(+), 23 deletions(-) diff --git a/docs/auth/multi-factor-auth.md b/docs/auth/multi-factor-auth.md index 8c750c4e44..efc94a7418 100644 --- a/docs/auth/multi-factor-auth.md +++ b/docs/auth/multi-factor-auth.md @@ -22,7 +22,7 @@ operations: ```js import auth from '@react-native-firebase/auth'; -const multiFactorUser = await auth.multiFactor(auth()); +const multiFactorUser = await auth().multiFactor(auth().currentUser); ``` Request the session identifier and use the phone number obtained from the user @@ -81,7 +81,7 @@ Using the error object you can obtain a continue the flow: ```js -const resolver = auth.getMultiFactorResolver(auth(), error); +const resolver = auth().getMultiFactorResolver(error); ``` The resolver object has all the required information to prompt the user for a @@ -143,7 +143,7 @@ authInstance const { code } = error; // Make sure to check if multi factor authentication is required if (code !== 'auth/multi-factor-auth-required') { - const resolver = auth.getMultiFactorResolver(authInstance, error); + const resolver = auth.getMultiFactorResolver(error); if (resolver.hints.length > 1) { // Use resolver.hints to display a list of second factors to the user diff --git a/packages/auth/e2e/helpers.js b/packages/auth/e2e/helpers.js index a9a103d095..74a6f064fe 100644 --- a/packages/auth/e2e/helpers.js +++ b/packages/auth/e2e/helpers.js @@ -212,7 +212,7 @@ exports.createUserWithMultiFactor = async function createUserWithMultiFactor() { const email = 'verified@example.com'; const password = 'test123'; await createVerifiedUser(email, password); - const multiFactorUser = await firebase.auth.multiFactor(firebase.auth()); + const multiFactorUser = await firebase.auth().multiFactor(firebase.auth().currentUser); const session = await multiFactorUser.getSession(); const phoneNumber = getRandomPhoneNumber(); const verificationId = await firebase @@ -242,7 +242,7 @@ exports.signInUserWithMultiFactor = async function signInUserWithMultiFactor( e.message.should.equal( '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', ); - const resolver = firebase.auth.getMultiFactorResolver(firebase.auth(), e); + const resolver = firebase.auth().getMultiFactorResolver(e); let verificationId = await firebase .auth() .verifyPhoneNumberWithMultiFactorInfo(resolver.hints[0], resolver.session); diff --git a/packages/auth/e2e/multiFactor.e2e.js b/packages/auth/e2e/multiFactor.e2e.js index 8b50acfa4a..ceae3f738c 100644 --- a/packages/auth/e2e/multiFactor.e2e.js +++ b/packages/auth/e2e/multiFactor.e2e.js @@ -41,7 +41,7 @@ describe('multi-factor', function () { e.message.should.equal( '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', ); - const resolver = firebase.auth.getMultiFactorResolver(firebase.auth(), e); + const resolver = firebase.auth().getMultiFactorResolver(e); resolver.should.be.an.Object(); resolver.hints.should.be.an.Array(); resolver.hints.length.should.equal(1); @@ -93,7 +93,7 @@ describe('multi-factor', function () { e.message.should.equal( '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', ); - const resolver = firebase.auth.getMultiFactorResolver(firebase.auth(), e); + const resolver = firebase.auth().getMultiFactorResolver(e); const verificationId = await firebase .auth() .verifyPhoneNumberWithMultiFactorInfo(resolver.hints[0], resolver.session); @@ -137,7 +137,7 @@ describe('multi-factor', function () { e.message.should.equal( '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', ); - const resolver = firebase.auth.getMultiFactorResolver(firebase.auth(), e); + const resolver = firebase.auth().getMultiFactorResolver(e); await firebase .auth() .verifyPhoneNumberWithMultiFactorInfo(resolver.hints[0], resolver.session); @@ -169,7 +169,7 @@ describe('multi-factor', function () { e.message.should.equal( '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', ); - const resolver = firebase.auth.getMultiFactorResolver(firebase.auth(), e); + const resolver = firebase.auth().getMultiFactorResolver(e); const unknownFactor = { uid: 'notknown', }; @@ -199,7 +199,7 @@ describe('multi-factor', function () { await firebase.auth().signInWithEmailAndPassword(TEST_EMAIL, TEST_PASS); try { - const multiFactorUser = await firebase.auth.multiFactor(firebase.auth()); + const multiFactorUser = await firebase.auth().multiFactor(firebase.auth().currentUser); const session = await multiFactorUser.getSession(); await firebase .auth() @@ -223,7 +223,7 @@ describe('multi-factor', function () { const phoneNumber = getRandomPhoneNumber(); should.deepEqual(firebase.auth().currentUser.multiFactor.enrolledFactors, []); - const multiFactorUser = await firebase.auth.multiFactor(firebase.auth()); + const multiFactorUser = await firebase.auth().multiFactor(firebase.auth().currentUser); const session = await multiFactorUser.getSession(); @@ -256,7 +256,7 @@ describe('multi-factor', function () { const phoneNumber = getRandomPhoneNumber(); should.deepEqual(firebase.auth().currentUser.multiFactor.enrolledFactors, []); - const multiFactorUser = await firebase.auth.multiFactor(firebase.auth()); + const multiFactorUser = await firebase.auth().multiFactor(firebase.auth().currentUser); const session = await multiFactorUser.getSession(); @@ -285,7 +285,7 @@ describe('multi-factor', function () { await signInUserWithMultiFactor(email, password, phoneNumber); const anotherNumber = getRandomPhoneNumber(); - const multiFactorUser = await firebase.auth.multiFactor(firebase.auth()); + const multiFactorUser = await firebase.auth().multiFactor(firebase.auth().currentUser); const session = await multiFactorUser.getSession(); const verificationId = await firebase @@ -318,7 +318,7 @@ describe('multi-factor', function () { await clearAllUsers(); const { email, password, phoneNumber } = await createUserWithMultiFactor(); await signInUserWithMultiFactor(email, password, phoneNumber); - const multiFactorUser = await firebase.auth.multiFactor(firebase.auth()); + const multiFactorUser = await firebase.auth().multiFactor(firebase.auth().currentUser); const session = await multiFactorUser.getSession(); const verificationId = await firebase @@ -355,7 +355,7 @@ describe('multi-factor', function () { e.message.should.equal( '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', ); - resolver = firebase.auth.getMultiFactorResolver(firebase.auth(), e); + resolver = firebase.auth().getMultiFactorResolver(e); } await firebase .auth() @@ -392,7 +392,7 @@ describe('multi-factor', function () { e.message.should.equal( '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', ); - resolver = firebase.auth.getMultiFactorResolver(firebase.auth(), e); + resolver = firebase.auth().getMultiFactorResolver(e); } try { @@ -420,7 +420,7 @@ describe('multi-factor', function () { e.message.should.equal( '[auth/multi-factor-auth-required] Please complete a second factor challenge to finish signing into this account.', ); - resolver = firebase.auth.getMultiFactorResolver(firebase.auth(), e); + resolver = firebase.auth().getMultiFactorResolver(e); } const verificationId = await firebase .auth() @@ -461,7 +461,7 @@ describe('multi-factor', function () { await confirmResult.confirm(lastSmsCode); // WHEN they attempt to enroll a second factor - const multiFactorUser = await firebase.auth.multiFactor(firebase.auth()); + const multiFactorUser = await firebase.auth().multiFactor(firebase.auth().currentUser); const session = await multiFactorUser.getSession(); try { await firebase.auth().verifyPhoneNumberForMultiFactor({ phoneNumber: '+1123123', session }); @@ -477,7 +477,7 @@ describe('multi-factor', function () { }); it('can not enroll when phone number is missing + sign', async function () { await createVerifiedUser('verified@example.com', 'test123'); - const multiFactorUser = firebase.auth.multiFactor(firebase.auth()); + const multiFactorUser = firebase.auth().multiFactor(firebase.auth().currentUser); const session = await multiFactorUser.getSession(); try { await firebase.auth().verifyPhoneNumberForMultiFactor({ phoneNumber: '491575', session }); diff --git a/packages/auth/lib/index.d.ts b/packages/auth/lib/index.d.ts index 40dac39eaf..ab41d09a00 100644 --- a/packages/auth/lib/index.d.ts +++ b/packages/auth/lib/index.d.ts @@ -1871,6 +1871,19 @@ export namespace FirebaseAuthTypes { * @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; } } diff --git a/packages/auth/lib/index.js b/packages/auth/lib/index.js index 79d67767ab..ea45f05d7f 100644 --- a/packages/auth/lib/index.js +++ b/packages/auth/lib/index.js @@ -42,7 +42,7 @@ import Settings from './Settings'; import User from './User'; import version from './version'; import { getMultiFactorResolver } from './getMultiFactorResolver'; -import { multiFactor } from './multiFactor'; +import { multiFactor, MultiFactorUser } from './multiFactor'; const statics = { AppleAuthProvider, @@ -414,6 +414,17 @@ class FirebaseAuthModule extends FirebaseModule { 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); + } } // import { SDK_VERSION } from '@react-native-firebase/auth'; diff --git a/packages/auth/lib/multiFactor.js b/packages/auth/lib/multiFactor.js index 3b5cae8325..889f01b617 100644 --- a/packages/auth/lib/multiFactor.js +++ b/packages/auth/lib/multiFactor.js @@ -2,14 +2,19 @@ * Return a MultiFactorUser instance the gateway to multi-factor operations. */ export function multiFactor(auth) { + // eslint-disable-next-line no-console + console.warn('This method is deprecated. Please use auth().multiFactor(user) instead'); return new MultiFactorUser(auth); } export class MultiFactorUser { - constructor(auth) { + constructor(auth, user) { this._auth = auth; - this._user = auth.currentUser; - this.enrolledFactor = auth.currentUser.multiFactor.enrolledFactors; + if (user === undefined) { + user = auth.currentUser; + } + this._user = user; + this.enrolledFactor = user.multiFactor.enrolledFactors; } getSession() {