查看 2022 年 Google I/O 大会上介绍的 Firebase 新动态。了解详情

Autenticati 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. Nel processo, viene verificato anche l'indirizzo e-mail dell'utente.

L'accesso tramite e-mail offre numerosi vantaggi:

  • Registrazione e accesso a basso attrito.
  • Minore rischio di riutilizzo delle password tra le applicazioni, che può compromettere la sicurezza anche di password ben selezionate.
  • La possibilità di autenticare un utente verificando anche che l'utente sia il legittimo proprietario di un indirizzo e-mail.
  • Un utente ha bisogno 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, che può essere ingombrante su un dispositivo mobile.
  • Un utente esistente che ha effettuato l'accesso in precedenza con un identificatore e-mail (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 reimpostare la password.

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 provider di posta elettronica e il metodo di accesso al collegamento e-mail per il tuo progetto Firebase:

    1. Nella console Firebase , apri la sezione Auth .
    2. Nella scheda Metodo di accesso, abilitare il provider di posta elettronica/password . Tieni presente che l'accesso tramite e-mail/password deve essere abilitato per utilizzare l'accesso tramite collegamento e-mail.
    3. Nella stessa sezione, abilita il metodo di accesso tramite 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 a Firebase di inviare 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 nell'elenco dei domini autorizzati di Firebase Console, che può essere trovato andando alla scheda Metodo di accesso (Autenticazione -> Metodo di accesso). Il collegamento reindirizzerà l'utente a questo URL se l'app non è installata sul proprio dispositivo e non è stato possibile installarla.

    • androidPackageName e IOSBundleId : le app da usare 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 link di 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 password e verifiche e-mail). Questo perché, alla fine del flusso, l'utente dovrebbe aver effettuato l'accesso e il suo stato di autenticazione persiste all'interno dell'app.

    • dynamicLinkDomain : quando vengono definiti più domini di collegamento dinamico personalizzati per un progetto, specificare quale utilizzare quando il collegamento deve essere aperto tramite un'app mobile specificata (ad esempio, example.page.link ). Altrimenti 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 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 all'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 evitare che un collegamento di accesso venga utilizzato per accedere come utente non previsto o su un dispositivo non previsto, Firebase Auth richiede che l'indirizzo e-mail dell'utente sia fornito al completamento del flusso di accesso. Affinché l'accesso abbia esito positivo, questo indirizzo email deve corrispondere all'indirizzo a cui è stato originariamente inviato il link 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.

Dopo il completamento dell'accesso, qualsiasi precedente meccanismo di accesso non verificato verrà rimosso dall'utente e tutte le sessioni esistenti verranno invalidate. Ad esempio, se qualcuno ha precedentemente creato 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 quell'account non verificato di accedere nuovamente con l'email e la 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 link 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.");
}

Questo può essere utilizzato anche per riautenticare un utente del 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 in cui l'utente originale non aveva effettuato l'accesso, questo flusso potrebbe non essere completato. In tal caso, all'utente può essere mostrato 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 utente.

Nel caso in cui si supporti sia l'accesso basato su password che su collegamento con l'e-mail, per differenziare il metodo di accesso per un utente con password/collegamento, utilizzare fetchSignInMethodsForEmail . Ciò è utile per i flussi di identificazione prima in cui all'utente viene prima chiesto di fornire la propria posta elettronica e quindi viene presentato il metodo di accesso:

try {
    final signInMethods =
        await FirebaseAuth.instance.fetchSignInMethodsForEmail(emailAuth);
    final userExists = signInMethods.isNotEmpty;
    final canSignInWithLink = signInMethods
        .contains(EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD);
    final canSignInWithPassword = signInMethods
        .contains(EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD);
} on FirebaseAuthException catch (exception) {
    switch (exception.code) {
        case "invalid-email":
            print("Not a valid email address.");
            break;
        default:
            print("Unknown error.");
    }
}

Come descritto sopra, email/password ed email/link sono considerati lo stesso EmailAuthProvider (stesso PROVIDER_ID ) con metodi di accesso diversi.

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 del profilo di base User dall'oggetto Utente. Vedere Gestisci utenti .

Nelle regole di sicurezza del database in tempo reale e dell'archiviazione cloud di Firebase, puoi ottenere 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();