Uwierzytelnianie w Firebase za pomocą linków w e-mailach

Usługa Uwierzytelnianie Firebase umożliwia logowanie użytkowników przez wysyłanie im e-maili z linkiem, który mogą kliknąć, aby się zalogować. W tym procesie weryfikowany jest też adres e-mail użytkownika.

Logowanie się za pomocą adresu e-mail ma wiele korzyści:

  • Prosta rejestracja i logowanie.
  • mniejsze ryzyko ponownego użycia haseł w różnych aplikacjach, co może osłabić bezpieczeństwo nawet dobrze dobranych haseł;
  • Możliwość uwierzytelniania użytkownika przy jednoczesnym potwierdzaniu, że jest on prawowitym właścicielem adresu e-mail.
  • Aby się zalogować, użytkownik potrzebuje tylko dostępnego konta e-mail. Nie musisz być właścicielem numeru telefonu ani konta w mediach społecznościowych.
  • Użytkownik może bezpiecznie zalogować się bez konieczności podawania (lub zapamiętywania) hasła, co może być uciążliwe na urządzeniu mobilnym.
  • Dotychczasowy użytkownik, który wcześniej logował się za pomocą identyfikatora e-mail (hasła lub logowania sfederowanego), może przejść na logowanie się tylko za pomocą adresu e-mail. Na przykład użytkownik, który zapomniał hasła, może się zalogować bez konieczności resetowania hasła.

Zanim zaczniesz

  1. Jeśli nie masz jeszcze dostępu do konta demonstracyjnego, postępuj zgodnie z instrukcjami w przewodniku Pierwsze kroki.

  2. Włącz logowanie za pomocą linku e-mail w projekcie w Firebase.

    Aby logować użytkowników za pomocą linku w e-mailu, musisz najpierw włączyć w projekcie w Firebase dostawcę poczty e-mail i metodę logowania za pomocą linku w e-mailu:

    1. W konsoli Firebase otwórz Bezpieczeństwo > Uwierzytelnianie.

    2. Na karcie Metoda logowania włącz dostawcę logowania E-mail/hasło. Pamiętaj, że aby korzystać z logowania za pomocą linku w e-mailu, musisz włączyć logowanie za pomocą adresu e-mail i hasła.

    3. W tej samej sekcji włącz metodę logowania Link w e-mailu (logowanie bez hasła).

    4. Kliknij Zapisz.

Aby rozpocząć proces uwierzytelniania, wyświetl interfejs, który prosi użytkownika o podanie adresu e-mail, a następnie wywołaj funkcję sendSignInLinkToEmail(), aby poprosić Firebase o wysłanie linku do uwierzytelniania na adres e-mail użytkownika.

  1. Utwórz obiekt ActionCodeSettings, który zawiera instrukcje dla Firebase dotyczące tworzenia linku w e-mailu. Ustaw wartości w tych polach:

    • url: precyzyjny link do umieszczenia i wszelkie dodatkowe informacje o stanie, które mają zostać przekazane. Jeśli jeszcze tego nie zrobisz, dodaj domenę linku do listy autoryzowanych domen:

      1. W konsoli Firebase kliknij kartę Uwierzytelnianie > Ustawienia.

      2. W sekcji Autoryzowane domeny kliknij Dodaj domenę i dodaj domenę linku.

      Jeśli aplikacja nie jest zainstalowana na urządzeniu użytkownika i nie udało się jej zainstalować, link przekieruje użytkownika pod ten adres URL.

    • androidPackageNameIOSBundleId: aplikacje, które mają być używane, gdy link do logowania zostanie otwarty na urządzeniu z Androidem lub iOS. Dowiedz się więcej o konfigurowaniu Linków dynamicznych Firebase, aby otwierać linki do działań w e-mailach w aplikacjach mobilnych.

    • handleCodeInApp: ustaw wartość true. Operacja logowania musi być zawsze przeprowadzana w aplikacji, w przeciwieństwie do innych działań wykonywanych poza pasmem (resetowanie hasła i weryfikacja adresu e-mail). Dzieje się tak, ponieważ na końcu procesu użytkownik powinien być zalogowany, a jego stan uwierzytelniania powinien być zachowany w aplikacji.

    • dynamicLinkDomain: (Wycofane, użyj linkDomain) Jeśli w projekcie zdefiniowano wiele niestandardowych domen dynamicznych linków, określ, której z nich należy użyć, gdy link ma być otwierany za pomocą określonej aplikacji mobilnej (np. example.page.link). W przeciwnym razie automatycznie zostanie wybrana pierwsza domena.

    • linkDomain: opcjonalna niestandardowa domena Hostingu Firebase, która ma być używana, gdy link jest otwierany w określonej aplikacji mobilnej. Domena musi być skonfigurowana w Hostingu Firebase i należeć do projektu. Nie może to być domena hostingu domyślnego (web.app lubfirebaseapp.com). Zastępuje to wycofane ustawienie dynamicLinkDomain.

    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. Poproś użytkownika o podanie adresu e-mail.

  3. Wyślij link do uwierzytelniania na adres e-mail użytkownika i zapisz ten adres na wypadek, gdyby użytkownik dokończył logowanie przez e-mail na tym samym urządzeniu.

    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'));
    });
    

Potencjalne problemy z bezpieczeństwem

Aby zapobiec użyciu linku do logowania w celu zalogowania się jako nieodpowiedni użytkownik lub na nieodpowiednim urządzeniu, Firebase Authentication wymaga podania adresu e-mail użytkownika podczas kończenia procesu logowania. Aby logowanie się powiodło, ten adres e-mail musi być zgodny z adresem, na który pierwotnie został wysłany link do logowania.

Możesz uprościć ten proces dla użytkowników, którzy otwierają link do logowania na tym samym urządzeniu, na którym o niego proszą. W tym celu zapisz lokalnie ich adres e-mail, np. za pomocą SharedPreferences, gdy wysyłasz e-maila z linkiem do logowania. Następnie użyj tego adresu, aby dokończyć proces. Nie przekazuj adresu e-mail użytkownika w parametrach adresu URL przekierowania i nie używaj go ponownie, ponieważ może to umożliwić wstrzykiwanie sesji.

Po zakończeniu logowania wszystkie poprzednie niezweryfikowane mechanizmy logowania zostaną usunięte z konta użytkownika, a wszystkie dotychczasowe sesje zostaną unieważnione. Jeśli na przykład ktoś wcześniej utworzył niezweryfikowane konto z tym samym adresem e-mail i hasłem, hasło użytkownika zostanie usunięte, aby uniemożliwić ponowne zalogowanie się osobie, która przejęła własność i utworzyła to niezweryfikowane konto, przy użyciu niezweryfikowanego adresu e-mail i hasła.

W środowisku produkcyjnym używaj adresu URL HTTPS, aby uniknąć potencjalnego przechwycenia linku przez serwery pośredniczące.

Zakończ logowanie

Usługa Linki dynamiczne Firebase została wycofana. Do wysyłania linku logowania używana jest teraz usługa Hosting Firebase. Postępuj zgodnie z przewodnikami dotyczącymi konfiguracji na poszczególnych platformach:

Aby dokończyć logowanie za pomocą aplikacji mobilnej, musi ona być skonfigurowana tak, aby wykrywać przychodzący link do aplikacji, analizować precyzyjny link i dokończyć logowanie.

  1. W programie obsługującym linki sprawdź, czy link jest przeznaczony do uwierzytelniania za pomocą linku w e-mailu. Jeśli tak, dokończ proces logowania.

    // 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.');
      }
    }
    

Możesz też połączyć tę metodę uwierzytelniania z dotychczasowym użytkownikiem. Na przykład użytkownik, który wcześniej uwierzytelnił się u innego dostawcy, np. za pomocą numeru telefonu, może dodać tę metodę logowania do swojego obecnego konta.

Różnica wystąpi w drugiej połowie operacji:

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

Można go też użyć do ponownego uwierzytelnienia użytkownika linku e-mail przed wykonaniem operacji wrażliwej.

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

Jednak proces może zakończyć się na innym urządzeniu, na którym pierwotny użytkownik nie był zalogowany, więc może nie zostać ukończony. W takim przypadku użytkownikowi może zostać wyświetlony błąd, który zmusi go do otwarcia linku na tym samym urządzeniu. W linku można przekazać parametr state, aby podać informacje o typie operacji i identyfikatorze użytkownika.

Jeśli projekt został utworzony 15 września 2023 r. lub później, ochrona przed wyliczaniem adresów e-mail jest domyślnie włączona. Ta funkcja zwiększa bezpieczeństwo kont użytkowników projektu, ale wyłącza metodę fetchSignInMethodsForEmail(), którą wcześniej zalecaliśmy do wdrażania procesów opartych na identyfikatorze.

Chociaż możesz wyłączyć ochronę przed wyliczaniem adresów e-mail w swoim projekcie, nie zalecamy tego.

Więcej informacji znajdziesz w dokumentacji dotyczącej ochrony przed wyliczaniem adresów e-mail.

Dalsze kroki

Po utworzeniu przez użytkownika nowego konta jest ono przechowywane w ramach projektu w Firebase i może służyć do identyfikowania użytkownika w każdej aplikacji w projekcie, niezależnie od metody logowania.

W aplikacjach możesz pobierać podstawowe informacje o profilu użytkownika z obiektu User. Zobacz Zarządzanie użytkownikami.

W regułach bezpieczeństwa Bazy danych czasu rzeczywistego Firebase i Cloud Storage możesz pobrać unikalny identyfikator zalogowanego użytkownika ze zmiennej auth i użyć go do kontrolowania, do jakich danych użytkownik ma dostęp.

Możesz zezwolić użytkownikom na logowanie się w aplikacji za pomocą wielu dostawców uwierzytelniania, łącząc dane logowania dostawcy uwierzytelniania z istniejącym kontem użytkownika.

Aby wylogować użytkownika, wywołaj funkcję signOut():

await FirebaseAuth.instance.signOut();