feat(auth)!: decouple SMS multi-factor configuration from the phone sign-in provider - #2483
Conversation
There was a problem hiding this comment.
Code Review
This pull request removes the unused smsCodeLength property and introduces allowedCountries to MfaConfiguration to restrict country selection during SMS multi-factor authentication (MFA) enrollment, decoupling it from the phone sign-in provider. It also updates the relevant UI components and adds comprehensive unit and E2E tests to verify the SMS MFA enrollment and challenge flows. The review feedback suggests optimizing performance in MfaEnrollmentDefaults.kt and PhoneAuthScreen.kt by wrapping the allowedCountries set conversions and provider filtering in remember blocks to prevent unnecessary allocations during recompositions.
e509900 to
9ad6e6e
Compare
russellwheatley
left a comment
There was a problem hiding this comment.
The crash fix and the MFA/phone split are right. Requesting changes because the custom-host path can still open on a country the selector will not offer.
FirebaseAuthScreen now passes mfaConfiguration.allowedCountries into rememberMfaEnrollmentFlowState. Anyone driving MfaEnrollmentScreen themselves, including the README example, still calls rememberMfaEnrollmentFlowState() with the default null. The picker is filtered. Send uses selectedCountry.value.dialCode with no check. Same mismatch the fifth commit fixed for the high-level screen.
I'd reconcile inside MfaEnrollmentScreen so forgetting the second argument cannot bring this back. At minimum, pass the same list in the README example, and add a test that the pre-selected dial code is one of the allowed countries. initialEnrollmentCountry has none.
The old rememberMfaEnrollmentFlowState KDoc is now sitting above initialEnrollmentCountry. Move it back.
Android CI is green on this HEAD. e2e last ran on an older SHA, so worth re-triggering that job. Gemini's remember comments are already done.
9ad6e6e to
dead5e9
Compare
The SMS enrolment step read its country restriction off the hosting configuration's
AuthProvider.Phone, andEnterPhoneNumberUItook.first()of that list, so opening SMS enrolment from a configuration without a phone provider crashed withNoSuchElementException. That is the ordinary case rather than an edge case — Firebase enables SMS second factors separately from phone sign-in, and phone sign-in cannot carry a second factor at all.The restriction now comes from
MfaConfiguration.allowedCountriesandEnterPhoneNumberUItakes it as a parameter, so the step no longer resolves a provider at all. That option takes ISO 3166-1 alpha-2 codes and validates them — a dial code throws rather than silently restricting the selector to nothing — and the step opens on a permitted country instead of the device's own when the two disagree.AuthProvider.Phone.allowedCountriesis unchanged and still drives phone sign-in.AuthProvider.Phone.smsCodeLengthis removed — nothing read it, both flows validate against a hardcoded 6, and Firebase exposes no SMS code length setting for it to mirror.Also adds the first genuine end-to-end MFA coverage:
MfaSmsFlowTestenrols an SMS factor and completes an MFA challenge against the Auth emulator, asserting onuser.multiFactor.enrolledFactorsandAuthState.Successrather than on screen state. The emulator supports SMS MFA in full — the two mocked MFA test files claimed it could not, and are corrected, TOTP's exact failure included.MfaEnrollmentSmsStepTestcovers the crash, verified failing on the old code.AuthProvider.Phone.smsCodeLengthis removed. Nothing read it, so nothing behaves differently without it.EnterPhoneNumberUIgained a requiredallowedCountriesparameter and no longer resolves a phone provider from the configuration. Callers stop compiling until they supply it, deliberately: with a default, a host driving this step from a customphoneAuthContentwould have silently lost the restriction it used to get implicitly. Derive it from your own provider —configuration.providers.filterIsInstance<AuthProvider.Phone>().firstOrNull()?.allowedCountries?.toSet()— or passnullfor no restriction.Usage
Maintainer note: Fixes internal CPRN-423