Uwierzytelnianie w Firebase za pomocą linku e-mail na Androidzie

Możesz użyć uwierzytelniania Firebase, aby zalogować użytkownika, wysyłając mu e-maila z linkiem, który może kliknąć, aby się zalogować. Podczas procesu weryfikacji zweryfikowany jest też adres e-mail użytkownika.

Logowanie się przez e-maila ma wiele zalet:

  • Rejestracja i logowanie przebiegają sprawnie.
  • Mniejsze ryzyko ponownego użycia tego samego hasła w różnych aplikacjach, co może zagrażać bezpieczeństwu nawet dobrze dobranych haseł.
  • Możliwość uwierzytelnienia użytkownika, a jednocześnie potwierdzanie, że jest on prawowitym właścicielem adresu e-mail.
  • Aby się zalogować, użytkownik potrzebuje tylko dostępnego konta e-mail. Nie jest wymagane posiadanie 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ące konto użytkownika, które wcześniej logowało się przy użyciu identyfikatora e-mail (hasła lub konta sfederowanego), można przejść na wyższą wersję, aby logować się przy użyciu samego adresu e-mail. Na przykład użytkownik, który nie pamięta hasła, może się zalogować bez konieczności resetowania hasła.

Zanim zaczniesz

Skonfiguruj projekt na Androida

  1. Dodaj Firebase do swojego projektu Android, chyba że masz to już za sobą.

  2. W pliku Gradle modułu (na poziomie aplikacji) (zwykle <project>/<app-module>/build.gradle.kts lub <project>/<app-module>/build.gradle) dodaj zależność z biblioteką uwierzytelniania Firebase na Androida. Do kontrolowania obsługi wersji biblioteki zalecamy używanie funkcji Firebase Android BoM.

    Poza tym w ramach konfigurowania uwierzytelniania Firebase musisz dodać pakiet SDK Usług Google Play do swojej aplikacji.

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:33.1.2"))
    
        // Add the dependency for the Firebase Authentication library
        // When using the BoM, you don't specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth")
    // Also add the dependency for the Google Play services library and specify its version implementation("com.google.android.gms:play-services-auth:21.2.0")
    }

    Dzięki użyciu BoM Firebase Android BoM Twoja aplikacja zawsze używa zgodnych wersji bibliotek Firebase na Androida.

    (Alternatywnie) Dodawanie zależności bibliotek Firebase bez korzystania z BM

    Jeśli nie chcesz używać Firebase BoM, musisz określić każdą wersję biblioteki Firebase w wierszu zależności.

    Pamiętaj, że jeśli w swojej aplikacji używasz wielu bibliotek Firebase, zdecydowanie zalecamy korzystanie z BoM do zarządzania wersjami bibliotek. Dzięki temu będziesz mieć pewność, że wszystkie wersje są zgodne.

    dependencies {
        // Add the dependency for the Firebase Authentication library
        // When NOT using the BoM, you must specify versions in Firebase library dependencies
        implementation("com.google.firebase:firebase-auth:23.0.0")
    // Also add the dependency for the Google Play services library and specify its version implementation("com.google.android.gms:play-services-auth:21.2.0")
    }
    Szukasz modułu biblioteki korzystającego z usługi Kotlin? Od października 2023 r. (Firebase BoM 32.5.0) zarówno deweloperzy aplikacji Kotlin, jak i języki Java mogą korzystać z modułu biblioteki głównej (więcej informacji znajdziesz w odpowiedziach na najczęstsze pytania o tę inicjatywę).

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

  1. W konsoli Firebase otwórz sekcję Uwierzytelnianie.
  2. Na karcie Metoda logowania włącz dostawcę E-mail/hasła. Pamiętaj, że aby korzystać z logowania za pomocą linku e-mail, 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 zainicjować proces uwierzytelniania, pokaż użytkownikowi interfejs, który prosi o podanie adresu e-mail, a następnie wywołaj sendSignInLinkToEmail z prośbą o wysłanie przez Firebase linku uwierzytelniającego na jego adres e-mail.

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

    • url: precyzyjny link do umieszczenia i wszystkie dodatkowe stany do przekazania. Domena linku musi znajdować się na białej liście na liście autoryzowanych domen w konsoli Firebase. Aby ją znaleźć, przejdź na kartę Metoda logowania (Uwierzytelnianie -> Metoda logowania). Link przekieruje użytkownika na ten adres URL, jeśli aplikacja nie jest zainstalowana na urządzeniu i nie można jej zainstalować.
    • androidPackageName i IOSBundleId: aplikacje, które mają być używane po otwarciu linku logowania na urządzeniu z Androidem lub urządzeniu firmy Apple. Dowiedz się więcej o tym, jak skonfigurować Linki dynamiczne Firebase, aby otwierać linki do działań w e-mailach w aplikacjach mobilnych.
    • handleCodeInApp: ustaw wartość prawda. Operacja logowania musi być zawsze wykonywana w aplikacji, w przeciwieństwie do innych pozapasmowych działań związanych z e-mailami (resetowania hasła i potwierdzania adresu e-mail). Wynika to z faktu, że pod koniec procesu użytkownik musi być zalogowany, a jego stan uwierzytelniania musi pozostać w aplikacji.
    • dynamicLinkDomain: jeśli w projekcie zdefiniowano wiele niestandardowych domen linków dynamicznych, określ, która ma być używana, gdy link ma być otwierany przez określoną aplikację mobilną (np. example.page.link). W przeciwnym razie automatycznie zostanie wybrana pierwsza domena.

    Kotlin+KTX

    val actionCodeSettings = 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
        setIOSBundleId("com.example.ios")
        setAndroidPackageName(
            "com.example.android",
            true, // installIfNotAvailable
            "12", // minimumVersion
        )
    }

    Java

    ActionCodeSettings actionCodeSettings =
            ActionCodeSettings.newBuilder()
                    // URL you want to redirect back to. The domain (www.example.com) for this
                    // URL must be whitelisted in the Firebase Console.
                    .setUrl("https://www.example.com/finishSignUp?cartId=1234")
                    // This must be true
                    .setHandleCodeInApp(true)
                    .setIOSBundleId("com.example.ios")
                    .setAndroidPackageName(
                            "com.example.android",
                            true, /* installIfNotAvailable */
                            "12"    /* minimumVersion */)
                    .build();

    Więcej informacji o ActionCodeSettings znajdziesz w sekcji Stan przekazywania w czynnościach poczty e-mail.

  2. Poproś użytkownika o podanie adresu e-mail.

  3. Wyślij link uwierzytelniania na adres e-mail użytkownika i zapisz adres e-mail użytkownika, na wypadek gdyby użytkownik logował się za pomocą adresu e-mail na tym samym urządzeniu.

    Kotlin+KTX

    Firebase.auth.sendSignInLinkToEmail(email, actionCodeSettings)
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                Log.d(TAG, "Email sent.")
            }
        }

    Java

    FirebaseAuth auth = FirebaseAuth.getInstance();
    auth.sendSignInLinkToEmail(email, actionCodeSettings)
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(@NonNull Task<Void> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "Email sent.");
                    }
                }
            });

Potencjalne problemy z bezpieczeństwem

Aby zapobiec użyciu linku logowania do zalogowania się jako niezamierzony użytkownik lub na niewłaściwym urządzeniu, Uwierzytelnianie Firebase wymaga podania adresu e-mail użytkownika podczas logowania się. Aby logowanie się powiodło, ten adres e-mail musi być zgodny z adresem, na który pierwotnie przesłano link.

Możesz usprawnić ten proces w przypadku użytkowników, którzy otwierają link logowania na tym samym urządzeniu, na tym samym urządzeniu, zapisując swój adres e-mail lokalnie – na przykład za pomocą SharedPreferences – gdy wysyłasz e-maila logowania. Następnie użyj tego adresu do dokończenia procesu. Nie przekazuj adresu e-mail użytkownika w parametrach przekierowania ani nie używaj go ponownie, ponieważ może to umożliwić wstrzykiwanie sesji.

Po zakończeniu logowania wszystkie wcześniejsze niezweryfikowane mechanizmy logowania zostaną usunięte z konta użytkownika, a wszystkie istniejące 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ć osobie podszywającej się pod inną osobę, która zgłosiła prawo własności i utworzyła niezweryfikowane konto, ponownie zalogowanie się przy użyciu niezweryfikowanego adresu e-mail i hasła.

Upewnij się też, że w środowisku produkcyjnym używasz adresu URL HTTPS, aby zapobiec potencjalnemu przechwyceniu linku przez serwery pośrednie.

Logowanie się w aplikacji na Androida

Uwierzytelnianie Firebase używa Linków dynamicznych Firebase do wysyłania linku e-mail na urządzenie mobilne. Aby zalogować się za pomocą aplikacji mobilnej, należy skonfigurować aplikację tak, aby wykrywała przychodzący link do aplikacji, przeanalizowała precyzyjny link i ukończyła logowanie.

Uwierzytelnianie Firebase używa Linków dynamicznych Firebase do wysyłania linku, który ma być otwierany w aplikacji mobilnej. Aby można było korzystać z tej funkcji, Linki dynamiczne musisz skonfigurować w konsoli Firebase.

  1. Włącz Linki dynamiczne Firebase:

    1. W konsoli Firebase otwórz sekcję Połączenia dynamiczne.
    2. Jeśli Warunki Linków dynamicznych nie zostały jeszcze zaakceptowane i masz utworzoną domenę Linków dynamicznych, zrób to teraz.

      Jeśli masz już utworzoną domenę Linki dynamiczne, zanotuj ją. Domena linków dynamicznych zwykle wygląda tak jak w przykładzie poniżej:

      example.page.link

      Będzie ona potrzebna podczas konfigurowania aplikacji na Apple lub Androida w taki sposób, aby przechwytywała link przychodzący.

  2. Konfigurowanie aplikacji na Androida:

    1. Aby obsługiwać te linki z aplikacji na Androida, musisz określić nazwę pakietu na Androida w ustawieniach projektu w Konsoli Firebase. Dodatkowo musisz podać SHA-1 i SHA-256 certyfikatu aplikacji.
    2. Po dodaniu domeny linku dynamicznego i upewnieniu się, że aplikacja na Androida jest skonfigurowana prawidłowo, link dynamiczny przekieruje Cię do Twojej aplikacji, zaczynając od działania programu uruchamiającego.
    3. Jeśli chcesz, by link dynamiczny przekierowywał do określonej aktywności, musisz skonfigurować filtr intencji w pliku AndroidManifest.xml. W tym celu możesz określić domenę linku dynamicznego lub moduł obsługi działań e-mail w filtrze intencji. Domyślnie moduł obsługi działań na poczcie e-mail jest hostowany w domenie, jak w tym przykładzie:
      PROJECT_ID.firebaseapp.com/
    4. Uwagi:
      1. Nie określaj adresu URL ustawionego w actionCodeSettings w filtrze intencji.
      2. Podczas tworzenia domeny linku dynamicznego możesz też utworzyć krótki link z adresem URL. Ten krótki adres URL nie zostanie przekazany. Nie konfiguruj filtra intencji, aby przechwytywał go za pomocą atrybutu android:pathPrefix. Oznacza to, że nie będzie można wychwytywać różnych linków dynamicznych w różnych częściach aplikacji. Możesz jednak sprawdzić parametr zapytania mode w linku, by zobaczyć, jaka operacja ma zostać wykonana, lub użyć metod SDK, takich jak isSignInWithEmailLink, by przekonać się, czy link otrzymany przez aplikację spełnia Twoje oczekiwania.
    5. Więcej informacji o otrzymywaniu linków dynamicznych znajdziesz w instrukcjach dotyczących otrzymywania linków dynamicznych w Androidzie.

Po otrzymaniu linku (zgodnie z opisem powyżej) upewnij się, że służy on do uwierzytelniania za pomocą linku w e-mailu, i zaloguj się.

Kotlin+KTX

val auth = Firebase.auth
val intent = intent
val emailLink = intent.data.toString()

// Confirm the link is a sign-in with email link.
if (auth.isSignInWithEmailLink(emailLink)) {
    // Retrieve this from wherever you stored it
    val email = "someemail@domain.com"

    // The client SDK will parse the code from the link for you.
    auth.signInWithEmailLink(email, emailLink)
        .addOnCompleteListener { task ->
            if (task.isSuccessful) {
                Log.d(TAG, "Successfully signed in with email link!")
                val result = task.result
                // You can access the new user via result.getUser()
                // Additional user info profile *not* available via:
                // result.getAdditionalUserInfo().getProfile() == null
                // You can check if the user is new or existing:
                // result.getAdditionalUserInfo().isNewUser()
            } else {
                Log.e(TAG, "Error signing in with email link", task.exception)
            }
        }
}

Java

FirebaseAuth auth = FirebaseAuth.getInstance();
Intent intent = getIntent();
String emailLink = intent.getData().toString();

// Confirm the link is a sign-in with email link.
if (auth.isSignInWithEmailLink(emailLink)) {
    // Retrieve this from wherever you stored it
    String email = "someemail@domain.com";

    // The client SDK will parse the code from the link for you.
    auth.signInWithEmailLink(email, emailLink)
            .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    if (task.isSuccessful()) {
                        Log.d(TAG, "Successfully signed in with email link!");
                        AuthResult result = task.getResult();
                        // You can access the new user via result.getUser()
                        // Additional user info profile *not* available via:
                        // result.getAdditionalUserInfo().getProfile() == null
                        // You can check if the user is new or existing:
                        // result.getAdditionalUserInfo().isNewUser()
                    } else {
                        Log.e(TAG, "Error signing in with email link", task.getException());
                    }
                }
            });
}

Więcej informacji o tym, jak obsługiwać logowanie się za pomocą linku przez e-maila w aplikacji Apple, znajdziesz w przewodniku po platformach Apple.

Aby dowiedzieć się, jak obsługiwać logowanie się w aplikacji internetowej za pomocą linku przez e-maila, zapoznaj się z Przewodnikiem po stronie internetowej.

Możesz też powiązać tę metodę uwierzytelniania z istniejącym użytkownikiem. Na przykład użytkownik, który wcześniej uwierzytelnił się u innego dostawcy (np. przy użyciu numeru telefonu), może dodać tę metodę logowania do swojego istniejącego konta.

Różnica będzie widoczna w drugiej połowie operacji:

Kotlin+KTX

// Construct the email link credential from the current URL.
val credential = EmailAuthProvider.getCredentialWithLink(email, emailLink)

// Link the credential to the current user.
Firebase.auth.currentUser!!.linkWithCredential(credential)
    .addOnCompleteListener { task ->
        if (task.isSuccessful) {
            Log.d(TAG, "Successfully linked emailLink credential!")
            val result = task.result
            // You can access the new user via result.getUser()
            // Additional user info profile *not* available via:
            // result.getAdditionalUserInfo().getProfile() == null
            // You can check if the user is new or existing:
            // result.getAdditionalUserInfo().isNewUser()
        } else {
            Log.e(TAG, "Error linking emailLink credential", task.exception)
        }
    }

Java

// Construct the email link credential from the current URL.
AuthCredential credential =
        EmailAuthProvider.getCredentialWithLink(email, emailLink);

// Link the credential to the current user.
auth.getCurrentUser().linkWithCredential(credential)
        .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    Log.d(TAG, "Successfully linked emailLink credential!");
                    AuthResult result = task.getResult();
                    // You can access the new user via result.getUser()
                    // Additional user info profile *not* available via:
                    // result.getAdditionalUserInfo().getProfile() == null
                    // You can check if the user is new or existing:
                    // result.getAdditionalUserInfo().isNewUser()
                } else {
                    Log.e(TAG, "Error linking emailLink credential", task.getException());
                }
            }
        });

W ten sposób możesz też ponownie uwierzytelnić użytkownika powiązanego z linkiem e-mail przed uruchomieniem operacji poufnej.

Kotlin+KTX

// Construct the email link credential from the current URL.
val credential = EmailAuthProvider.getCredentialWithLink(email, emailLink)

// Re-authenticate the user with this credential.
Firebase.auth.currentUser!!.reauthenticateAndRetrieveData(credential)
    .addOnCompleteListener { task ->
        if (task.isSuccessful) {
            // User is now successfully reauthenticated
        } else {
            Log.e(TAG, "Error reauthenticating", task.exception)
        }
    }

Java

// Construct the email link credential from the current URL.
AuthCredential credential =
        EmailAuthProvider.getCredentialWithLink(email, emailLink);

// Re-authenticate the user with this credential.
auth.getCurrentUser().reauthenticateAndRetrieveData(credential)
        .addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {
                if (task.isSuccessful()) {
                    // User is now successfully reauthenticated
                } else {
                    Log.e(TAG, "Error reauthenticating", task.getException());
                }
            }
        });

Proces ten może jednak nie zostać ukończony na innym urządzeniu, na którym pierwotny użytkownik nie był zalogowany. W takim przypadku może wyświetlić się komunikat o błędzie, który będzie wymuszał na nim otwarcie linku na tym samym urządzeniu. W linku można przekazać informacje o typie działania i identyfikatorze UID użytkownika.

Jeśli Twój projekt został utworzony 15 września 2023 r. lub później, ochrona przed wyliczeniem adresów e-mail jest domyślnie włączona. Ta funkcja zwiększa bezpieczeństwo kont użytkowników Twojego projektu, ale wyłącza metodę fetchSignInMethodsForEmail(), którą wcześniej rekomendowaliśmy w celu implementacji przepływów skoncentrowanych na identyfikatorze.

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

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

Dalsze kroki

Gdy użytkownik loguje się po raz pierwszy, tworzone jest nowe konto użytkownika, które jest łączone z danymi logowania (nazwa użytkownika i hasło, numer telefonu lub informacje o dostawcy uwierzytelniania). Nowe konto jest przechowywane w ramach Twojego projektu Firebase i może być używane do identyfikowania użytkowników we wszystkich aplikacjach w Twoim projekcie niezależnie od tego, jak się on loguje.

  • W swoich aplikacjach możesz uzyskać podstawowe informacje o profilu użytkownika z obiektu FirebaseUser. Patrz: Zarządzanie użytkownikami.

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

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

Aby wylogować użytkownika, wywołaj signOut:

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();