Autenticazione con Firebase utilizzando i collegamenti e-mail

Puoi utilizzare l'autenticazione Firebase per accedere a un utente inviandogli un'e-mail contenente un collegamento su cui può fare clic per accedere. Durante il processo, viene verificato anche l'indirizzo e-mail dell'utente.

I vantaggi derivanti dall'accesso via e-mail sono numerosi:

  • Iscrizione e accesso a basso attrito.
  • Minore rischio di riutilizzo delle password tra le applicazioni, che può compromettere la sicurezza anche delle password ben selezionate.
  • La capacità di autenticare un utente verificando anche che l'utente sia il legittimo proprietario di un indirizzo email.
  • Un utente necessita solo di un account e-mail accessibile per accedere. Non è richiesta la proprietà di un numero di telefono o di un account di social media.
  • Un utente può accedere in modo sicuro senza la necessità di fornire (o ricordare) una password, il che può risultare complicato su un dispositivo mobile.
  • Un utente esistente che ha effettuato l'accesso in precedenza con un identificatore di posta elettronica (password o federato) può essere aggiornato per accedere solo con l'e-mail. Ad esempio, un utente che ha dimenticato la password può comunque accedere senza dover reimpostarla.

Prima di iniziare

  1. Se non l'hai già fatto, segui i passaggi nella guida introduttiva .

  2. Abilita l'accesso tramite collegamento e-mail per il tuo progetto Firebase.

    Per accedere agli utenti tramite collegamento e-mail, devi prima abilitare il metodo di accesso Provider e-mail e Collegamento e-mail per il tuo progetto Firebase:

    1. Nella console Firebase , apri la sezione Autenticazione .
    2. Nella scheda Metodo di accesso , abilita il provider di posta elettronica/password . Tieni presente che l'accesso tramite posta elettronica/password deve essere abilitato per utilizzare l'accesso tramite collegamento tramite posta elettronica.
    3. Nella stessa sezione, abilita il metodo di accesso Collegamento e-mail (accesso senza password) .
    4. Fare clic su Salva .

Per avviare il flusso di autenticazione, presenta un'interfaccia che richiede all'utente di fornire il proprio indirizzo e-mail e quindi chiama sendSignInLinkToEmail() per richiedere che Firebase invii il collegamento di autenticazione all'e-mail dell'utente.

  1. Costruisci l'oggetto ActionCodeSettings, che fornisce a Firebase le istruzioni su come costruire il collegamento e-mail. Imposta i seguenti campi:

    • url : il collegamento diretto da incorporare e qualsiasi stato aggiuntivo da trasmettere. Il dominio del collegamento deve essere inserito nella whitelist dell'elenco dei domini autorizzati della Console Firebase, che può essere trovato accedendo alla scheda Metodo di accesso (Autenticazione -> Metodo di accesso). Il collegamento 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 collegamento di accesso viene aperto su un dispositivo Android o iOS. Scopri di più su come configurare Firebase Dynamic Links per aprire i collegamenti alle azioni e-mail tramite app mobili.

    • handleCodeInApp : impostato su true . L'operazione di accesso deve essere sempre completata nell'app a differenza di altre azioni e-mail fuori banda (reimpostazione della password e verifiche e-mail). Questo perché, alla fine del flusso, è previsto che l'utente abbia effettuato l'accesso e che il suo stato di autenticazione sia persistente all'interno dell'app.

    • dynamicLinkDomain : quando per un progetto vengono definiti più domini di collegamento dinamico personalizzati, specificare quale utilizzare quando il collegamento deve essere aperto tramite un'app mobile specificata (ad esempio, example.page.link ). Altrimenti verrà 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 la sua email.

  3. Invia il collegamento di autenticazione all'e-mail dell'utente e salva l'e-mail dell'utente nel caso in cui l'utente completi l'accesso tramite e-mail 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 impedire che un collegamento di accesso venga utilizzato per accedere come utente non previsto o su un dispositivo non previsto, Firebase Auth richiede che venga fornito l'indirizzo email dell'utente al completamento del flusso di accesso. Affinché l'accesso abbia esito positivo, questo indirizzo e-mail deve corrispondere all'indirizzo a cui è stato originariamente inviato il collegamento di accesso.

Puoi semplificare questo flusso per gli utenti che aprono il collegamento di accesso sullo stesso dispositivo su cui richiedono il collegamento, memorizzando il loro indirizzo e-mail localmente, ad esempio utilizzando SharedPreferences, quando invii l'e-mail di accesso. Quindi, utilizza questo indirizzo per completare il flusso. Non passare l'e-mail dell'utente nei parametri dell'URL di reindirizzamento e riutilizzarla poiché ciò potrebbe consentire iniezioni di sessione.

Una volta completato l'accesso, qualsiasi meccanismo di accesso precedente non verificato verrà rimosso dall'utente e tutte le sessioni esistenti verranno invalidate. 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 al sosia che ha rivendicato la proprietà e creato l'account non verificato di accedere nuovamente con email e password non verificate.

Assicurati inoltre di utilizzare un URL HTTPS in produzione per evitare che il tuo collegamento venga potenzialmente intercettato da server intermedi.

L'autenticazione Firebase utilizza Firebase Dynamic Links per inviare il collegamento e-mail a un dispositivo mobile. Per completare l'accesso tramite l'applicazione mobile, l'applicazione deve essere configurata per rilevare il collegamento dell'applicazione in entrata, analizzare il collegamento diretto sottostante e quindi completare l'accesso.

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

  2. Nel gestore del collegamento, controlla se il collegamento è destinato all'autenticazione del collegamento e-mail e, in tal caso, 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 precedentemente autenticato con un altro provider, ad esempio un numero di telefono, può aggiungere questo metodo di accesso al proprio account esistente.

La differenza sarebbe 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 nuovamente un utente con collegamento e-mail 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 finire su un dispositivo diverso su cui l'utente originale non ha effettuato l'accesso, questo flusso potrebbe non essere completato. In tal caso, è possibile mostrare all'utente un errore per costringerlo ad aprire il collegamento sullo stesso dispositivo. Alcuni stati possono essere passati nel collegamento per fornire informazioni sul tipo di operazione e sull'uid dell'utente.

Se hai creato il tuo progetto a partire dal 15 settembre 2023, la protezione dell'enumerazione dei messaggi di posta elettronica è abilitata per impostazione predefinita. Questa funzionalità migliora la sicurezza degli account utente del tuo progetto, ma disabilita il metodo fetchSignInMethodsForEmail() , che in precedenza consigliavamo per implementare i flussi incentrati sull'identificatore.

Anche se puoi disabilitare la protezione dell'enumerazione delle email per il tuo progetto, ti consigliamo di non farlo.

Per ulteriori dettagli, consultare la documentazione sulla protezione dell'enumerazione della posta elettronica .

Prossimi passi

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

Nelle tue app puoi ottenere le informazioni di base del profilo dell'utente dall'oggetto User . Vedi Gestisci utenti .

Nel tuo Firebase Realtime Database e nelle regole di sicurezza Cloud Storage, puoi ottenere l'ID utente univoco dell'utente che ha effettuato 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();