Skip to content

Commit 610024b

Browse files
committed
test(auth, ios): enable phone MFA test, w/firebase-tools patch
on iOS they attempt to verify a masked number for 2FA not an unmasked one - works fine against cloud auth, so it is an emulator-specific issue - in emulator you can fix it with a patch that looks for unobfuscated *or* obfuscated verification See firebase/firebase-tools#9062
1 parent b77cdd5 commit 610024b

File tree

2 files changed

+61
-3
lines changed

2 files changed

+61
-3
lines changed

packages/auth/e2e/multiFactor.e2e.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -556,9 +556,11 @@ describe('multi-factor modular', function () {
556556

557557
describe('sign-in', function () {
558558
it('requires multi-factor auth when enrolled', async function () {
559-
if (Platform.ios) {
560-
this.skip();
561-
}
559+
// iOS receives:
560+
// NativeFirebaseError: [auth/unknown] MFA_ENROLLMENT_NOT_FOUND
561+
// if (device.getPlatform() === 'ios') {
562+
// this.skip();
563+
// }
562564
const { phoneNumber, email, password } = await createUserWithMultiFactor();
563565
const maskedNumber = '+********' + phoneNumber.substring(phoneNumber.length - 4);
564566

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
diff --git a/node_modules/firebase-tools/lib/emulator/auth/operations.js b/node_modules/firebase-tools/lib/emulator/auth/operations.js
2+
index 2104c80..c42d2f5 100644
3+
--- a/node_modules/firebase-tools/lib/emulator/auth/operations.js
4+
+++ b/node_modules/firebase-tools/lib/emulator/auth/operations.js
5+
@@ -721,6 +721,7 @@ function sendVerificationCode(state, reqBody) {
6+
(0, errors_1.assert)(state instanceof state_1.AgentProjectState, "UNSUPPORTED_TENANT_OPERATION");
7+
(0, errors_1.assert)(reqBody.phoneNumber && (0, utils_1.isValidPhoneNumber)(reqBody.phoneNumber), "INVALID_PHONE_NUMBER : Invalid format.");
8+
const user = state.getUserByPhoneNumber(reqBody.phoneNumber);
9+
+ console.log('getting user by ' + reqBody.phoneNumber + ', got ' + JSON.stringify(user));
10+
(0, errors_1.assert)(!((_a = user === null || user === void 0 ? void 0 : user.mfaInfo) === null || _a === void 0 ? void 0 : _a.length), "UNSUPPORTED_FIRST_FACTOR : A phone number cannot be set as a first factor on an SMS based MFA user.");
11+
const { sessionInfo, phoneNumber, code } = state.createVerificationCode(reqBody.phoneNumber);
12+
emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.AUTH).log("BULLET", `To verify the phone number ${phoneNumber}, use the code ${code}.`);
13+
@@ -1485,6 +1486,7 @@ function mfaSignInStart(state, reqBody) {
14+
(0, errors_1.assert)(reqBody.mfaPendingCredential, "MISSING_MFA_PENDING_CREDENTIAL : Request does not have MFA pending credential.");
15+
(0, errors_1.assert)(reqBody.mfaEnrollmentId, "MISSING_MFA_ENROLLMENT_ID : No second factor identifier is provided.");
16+
const { user } = parsePendingCredential(state, reqBody.mfaPendingCredential);
17+
+ console.log('in mfaSignInStart?')
18+
const enrollment = (_b = user.mfaInfo) === null || _b === void 0 ? void 0 : _b.find((factor) => factor.mfaEnrollmentId === reqBody.mfaEnrollmentId);
19+
(0, errors_1.assert)(enrollment, "MFA_ENROLLMENT_NOT_FOUND");
20+
const phoneNumber = enrollment.unobfuscatedPhoneInfo;
21+
@@ -1511,8 +1513,9 @@ async function mfaSignInFinalize(state, reqBody) {
22+
(0, errors_1.assert)(code, "MISSING_CODE");
23+
(0, errors_1.assert)(sessionInfo, "MISSING_SESSION_INFO");
24+
const phoneNumber = verifyPhoneNumber(state, sessionInfo, code);
25+
+ console.error('phoneNumber is ' + phoneNumber);
26+
let { user, signInProvider } = parsePendingCredential(state, reqBody.mfaPendingCredential);
27+
- const enrollment = (_b = user.mfaInfo) === null || _b === void 0 ? void 0 : _b.find((enrollment) => enrollment.unobfuscatedPhoneInfo === phoneNumber);
28+
+ const enrollment = (_b = user.mfaInfo) === null || _b === void 0 ? void 0 : _b.find((enrollment) => { console.log('searching, enrollment is ' + JSON.stringify(enrollment)); return enrollment.unobfuscatedPhoneInfo === phoneNumber || ('+********' + enrollment.unobfuscatedPhoneInfo.substring(enrollment.unobfuscatedPhoneInfo.length - 4)) === phoneNumber; });
29+
const { updates, extraClaims } = await fetchBlockingFunction(state, state_1.BlockingFunctionEvents.BEFORE_SIGN_IN, user, { signInMethod: signInProvider, signInSecondFactor: "phone" });
30+
user = state.updateUserByLocalId(user.localId, Object.assign(Object.assign({}, updates), { lastLoginAt: Date.now().toString() }));
31+
(0, errors_1.assert)(enrollment && enrollment.mfaEnrollmentId, "MFA_ENROLLMENT_NOT_FOUND");
32+
@@ -1657,6 +1660,7 @@ function verifyPhoneNumber(state, sessionInfo, code) {
33+
(0, errors_1.assert)(verification, "INVALID_SESSION_INFO");
34+
(0, errors_1.assert)(verification.code === code, "INVALID_CODE");
35+
state.deleteVerificationCodeBySessionInfo(sessionInfo);
36+
+ console.log('verifyPhoneNumber verification is ' + JSON.stringify(verification));
37+
return verification.phoneNumber;
38+
}
39+
const CUSTOM_ATTRIBUTES_MAX_LENGTH = 1000;
40+
diff --git a/node_modules/firebase-tools/lib/emulator/auth/state.js b/node_modules/firebase-tools/lib/emulator/auth/state.js
41+
index 204ead8..99425c7 100644
42+
--- a/node_modules/firebase-tools/lib/emulator/auth/state.js
43+
+++ b/node_modules/firebase-tools/lib/emulator/auth/state.js
44+
@@ -328,10 +328,12 @@ class ProjectState {
45+
phoneNumber,
46+
sessionInfo,
47+
};
48+
+ console.log('creating verification code for ' + phoneNumber + ': ' + JSON.stringify(verification));
49+
this.verificationCodes.set(sessionInfo, verification);
50+
return verification;
51+
}
52+
getVerificationCodeBySessionInfo(sessionInfo) {
53+
+ console.log('getVerificationCodesBySessionInfo returning ' + JSON.stringify(this.verificationCodes.get(sessionInfo)));
54+
return this.verificationCodes.get(sessionInfo);
55+
}
56+
deleteVerificationCodeBySessionInfo(sessionInfo) {

0 commit comments

Comments
 (0)