Autenticazione con Firebase utilizzando i link email

Puoi utilizzare Firebase Authentication per far accedere un utente inviandogli un'email contenente un link su cui può fare clic per accedere. Durante la procedura, viene verificato anche l'indirizzo email dell'utente.

L'accesso via email offre numerosi vantaggi:

  • Registrazione e accesso semplici.
  • Minore rischio di riutilizzo delle password nelle applicazioni, con un conseguente rischio di compromissione della sicurezza anche di password ben selezionate.
  • La possibilità di autenticare un utente e di verificare al contempo che sia il proprietario legittimo di un indirizzo email.
  • Per accedere, un utente ha bisogno solo di un account email accessibile. Non è richiesta la proprietà di un numero di telefono o di un account di social media.
  • Un utente può accedere in sicurezza senza dover fornire (o ricordare) una password, il che può essere complicato su un dispositivo mobile.
  • Per un utente esistente che in precedenza ha eseguito l'accesso con un identificatore email (password o federato), è possibile eseguire l'upgrade in modo che possa accedere solo con l'email. Ad esempio, un utente che ha dimenticato la password può comunque accedere senza doverla reimpostare.

Prima di iniziare

  1. Se non lo hai già fatto, segui i passaggi nella Guida introduttiva.

  2. Abilita l'accesso tramite link email per il tuo progetto Firebase.

    Per consentire agli utenti di accedere tramite link email, devi prima attivare il fornitore di email e il metodo di accesso tramite link email per il tuo progetto Firebase:

    1. Nella Console Firebase, apri la sezione Auth.
    2. Nella scheda Metodo di accesso, attiva il provider Email/Password. Tieni presente che l'accesso con email/password deve essere abilitato per utilizzare l'accesso tramite link via email.
    3. Nella stessa sezione, attiva il metodo di accesso Link via email (accesso senza password).
    4. Fai clic su Salva.

Per avviare il flusso di autenticazione, presenta un'interfaccia che chieda all'utente di fornire il proprio indirizzo email e poi chiama sendSignInLinkToEmail() per richiedere a Firebase di inviare il link di autenticazione all'indirizzo email dell'utente.

  1. Crea l'oggetto ActionCodeSettings, che fornisce a Firebase le istruzioni su come creare il link email. Imposta i seguenti campi:

    • url: il link diretto da incorporare ed eventuali altri stati da trasmettere. Il dominio del link deve essere inserito nella lista consentita nell'elenco dei domini autorizzati della console Firebase, che puoi trovare nella scheda Metodo di accesso (Autenticazione -> Metodo di accesso). Il link reindirizzerà l'utente a questo URL se l'app non è installata sul dispositivo e non è stato possibile installarla.

    • androidPackageName e IOSBundleId: le app da utilizzare quando il link di accesso viene aperto su un dispositivo Android o iOS. Scopri di più su come configurare Firebase Dynamic Links per aprire i link alle azioni email tramite app mobile.

    • handleCodeInApp: impostato su true. L'operazione di accesso deve sempre essere completata nell'app, a differenza di altre azioni via email out of band (reimpostazione della password e verifiche email). Questo perché, al termine del flusso, si presume che l'utente abbia eseguito l'accesso e che il suo stato di autenticazione sia stato mantenuto all'interno dell'app.

    • dynamicLinkDomain: quando sono definiti più domini di link dinamici personalizzati per un progetto, specifica quello da utilizzare quando il link deve essere aperto tramite un'app mobile specificata (ad esempio example.page.link). In caso contrario, viene selezionato automaticamente il primo dominio.

    var acs = ActionCodeSettings(
        // URL you want to redirect back to. The domain (www.example.com) for this
        // URL must be whitelisted in the Firebase Console.
        url: 'https://www.example.com/finishSignUp?cartId=1234',
        // This must be true
        handleCodeInApp: true,
        iOSBundleId: 'com.example.ios',
        androidPackageName: 'com.example.android',
        // installIfNotAvailable
        androidInstallApp: true,
        // minimumVersion
        androidMinimumVersion: '12');
    
  2. Chiedi all'utente il suo indirizzo email.

  3. Invia il link di autenticazione all'indirizzo email dell'utente e salvalo nel caso in cui l'utente completi l'accesso via email sullo stesso dispositivo.

    var emailAuth = 'someemail@domain.com';
    FirebaseAuth.instance.sendSignInLinkToEmail(
            email: emailAuth, actionCodeSettings: acs)
        .catchError((onError) => print('Error sending email verification $onError'))
        .then((value) => print('Successfully sent email verification'));
    });
    

Problemi di sicurezza

Per evitare che un link di accesso venga utilizzato per accedere come utente non intenzionale o su un dispositivo non intenzionale, Firebase Auth richiede di fornire l'indirizzo email dell'utente al momento di completare il flusso di accesso. Affinché l'accesso vada a buon fine, questo indirizzo email deve corrispondere a quello a cui è stato inviato originariamente il link di accesso.

Puoi semplificare questo flusso per gli utenti che aprono il link di accesso sullo stesso dispositivo su cui lo richiedono, memorizzando il loro indirizzo email localmente, ad esempio utilizzando SharedPreferences, quando invii l'email di accesso. Poi, utilizza questo indirizzo per completare la procedura. Non trasmettere l'email dell'utente nei parametri dell'URL di reindirizzamento e riutilizzala, perché questo potrebbe consentire l'inserimento di sessioni.

Dopo il completamento dell'accesso, qualsiasi meccanismo di accesso non verificato precedente verrà rimosso dall'utente e le eventuali sessioni esistenti verranno annullate. Ad esempio, se qualcuno ha creato in precedenza un account non verificato con la stessa email e password, la password dell'utente verrà rimossa per impedire all'usurpatore che ha rivendicato la proprietà e creato l'account non verificato di accedere di nuovo con l'email e la password non verificate.

Inoltre, assicurati di utilizzare un URL HTTPS in produzione per evitare che il link venga potentially intercettato da server intermedi.

Firebase Authentication utilizza Firebase Dynamic Links per inviare il link email a un dispositivo mobile. Per completare l'accesso tramite l'applicazione mobile, l'applicazione deve essere configurata per rilevare il link dell'applicazione in arrivo, analizzare il link diretto sottostante e completare l'accesso.

  1. Configura la tua app per ricevere i link dinamici su Flutter nella guida.

  2. Nel gestore dei link, controlla se il link è destinato all'autenticazione tramite link email e, in caso affermativo, completa la procedura di accesso.

    // Confirm the link is a sign-in with email link.
    if (FirebaseAuth.instance.isSignInWithEmailLink(emailLink)) {
      try {
        // The client SDK will parse the code from the link for you.
        final userCredential = await FirebaseAuth.instance
            .signInWithEmailLink(email: emailAuth, emailLink: emailLink);
    
        // You can access the new user via userCredential.user.
        final emailAddress = userCredential.user?.email;
    
        print('Successfully signed in with email link!');
      } catch (error) {
        print('Error signing in with email link.');
      }
    }
    

Puoi anche collegare questo metodo di autenticazione a un utente esistente. Ad esempio, un utente che si è autenticato in precedenza con un altro fornitore, ad esempio un numero di telefono, può aggiungere questo metodo di accesso al proprio account esistente.

La differenza si trova nella seconda metà dell'operazione:

final authCredential = EmailAuthProvider
    .credentialWithLink(email: emailAuth, emailLink: emailLink.toString());
try {
    await FirebaseAuth.instance.currentUser
        ?.linkWithCredential(authCredential);
} catch (error) {
    print("Error linking emailLink credential.");
}

Può essere utilizzato anche per autenticare di nuovo un utente con link email prima di eseguire un'operazione sensibile.

final authCredential = EmailAuthProvider
    .credentialWithLink(email: emailAuth, emailLink: emailLink.toString());
try {
    await FirebaseAuth.instance.currentUser
        ?.reauthenticateWithCredential(authCredential);
} catch (error) {
    print("Error reauthenticating credential.");
}

Tuttavia, poiché il flusso potrebbe non essere completato su un dispositivo diverso su cui l'utente originale non aveva eseguito l'accesso, In questo caso, all'utente può essere mostrato un errore che lo costringe ad aprire il link sullo stesso dispositivo. Nel link è possibile passare un valore per fornire informazioni sul tipo di operazione e sull'UID dell'utente.

Se hai creato il progetto a partire dal 15 settembre 2023, la protezione dall'enumerazione email è abilitata per impostazione predefinita. Questa funzionalità migliora la sicurezza degli account utente del progetto, ma disattiva il metodo fetchSignInMethodsForEmail(), che in precedenza consigliavamo per implementare i flussi che danno la priorità all'identificatore.

Sebbene tu possa disattivare la protezione da enumerazione email per il tuo progetto, non lo consigliamo.

Per ulteriori dettagli, consulta la documentazione sulla protezione dall'enumerazione delle email.

Passaggi successivi

Dopo che un utente ha creato un nuovo account, questo viene archiviato nel progetto Firebase e può essere utilizzato per identificare un utente in ogni app del progetto, indipendentemente dal metodo di accesso utilizzato.

Nelle tue app puoi recuperare le informazioni di base del profilo dell'utente dall'oggetto User. Vedi Gestire gli utenti.

Nelle regole di sicurezza di Firebase Realtime Database e Cloud Storage, puoi recuperare l'ID utente univoco dell'utente che ha eseguito l'accesso dalla variabile auth e utilizzarlo per controllare a quali dati può accedere un utente.

Puoi consentire agli utenti di accedere alla tua app utilizzando più provider di autenticazione collegando le credenziali del provider di autenticazione) a un account utente esistente.

Per disconnettere un utente, chiama signOut():

await FirebaseAuth.instance.signOut();