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

Możesz użyć Firebase Authentication, aby zalogować użytkownika, wysyłając mu e-maila z linkiem, który może kliknąć, aby się zalogować. 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 potrzebuje tylko dostępu do konta 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 uzyskać możliwość logowania się tylko za pomocą adresu e-mail. Na przykład użytkownik, który zapomniał hasło, może się zalogować bez konieczności resetowania hasła.

Zanim zaczniesz

Konfigurowanie projektu na Androida

  1. Jeśli jeszcze tego nie zrobiono, dodaj Firebase do projektu na Androida.

  2. 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ą Firebase Authentication na Androida. Zalecamy używanie Firebase Android BoM do kontrolowania wersji biblioteki.

    W ramach konfigurowania Firebase Authentication musisz też dodać do aplikacji pakiet SDK usług Google Play.

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

    Dzięki użyciu Firebase Android BoMaplikacja zawsze będzie używać zgodnych wersji bibliotek Firebase na Androida.

    (Alternatywnie)  Dodaj zależności biblioteki Firebase bez używania pakietu BoM

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

    Jeśli w aplikacji używasz kilku bibliotek Firebase, zdecydowanie zalecamy korzystanie z BoM do zarządzania wersjami bibliotek. Dzięki temu wszystkie wersje będą ze sobą 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.1.0")
    // Also add the dependency for the Google Play services library and specify its version implementation("com.google.android.gms:play-services-auth:21.3.0")
    }
    Szukasz modułu biblioteki dla Kotlina? Od października 2023 r. (Firebase BoM 32.5.0) deweloperzy Kotlina i Java mogą korzystać z głównego modułu biblioteki (szczegółowe informacje znajdziesz w często zadawanych pytaniach dotyczących tej inicjatywy).

Włączanie logowania za pomocą usługi Email Link w projekcie Firebase

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

  1. W konsoli Firebase otwórz sekcję Autoryzacja.
  2. Na karcie Metoda logowania włącz dostawcę 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 zainicjować proces uwierzytelniania, wyświetl użytkownikowi interfejs, który poprosi go o podanie adresu e-mail, a następnie 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ą być przekazywane. Domena linku musi znajdować się na liście autoryzowanych domen w konsoli Firebase (karta Metoda logowania -> Metoda logowania). Jeśli aplikacja nie jest zainstalowana na urządzeniu użytkownika i nie udało się jej zainstalować, link przekieruje użytkownika na ten adres URL.
    • androidPackageNameiOSBundleId: pomagają Firebase Authentication określić, czy mają utworzyć link tylko do strony internetowej czy do strony mobilnej, który będzie otwierany na urządzeniu z Androidem lub Apple.
    • handleCodeInApp: ustaw na wartość true. W przeciwieństwie do innych działań wykonywanych poza aplikacją (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 autoryzacji powinien być zachowany w aplikacji.
    • linkDomain: jeśli w projekcie zdefiniowano niestandardowe Hostingdomeny linków, określ, której z nich chcesz używać, gdy link ma być otwierany przez określoną aplikację mobilną. W przeciwnym razie domyślnie zostanie wybrana domena domyślna (np. PROJECT_ID.firebaseapp.com).
    • dynamicLinkDomain: wycofany. Nie podawaj tego parametru.

    Kotlin

    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 ustawieniu ActionCodeSettings znajdziesz w sekcji Przekazywanie stanu w działaniach e-mail.

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

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

    Kotlin

    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żywaniu linku logowania przez nieuprawnionego użytkownika lub na nieuprawnionym urządzeniu, Firebase Authentication 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 logowania wszystkie wcześniejsze niesprawdzone mechanizmy logowania zostaną usunięte z konta użytkownika, a istniejące sesje zostaną unieważnione. Jeśli na przykład ktoś wcześniej utworzył niezweryfikowane 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 właściciela konta, która utworzyła to niezweryfikowane konto, ponowne zalogowanie się za pomocą niezweryfikowanego 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.

Logowanie się w aplikacji na Androida

Firebase Authentication używa Firebase Hosting do wysyłania e-maila z linkiem na urządzenie mobilne. Aby umożliwić logowanie się za pomocą aplikacji mobilnej, musisz skonfigurować aplikację tak, aby wykrywała przychodzące linki aplikacji, analizowała precyzyjne linki i dokonywała logowania. Więcej informacji znajdziesz w dokumentacji linków aplikacji na Androida.

Skonfiguruj: Firebase Hosting

Firebase Authentication używa domen Firebase Hosting podczas tworzenia i wysyłania linku, który ma być otwierany w aplikacji mobilnej. Domena domyślna Firebase Hosting została już skonfigurowana.

  1. Skonfiguruj domeny Firebase Hosting:

    W konsoli Firebase otwórz sekcję Hosting.

    • Jeśli chcesz użyć domyślnej domeny dla linku e-maila, który otwiera się w aplikacji mobilnej, otwórz witrynę domyślną i zapisz swoją domyślną domenę Hosting. Domyślna domena Hosting wygląda zwykle tak: PROJECT_ID.firebaseapp.com.

      Będzie ona potrzebna do skonfigurowania aplikacji w celu przechwytywania linków przychodzących.

    • Jeśli chcesz użyć domeny niestandardowej dla linku e-mail, możesz zarejestrować ją w Firebase Hosting i użyć jej jako domeny linku.

  2. Konfigurowanie aplikacji na Androida:

    Aby obsługiwać te linki z aplikacji na Androida, musisz podać nazwę pakietu aplikacji w ustawieniach projektu w konsoli Firebase. Dodatkowo należy podać odciski cyfrowe SHA-1 i SHA-256 certyfikatu aplikacji.

    Jeśli chcesz, aby te linki przekierowywały do określonej aktywności, musisz skonfigurować filtr intencji w pliku AndroidManifest.xml. Filtr intencji powinien wykrywać linki do e-maili w Twojej domenie. W AndroidManifest.xml:

    <intent-filter android:autoVerify="true">
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.BROWSABLE" />
      <category android:name="android.intent.category.DEFAULT" />
      <data
        android:scheme="https"
        android:host="<PROJECT_ID>.firebaseapp.com or your custom domain"
        android:pathPrefix="/__/auth/links" />
    </intent-filter>
    

    Gdy użytkownicy otworzą link do hosta z ścieżką /__/auth/links i określonym przez Ciebie schematem oraz hostem, aplikacja uruchomi aktywność z tym filtrem intencji, aby obsługiwać ten link.

Gdy otrzymasz link w sposób opisany powyżej, sprawdź, czy jest on przeznaczony do uwierzytelniania za pomocą linku e-mail, i zaloguj się.

Kotlin

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 logowaniu się za pomocą linku e-mail w aplikacji Apple znajdziesz w przewodniku po platformach Apple.

Informacje o logowaniu się za pomocą linku e-mail w aplikacji internetowej znajdziesz w przewodniku po interfejsie internetowym.

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:

Kotlin

// 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 go też użyć do ponownego uwierzytelnienia użytkownika, który używa linku e-mail, przed wykonaniem operacji wrażliwej.

Kotlin

// 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 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).

Uwierzytelnianie za pomocą linku e-mail było wcześniej oparte na Firebase Dynamic Links, które zostanie wyłączone 25 sierpnia 2025 r.

Opublikowaliśmy alternatywne rozwiązanie w pakiecie Firebase Authentication Android SDK w wersji 23.2.0 lub nowszej oraz w pakiecie Firebase BoM w wersji 33.9.0 lub nowszej.

Jeśli Twoja aplikacja używa linków w starym formacie, musisz przeprowadzić jej migrację na system oparty na nowym formacie Firebase Hosting.

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 procesów opartych na identyfikatorze.

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 zaloguje się po raz pierwszy, zostanie utworzone nowe konto użytkownika i połączone z danymi logowania, czyli nazwą użytkownika i hasłem, numerem telefonu lub informacjami dostawcy uwierzytelniania, za pomocą których użytkownik się zalogował. To nowe konto jest przechowywane w ramach projektu Firebase i może służyć do identyfikowania użytkownika we wszystkich aplikacjach w projekcie, niezależnie od tego, jak użytkownik się loguje.

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

  • W regułach Firebase Realtime DatabaseCloud Storage Regułach bezpieczeństwa możesz pobrać z zmiennej auth unikalny identyfikator zalogowanego użytkownika i używać go do kontrolowania dostępu użytkownika do danych.

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

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

Kotlin

Firebase.auth.signOut()

Java

FirebaseAuth.getInstance().signOut();