Aggiungere l'autenticazione a più fattori all'app Flutter

Se hai eseguito l'upgrade a Firebase Authentication con Identity Platform, puoi aggiungere l'autenticazione a più fattori tramite SMS alla tua app Flutter.

L'autenticazione a più fattori (MFA) aumenta la sicurezza della tua app. Mentre gli utenti malintenzionati spesso compromettono password e account social, intercettare un messaggio di testo è più difficile.

Prima di iniziare

  1. Attiva almeno un provider che supporti l'autenticazione a più fattori. Tutti i provider supportano l'autenticazione a più fattori, ad eccezione dell'autenticazione telefonica, dell'autenticazione anonima e di Apple Game Center.

  2. Assicurati che la tua app verifichi le email degli utenti. L'autenticazione a più fattori richiede la verifica dell'email. In questo modo, gli utenti malintenzionati non possono registrarsi a un servizio con un'email di cui non sono proprietari e poi bloccare il vero proprietario aggiungendo un secondo fattore.

    • iOS+: in Xcode, attiva le notifiche push per il tuo progetto e assicurati che la chiave di autenticazione APNs sia configurata con Firebase Cloud Messaging (FCM).

      Inoltre, devi attivare le modalità di background per le notifiche remote. Per una spiegazione dettagliata, consulta la documentazione di Firebase iOS Phone Auth.

    • Android: se non l'hai già fatto, specifica la fingerprint SHA-256 della tua app:

      1. Nella console Firebase, vai alla scheda Impostazioni > Generale.

      2. Scorri verso il basso fino alla scheda Le tue app , seleziona la tua app per Android e aggiungi la fingerprint SHA-256 nel campo Fingerprint del certificato SHA.

      Per informazioni dettagliate su come ottenere la fingerprint SHA della tua app, consulta Autenticare il client.

    • Web: se non l'hai già fatto, autorizza il dominio della tua app:

      1. Nella console Firebase, vai alla scheda Sicurezza> Autenticazione > Impostazioni.

      2. Nella sezione Domini autorizzati , fai clic su Aggiungi dominio e aggiungi il tuo dominio.

Attivare l'autenticazione a più fattori

  1. Nella console Firebase, vai a Sicurezza > Autenticazione.

  2. Nella scheda Metodo di accesso, nella sezione Avanzate, attiva Autenticazione a più fattori tramite SMS.

    Dovresti anche inserire i numeri di telefono con cui testerai la tua app. Sebbene sia facoltativo, ti consigliamo vivamente di registrare i numeri di telefono per i test al fine di evitare limitazioni durante lo sviluppo.

  3. Se non l'hai già fatto, autorizza il dominio della tua app:

    1. Nella console Firebase, vai alla scheda Sicurezza > Autenticazione > Impostazioni.

    2. Nella sezione Domini autorizzati , fai clic su Aggiungi dominio e aggiungi il tuo dominio.

Scegliere un pattern di registrazione

Puoi scegliere se la tua app richiede l'autenticazione a più fattori e come e quando registrare i tuoi utenti. Alcuni pattern comuni includono:

  • Registra il secondo fattore dell'utente come parte della registrazione. Utilizza questo metodo se la tua app richiede l'autenticazione a più fattori per tutti gli utenti.

  • Offri un'opzione ignorabile per registrare un secondo fattore durante la registrazione. Le app che vogliono incoraggiare, ma non richiedere, l'autenticazione a più fattori potrebbero preferire questo approccio.

  • Consenti di aggiungere un secondo fattore dalla pagina di gestione dell'account o del profilo dell'utente, anziché dalla schermata di registrazione. In questo modo si riduce al minimo l'attrito durante la procedura di registrazione, pur rendendo disponibile l'autenticazione a più fattori per gli utenti sensibili alla sicurezza.

  • Richiedi l'aggiunta di un secondo fattore in modo incrementale quando l'utente vuole accedere a funzionalità con requisiti di sicurezza maggiori.

Registrare un secondo fattore

Per registrare un nuovo fattore secondario per un utente:

  1. Esegui di nuovo l'autenticazione dell'utente.

  2. Chiedi all'utente di inserire il suo numero di telefono.

  3. Ottieni una sessione a più fattori per l'utente:

    final multiFactorSession = await user.multiFactor.getSession();
    
  4. Verifica il numero di telefono con una sessione a più fattori e i tuoi callback:

    await FirebaseAuth.instance.verifyPhoneNumber(
      multiFactorSession: multiFactorSession,
      phoneNumber: phoneNumber,
      verificationCompleted: (_) {},
      verificationFailed: (_) {},
      codeSent: (String verificationId, int? resendToken) async {
        // The SMS verification code has been sent to the provided phone number.
        // ...
      },
      codeAutoRetrievalTimeout: (_) {},
    );
    
  5. Una volta inviato il codice SMS, chiedi all'utente di verificarlo:

    final credential = PhoneAuthProvider.credential(
      verificationId: verificationId,
      smsCode: smsCode,
    );
    
  6. Completa la registrazione:

    await user.multiFactor.enroll(
      PhoneMultiFactorGenerator.getAssertion(
        credential,
      ),
    );
    

Il codice riportato di seguito mostra un esempio completo di registrazione di un secondo fattore:

  final session = await user.multiFactor.getSession();
  final auth = FirebaseAuth.instance;
  await auth.verifyPhoneNumber(
    multiFactorSession: session,
    phoneNumber: phoneController.text,
    verificationCompleted: (_) {},
    verificationFailed: (_) {},
    codeSent: (String verificationId, int? resendToken) async {
      // See `firebase_auth` example app for a method of retrieving user's sms code:
      // https://github.com/firebase/flutterfire/blob/main/packages/firebase_auth/firebase_auth/example/lib/auth.dart#L591
      final smsCode = await getSmsCodeFromUser(context);

      if (smsCode != null) {
        // Create a PhoneAuthCredential with the code
        final credential = PhoneAuthProvider.credential(
          verificationId: verificationId,
          smsCode: smsCode,
        );

        try {
          await user.multiFactor.enroll(
            PhoneMultiFactorGenerator.getAssertion(
              credential,
            ),
          );
        } on FirebaseAuthException catch (e) {
          print(e.message);
        }
      }
    },
    codeAutoRetrievalTimeout: (_) {},
  );

Complimenti! Hai registrato correttamente un secondo fattore di autenticazione per un utente.

Accedere degli utenti con un secondo fattore

Per accedere a un utente con la verifica SMS a due fattori:

  1. Accedi all'utente con il suo primo fattore, quindi intercetta l'eccezione FirebaseAuthMultiFactorException. Questo errore contiene un resolver, che puoi utilizzare per ottenere i secondi fattori registrati dell'utente. Contiene anche una sessione sottostante che dimostra che l'utente ha eseguito l'autenticazione correttamente con il suo primo fattore.

    Ad esempio, se il primo fattore dell'utente era un'email e una password:

    try {
      await _auth.signInWithEmailAndPassword(
          email: emailController.text,
          password: passwordController.text,
      );
      // User is not enrolled with a second factor and is successfully
      // signed in.
      // ...
    } on FirebaseAuthMultiFactorException catch (e) {
      // The user is a multi-factor user. Second factor challenge is required
      final resolver = e.resolver
      // ...
    }
    
  2. Se l'utente ha registrato più fattori secondari, chiedigli quale utilizzare:

    final session = e.resolver.session;
    
    final hint = e.resolver.hints[selectedHint];
    
  3. Invia un messaggio di verifica al telefono dell'utente con il suggerimento e la sessione a più fattori:

    await FirebaseAuth.instance.verifyPhoneNumber(
      multiFactorSession: session,
      multiFactorInfo: hint,
      verificationCompleted: (_) {},
      verificationFailed: (_) {},
      codeSent: (String verificationId, int? resendToken) async {
        // ...
      },
      codeAutoRetrievalTimeout: (_) {},
    );
    
  4. Chiama resolver.resolveSignIn() per completare l'autenticazione secondaria:

    final smsCode = await getSmsCodeFromUser(context);
    if (smsCode != null) {
      // Create a PhoneAuthCredential with the code
      final credential = PhoneAuthProvider.credential(
        verificationId: verificationId,
        smsCode: smsCode,
      );
    
      try {
        await e.resolver.resolveSignIn(
          PhoneMultiFactorGenerator.getAssertion(credential)
        );
      } on FirebaseAuthException catch (e) {
        print(e.message);
      }
    }
    

Il codice riportato di seguito mostra un esempio completo di accesso di un utente con autenticazione a più fattori:

try {
  await _auth.signInWithEmailAndPassword(
    email: emailController.text,
    password: passwordController.text,
  );
} on FirebaseAuthMultiFactorException catch (e) {
  setState(() {
    error = '${e.message}';
  });
  final firstHint = e.resolver.hints.first;
  if (firstHint is! PhoneMultiFactorInfo) {
    return;
  }
  await FirebaseAuth.instance.verifyPhoneNumber(
    multiFactorSession: e.resolver.session,
    multiFactorInfo: firstHint,
    verificationCompleted: (_) {},
    verificationFailed: (_) {},
    codeSent: (String verificationId, int? resendToken) async {
      // See `firebase_auth` example app for a method of retrieving user's sms code:
      // https://github.com/firebase/flutterfire/blob/main/packages/firebase_auth/firebase_auth/example/lib/auth.dart#L591
      final smsCode = await getSmsCodeFromUser(context);

      if (smsCode != null) {
        // Create a PhoneAuthCredential with the code
        final credential = PhoneAuthProvider.credential(
          verificationId: verificationId,
          smsCode: smsCode,
        );

        try {
          await e.resolver.resolveSignIn(
            PhoneMultiFactorGenerator.getAssertion(
              credential,
            ),
          );
        } on FirebaseAuthException catch (e) {
          print(e.message);
        }
      }
    },
    codeAutoRetrievalTimeout: (_) {},
  );
} catch (e) {
  ...
}

Complimenti! Hai eseguito l'accesso a un utente utilizzando l'autenticazione a più fattori.

Passaggi successivi