Uwierzytelnij się w Firebase za pomocą łącza e-mail w systemie Android

Możesz użyć uwierzytelniania Firebase, aby zalogować użytkownika, wysyłając mu wiadomość e-mail zawierającą link, który może kliknąć, aby się zalogować. W tym procesie weryfikowany jest również adres e-mail użytkownika.

Logowanie się przez e-mail ma wiele zalet:

  • Rejestracja i logowanie o niskim współczynniku tarcia.
  • Mniejsze ryzyko ponownego użycia hasła w różnych aplikacjach, co może podważyć bezpieczeństwo nawet dobrze wybranych haseł.
  • Możliwość uwierzytelnienia użytkownika przy jednoczesnej weryfikacji, czy użytkownik jest prawowitym właścicielem adresu e-mail.
  • Aby się zalogować, użytkownik potrzebuje jedynie dostępnego konta e-mail. Nie jest wymagane posiadanie numeru telefonu ani konta w mediach społecznościowych.
  • Użytkownik może zalogować się bezpiecznie, bez konieczności podawania (lub zapamiętywania) hasła, co na urządzeniu mobilnym może być uciążliwe.
  • Istniejącego użytkownika, który wcześniej logował się przy użyciu identyfikatora e-mail (hasła lub konta federacyjnego), można uaktualnić tak, aby logował się wyłącznie przy użyciu adresu e-mail. Na przykład użytkownik, który zapomniał hasła, nadal może się zalogować bez konieczności resetowania hasła.

Zanim zaczniesz

Skonfiguruj swój projekt na Androida

  1. Jeśli jeszcze tego nie zrobiłeś, dodaj Firebase do swojego projektu na Androida .

  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ść dla uwierzytelniania Firebase biblioteka dla Androida. Zalecamy używanie Firebase Android BoM do kontrolowania wersji bibliotek.

    Ponadto w ramach konfigurowania uwierzytelniania Firebase musisz dodać do swojej aplikacji pakiet SDK usług Google Play.

    dependencies {
        // Import the BoM for the Firebase platform
        implementation(platform("com.google.firebase:firebase-bom:32.8.0"))
    
        // 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.0.0")
    }

    Korzystając z Firebase Android BoM , Twoja aplikacja będzie zawsze korzystać z kompatybilnych wersji bibliotek Firebase Android.

    (Alternatywa) Dodaj zależności biblioteki Firebase bez użycia BoM

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

    Pamiętaj, że jeśli używasz w swojej aplikacji wielu bibliotek Firebase, zdecydowanie zalecamy używanie BoM do zarządzania wersjami bibliotek, co gwarantuje, że wszystkie wersje będą kompatybilne.

    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:22.3.1")
    // Also add the dependency for the Google Play services library and specify its version implementation("com.google.android.gms:play-services-auth:21.0.0")
    }
    Szukasz modułu bibliotecznego specyficznego dla Kotlina? Począwszy od października 2023 r. (Firebase BoM 32.5.0) zarówno programiści Kotlin, jak i Java mogą polegać na głównym module biblioteki (więcej informacji można znaleźć w często zadawanych pytaniach dotyczących tej inicjatywy ).

Aby logować użytkowników za pomocą łącza e-mail, musisz najpierw włączyć dostawcę poczty e-mail i metodę logowania za pomocą łącza e-mail dla swojego projektu Firebase:

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

Aby zainicjować proces uwierzytelniania, wyświetl użytkownikowi interfejs, który poprosi go o podanie adresu e-mail, a następnie wywołaj sendSignInLinkToEmail , aby poprosić Firebase o przesłanie linku uwierzytelniającego na adres e-mail użytkownika.

  1. Skonstruuj obiekt ActionCodeSettings , który udostępnia Firebase instrukcje dotyczące tworzenia łącza e-mail. Ustaw następujące pola:

    • url : precyzyjny link do umieszczenia i wszelki dodatkowy stan, który należy przekazać. Domena linku musi znajdować się na białej liście w konsoli Firebase Console, na liście autoryzowanych domen, którą można znaleźć przechodząc do zakładki Metoda logowania (Uwierzytelnianie -> Metoda logowania). Link przekieruje użytkownika na ten adres URL, jeśli aplikacja nie jest zainstalowana na jego urządzeniu i nie można było jej zainstalować.
    • androidPackageName i IOSBundleId : aplikacje, które mają być używane po otwarciu łącza logowania na urządzeniu z systemem Android lub Apple. Dowiedz się więcej o konfigurowaniu łączy dynamicznych Firebase w celu otwierania linków do działań w wiadomościach e-mail za pośrednictwem aplikacji mobilnych.
    • handleCodeInApp : Ustaw na true. Operację logowania należy zawsze przeprowadzić w aplikacji, w przeciwieństwie do innych pozapasmowych działań e-mailowych (reset hasła i weryfikacja adresu e-mail). Dzieje się tak, ponieważ na końcu przepływu oczekuje się, że użytkownik będzie zalogowany, a jego stan uwierzytelnienia zostanie utrwalony w aplikacji.
    • dynamicLinkDomain : Jeśli dla projektu zdefiniowano wiele niestandardowych domen łączy dynamicznych, określ, która z nich ma być używana, gdy łącze ma być otwierane za pośrednictwem określonej aplikacji mobilnej (na przykład example.page.link ). W przeciwnym wypadku automatycznie wybierana jest 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();

    Aby dowiedzieć się więcej na temat ActionCodeSettings, zapoznaj się z sekcją Przekazywanie stanu w akcjach e-mailowych .

  2. Poproś użytkownika o adres e-mail.

  3. Wyślij link uwierzytelniający na adres e-mail użytkownika i zapisz adres e-mail użytkownika na wypadek, gdyby użytkownik ukończył logowanie e-mailem 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.");
                    }
                }
            });

Obawy dotyczące bezpieczeństwa

Aby zapobiec używaniu linku do logowania do logowania się jako niezamierzony użytkownik lub na niezamierzonym urządzeniu, Firebase Auth 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 usprawnić ten przepływ dla użytkowników, którzy otwierają link do logowania na tym samym urządzeniu, na którym proszą o łącze, przechowując lokalnie ich adresy e-mail — na przykład za pomocą SharedPreferences — podczas wysyłania wiadomości e-mail logowania. Następnie użyj tego adresu, aby zakończyć przepływ. Nie podawaj adresu e-mail użytkownika w parametrach adresu URL przekierowania i używaj go ponownie, ponieważ może to umożliwić zastrzyki sesji.

Po zakończeniu logowania wszelkie dotychczasowe niezweryfikowane mechanizmy logowania zostaną usunięte z użytkownika, a wszelkie istniejące sesje zostaną unieważnione. Na przykład, jeśli ktoś wcześniej utworzył niezweryfikowane konto przy użyciu tego samego adresu e-mail i hasła, hasło użytkownika zostanie usunięte, aby uniemożliwić osobie podszywającej się, która rościła sobie prawo własności i utworzyła to niezweryfikowane konto, ponowne zalogowanie się przy użyciu niezweryfikowanego adresu e-mail i hasła.

Upewnij się także, że używasz adresu URL HTTPS w środowisku produkcyjnym, aby uniknąć potencjalnego przechwycenia łącza przez serwery pośredniczące.

Kończenie logowania w aplikacji na Androida

Uwierzytelnianie Firebase wykorzystuje łącza dynamiczne Firebase do wysyłania linku e-mail na urządzenie mobilne. Aby móc logować się za pomocą aplikacji mobilnej, należy ją skonfigurować tak, aby wykrywała przychodzące łącze do aplikacji, analizowała głęboki link, a następnie dokończyła logowanie.

Firebase Auth korzysta z Firebase Dynamic Links podczas wysyłania linku, który ma zostać otwarty w aplikacji mobilnej. Aby móc korzystać z tej funkcji, należy skonfigurować łącza dynamiczne w konsoli Firebase.

  1. Włącz łącza dynamiczne Firebase:

    1. W konsoli Firebase otwórz sekcję Linki dynamiczne .
    2. Jeśli jeszcze nie zaakceptowałeś warunków Linków Dynamicznych i nie utworzyłeś domeny Dynamic Links, zrób to teraz.

      Jeśli masz już domenę Dynamic Links, zanotuj ją. Domena Linków Dynamicznych zazwyczaj wygląda jak w poniższym przykładzie:

      example.page.link

      Ta wartość będzie Ci potrzebna podczas konfigurowania aplikacji na urządzenia Apple lub Android w celu przechwytywania łącza przychodzącego.

  2. Konfiguracja aplikacji na Androida:

    1. Aby obsłużyć te linki z aplikacji na Androida, należy określić nazwę pakietu Androida w ustawieniach projektu konsoli Firebase. Ponadto należy podać SHA-1 i SHA-256 certyfikatu aplikacji.
    2. Teraz, gdy dodałeś domenę z linkiem dynamicznym i upewniłeś się, że Twoja aplikacja na Androida jest poprawnie skonfigurowana, link dynamiczny przekieruje do Twojej aplikacji, zaczynając od działania programu uruchamiającego.
    3. Jeśli chcesz, aby link dynamiczny przekierowywał do określonej aktywności, musisz skonfigurować filtr intencji w pliku AndroidManifest.xml . Można to zrobić, określając domenę łącza dynamicznego lub procedurę obsługi akcji e-mail w filtrze intencji. Domyślnie moduł obsługi akcji e-mail jest hostowany w domenie, jak w poniższym przykładzie:
      PROJECT_ID.firebaseapp.com/
    4. Zastrzeżenia:
      1. Nie podawaj adresu URL ustawionego w actionCodeSettings w filtrze intencji.
      2. Podczas tworzenia domeny z linkiem dynamicznym mogłeś także utworzyć krótki link 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ędziesz w stanie przechwycić różnych linków dynamicznych w różnych częściach aplikacji. Możesz jednak sprawdzić parametr zapytania mode w łączu, aby zobaczyć, jaką operację próbuje się wykonać, lub użyć metod zestawu SDK, takich jak isSignInWithEmailLink , aby sprawdzić, czy link otrzymany przez Twoją aplikację działa zgodnie z oczekiwaniami.
    5. Więcej informacji na temat otrzymywania linków dynamicznych znajdziesz w instrukcji odbierania linków dynamicznych w systemie Android .

Po otrzymaniu linku w sposób opisany powyżej sprawdź, czy służy on do uwierzytelniania łącza e-mail i dokończ logowanie.

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

Aby dowiedzieć się więcej na temat obsługi logowania za pomocą łącza e-mail w aplikacji Apple, zapoznaj się z przewodnikiem po platformach Apple .

Aby dowiedzieć się, jak obsługiwać logowanie za pomocą łącza e-mail w aplikacji internetowej, zapoznaj się z przewodnikiem internetowym .

Możesz także powiązać tę metodę uwierzytelniania z istniejącym użytkownikiem. Na przykład użytkownik uwierzytelniony wcześniej u innego dostawcy, na przykład za pomocą numeru telefonu, może dodać tę metodę logowania do swojego istniejącego konta.

Różnica będzie dotyczyć drugiej połowy 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());
                }
            }
        });

Można to również wykorzystać do ponownego uwierzytelnienia użytkownika łącza e-mail przed wykonaniem poufnej operacji.

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

Ponieważ jednak przepływ może zakończyć się na innym urządzeniu, na którym pierwotny użytkownik nie był zalogowany, przepływ ten może nie zostać ukończony. W takim przypadku użytkownikowi może zostać wyświetlony błąd mający na celu wymuszenie otwarcia łącza na tym samym urządzeniu. W łączu można przekazać pewien stan, aby dostarczyć informacji o typie operacji i identyfikatorze użytkownika.

Jeśli projekt utworzyłeś 15 września 2023 r. lub później, ochrona wyliczeń 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 w celu implementacji przepływów opartych na identyfikatorze.

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

Więcej szczegółów znajdziesz w dokumentacji dotyczącej ochrony wyliczeń e-maili .

Następne kroki

Gdy użytkownik zaloguje się po raz pierwszy, zostanie utworzone nowe konto użytkownika i powiązane z poświadczeniami — czyli nazwą użytkownika i hasłem, numerem telefonu lub informacjami o dostawcy uwierzytelniania — za pomocą których użytkownik się zalogował. To nowe konto jest przechowywane jako część Twojego projektu Firebase i może służyć do identyfikowania użytkownika w każdej aplikacji w Twoim projekcie, niezależnie od tego, w jaki sposób użytkownik się loguje.

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

  • W regułach bezpieczeństwa bazy danych Firebase Realtime i Cloud Storage możesz uzyskać unikalny identyfikator zalogowanego użytkownika ze zmiennej auth i użyć go do kontrolowania, do jakich danych użytkownik może uzyskać dostęp.

Możesz zezwolić użytkownikom na logowanie się do aplikacji przy użyciu wielu dostawców uwierzytelniania, łącząc poświadczenia dostawcy uwierzytelniania z istniejącym kontem użytkownika.

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

Kotlin+KTX

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();