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

Użyj usługi Uwierzytelnianie Firebase, aby zalogować użytkownika. Wyślij mu e-maila z linkiem, który umożliwi mu zalogowanie się. W ramach tego procesu weryfikowany jest też adres e-mail użytkownika.

Logowanie się za pomocą adresu e-mail ma wiele zalet:

  • Rejestracja i logowanie bez zbędnych formalności.
  • mniejsze ryzyko ponownego użycia hasła w różnych aplikacjach, co może obniżyć bezpieczeństwo nawet dobrze dobranych haseł;
  • Umożliwia uwierzytelnianie użytkownika i weryfikowanie, czy jest on prawowitym właścicielem adresu e-mail.
  • Aby się zalogować, użytkownik musi mieć tylko dostępne konto e-mail. Nie musisz być właścicielem numeru telefonu ani konta w mediach społecznościowych.
  • Użytkownik może logować się bezpiecznie bez konieczności podawania (lub zapamiętywania) hasła, co może być uciążliwe na urządzeniu mobilnym.
  • Istniejący użytkownik, który wcześniej logował się przy użyciu identyfikatora e-mail (hasła lub federacji), 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 jego resetowania.

Zanim zaczniesz

  1. Jeśli nie została jeszcze przeprowadzona, wykonaj kroki konfiguracji.

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

    Aby umożliwić użytkownikom logowanie się za pomocą linku e-mail, musisz najpierw włączyć metodę logowania za pomocą dostawcy e-maili i linku e-mail w swoim projekcie Firebase:

    1. konsoli Firebase otwórz sekcję Uwierzytelnianie.
    2. Na karcie Metoda logowania włącz dostawcę E-mail/hasło. Pamiętaj, że aby można było logować się za pomocą linku w e-mailu, logowanie za pomocą adresu e-mail i hasła musi być włączone.
    3. W tej samej sekcji włącz metodę logowania Link w e-mailu (logowanie bez hasła).
    4. Kliknij Zapisz.

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

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

    • url: precyzyjny link do osadzenia i dodatkowe stany, które mają zostać przekazane. Domena linku musi znajdować się na liście autoryzowanych domen w konsoli Firebase. Listę tę znajdziesz na karcie Ustawienia (Uwierzytelnianie -> Ustawienia -> Autoryzowane domeny). Link przekieruje użytkownika pod ten adres URL, jeśli aplikacja nie jest zainstalowana na urządzeniu i nie udało się jej zainstalować.

    • androidPackageName i IOSBundleId: aplikacje, których należy używać, gdy link logowania jest otwierany na urządzeniu z Androidem lub iOS. Dowiedz się więcej o konfigurowaniu linków dynamicznych Firebase, aby otwierały linki akcji e-mail w aplikacjach mobilnych.

    • handleCodeInApp: ustaw na true. W przeciwieństwie do innych działań związanych z e-mailem (takich jak resetowanie hasła czy weryfikacja adresu e-mail) operacja logowania musi być zawsze wykonywana w aplikacji. Dzieje się tak, ponieważ na końcu procesu użytkownik powinien być zalogowany, a stan uwierzytelniania powinien być zachowany w aplikacji.

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

    • linkDomain: opcjonalna niestandardowa domena Hostingu Firebase, której należy użyć, gdy link ma być otwierany za pomocą określonej aplikacji mobilnej. Domena musi być skonfigurowana w Hostingu Firebase i należeć do projektu. Nie może to być domyślna domena hostingu (web.app lub firebaseapp.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 adres e-mail.

  3. Wyślij link uwierzytelniania na adres e-mail użytkownika i zapisz ten adres na wypadek, gdyby użytkownik zalogował się za pomocą adresu 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żywaniu linku logowania przez nieuprawnionego użytkownika lub na nieuprawnionym urządzeniu, usługa Firebase Auth wymaga podania adresu e-mail użytkownika podczas procesu logowania. Aby zalogować się na konto, musisz podać adres e-mail, na który został wysłany link do logowania.

Możesz uprościć ten proces w przypadku użytkowników, którzy otwierają link logowania na tym samym urządzeniu, na którym wysłali prośbę o link, przechowując ich adresy e-mail lokalnie (np. za pomocą SharedPreferences) podczas wysyłania e-maila z linkiem logowania. Następnie użyj tego adresu, aby dokończyć proces. Nie przekazuj adresu e-mail użytkownika w parametrach adresu URL przekierowania ani nie używaj go ponownie, ponieważ może to umożliwić wstrzyknięcie sesji.

Po zakończeniu procesu logowania wszystkie wcześniejsze mechanizmy logowania bez weryfikacji zostaną usunięte z konta użytkownika, a istniejące sesje zostaną unieważnione. Jeśli na przykład ktoś wcześniej utworzył niezatwierdzone konto z tym samym adresem e-mail i tym samym hasłem, hasło użytkownika zostanie usunięte, aby uniemożliwić osobie podszywającej się pod niego zalogowanie się ponownie przy użyciu niezatwierdzonego adresu e-mail i hasła.

Pamiętaj też, aby w produkcji używać adresu URL HTTPS, aby uniknąć przechwycenia linku przez serwery pośredniczące.

Zaloguj się

Linki dynamiczne Firebase zostały wycofane. Do wysyłania linku do logowania jest teraz używany Hosting Firebase. Postępuj zgodnie z instrukcjami dotyczącymi konfiguracji na danej platformie:

Aby umożliwić logowanie się za pomocą aplikacji mobilnej, musisz skonfigurować aplikację tak, aby wykrywała przychodzące linki aplikacji, analizowała je i dokonywała logowania.

  1. W obsługiwaniu linków sprawdź, czy link jest przeznaczony do uwierzytelniania za pomocą linku e-mail. Jeśli tak, ukoń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 dotychczasowego konta.

Różnica polega na tym, że druga połowa 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, który używa 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.");
}

Ponieważ jednak proces może zakończyć się na innym urządzeniu, na którym pierwotny użytkownik nie był zalogowany, może on nie zostać ukończony. W takim przypadku użytkownik może zobaczyć komunikat o błędzie, który zmusza go do otwarcia linku na tym samym urządzeniu. W linku można przekazać pewien stan, aby podać informacje o typie operacji i identyfikatorze użytkownika (UID).

Jeśli projekt został utworzony 15 września 2023 r. lub później, ochrona przed enumeracją 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óra była wcześniej zalecana do implementacji przepływów z identyfikatorem na pierwszym miejscu.

Możesz wyłączyć ochronę przed wyliczaniem adresów e-mail w przypadku swojego projektu, ale nie zalecamy tego.

Aby dowiedzieć się więcej, zapoznaj się z dokumentacją dotyczącą ochrony przed wyliczaniem adresów e-mail.

Dalsze kroki

Gdy użytkownik utworzy nowe konto, zostanie ono zapisane w ramach projektu Firebase i może służyć do identyfikowania użytkownika we wszystkich aplikacjach w projekcie, niezależnie od tego, której metody logowania użył.

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

W regułach bezpieczeństwa Firebase Realtime Database i Cloud Storage możesz pobrać z zmiennej auth unikalny identyfikator zalogowanego użytkownika, aby określić, do jakich danych ma on dostęp.

Możesz zezwolić użytkownikom na logowanie się w aplikacji za pomocą danych logowania pochodzących od wielu dostawców uwierzytelniania, połączając dane logowania dostawcy uwierzytelniania z dotychczasowym kontem użytkownika.

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

await FirebaseAuth.instance.signOut();