Skip to content

feat(auth)!: decouple SMS multi-factor configuration from the phone sign-in provider - #2483

Merged
russellwheatley merged 6 commits into
version-10.0.0-beta05from
feat/decouple-sms-mfa-from-phone-provider
Sep 8, 2026
Merged

feat(auth)!: decouple SMS multi-factor configuration from the phone sign-in provider#2483
russellwheatley merged 6 commits into
version-10.0.0-beta05from
feat/decouple-sms-mfa-from-phone-provider

Conversation

@demolaf

@demolaf demolaf commented Sep 6, 2026

Copy link
Copy Markdown
Member

The SMS enrolment step read its country restriction off the hosting configuration's AuthProvider.Phone, and EnterPhoneNumberUI took .first() of that list, so opening SMS enrolment from a configuration without a phone provider crashed with NoSuchElementException. 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.allowedCountries and EnterPhoneNumberUI takes 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.allowedCountries is unchanged and still drives phone sign-in. AuthProvider.Phone.smsCodeLength is 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: MfaSmsFlowTest enrols an SMS factor and completes an MFA challenge against the Auth emulator, asserting on user.multiFactor.enrolledFactors and AuthState.Success rather 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. MfaEnrollmentSmsStepTest covers the crash, verified failing on the old code.

⚠️ Breaking Changes

  • AuthProvider.Phone.smsCodeLength is removed. Nothing read it, so nothing behaves differently without it.
  • EnterPhoneNumberUI gained a required allowedCountries parameter 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 custom phoneAuthContent would 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 pass null for no restriction.

Usage

FirebaseAuthScreen(
    configuration = configuration,
    mfaConfiguration = MfaConfiguration(
        allowedFactors = listOf(MfaFactor.Sms),
        allowedCountries = listOf("GB", "IE"),
    ),
    onSignInSuccess = { },
    onSignInFailure = { },
    onSignInCancelled = { },
)

Maintainer note: Fixes internal CPRN-423

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread auth/src/main/java/com/firebase/ui/auth/ui/screens/mfa/MfaEnrollmentDefaults.kt Outdated
Comment thread auth/src/main/java/com/firebase/ui/auth/ui/screens/phone/PhoneAuthScreen.kt Outdated
@demolaf
demolaf marked this pull request as ready for review September 7, 2026 12:35
@demolaf
demolaf force-pushed the feat/decouple-sms-mfa-from-phone-provider branch from e509900 to 9ad6e6e Compare September 7, 2026 15:12
@demolaf
demolaf changed the base branch from refactor/reauth-remove-shared-flow-coupling to version-10.0.0-beta05 September 7, 2026 15:12

@russellwheatley russellwheatley left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread auth/README.md
@demolaf
demolaf force-pushed the feat/decouple-sms-mfa-from-phone-provider branch from 9ad6e6e to dead5e9 Compare September 7, 2026 16:04
@russellwheatley
russellwheatley merged commit ba697de into version-10.0.0-beta05 Sep 8, 2026
9 checks passed
@russellwheatley
russellwheatley deleted the feat/decouple-sms-mfa-from-phone-provider branch September 8, 2026 08:15
@github-project-automation github-project-automation Bot moved this from Backlog to Done in studio-2394994192-60a69 Sep 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants