Uwierzytelnij się w Firebase za pomocą Email Link w Androidzie

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

Logowanie przez e-mail ma wiele zalet:

  • Rejestracja i logowanie o niskim współczynniku tarcia.
  • Niższe ryzyko ponownego użycia haseł w różnych aplikacjach, co może podważyć bezpieczeństwo nawet dobrze wybranych haseł.
  • Możliwość uwierzytelniania użytkownika przy jednoczesnym weryfikowaniu, czy 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 się bezpiecznie zalogować bez konieczności podawania (lub zapamiętywania) hasła, które może być uciążliwe na urządzeniu mobilnym.
  • Istniejący użytkownik, który wcześniej zalogował się przy użyciu identyfikatora e-mail (hasło lub federacja), może zostać uaktualniony tak, aby logował się tylko 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. Za pomocą Firebase Android BoM zadeklaruj zależność dla biblioteki Firebase Authentication Android w pliku Gradle modułu (na poziomie aplikacji) (zwykle app/build.gradle ).

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

    Java

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:30.1.0')
    
        // Declare 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 declare the dependency for the Google Play services library and specify its version implementation 'com.google.android.gms:play-services-auth:20.2.0'
    }

    Korzystając z Firebase Android BoM , Twoja aplikacja będzie zawsze używać zgodnych wersji bibliotek Firebase Android.

    (Alternatywnie) Zadeklaruj zależności biblioteki Firebase bez użycia BoM

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

    Pamiętaj, że jeśli korzystasz z wielu bibliotek Firebase w swojej aplikacji, zdecydowanie zalecamy używanie BoM do zarządzania wersjami bibliotek, co zapewnia zgodność wszystkich wersji.

    dependencies {
        // Declare 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:21.0.6'
    // Also declare the dependency for the Google Play services library and specify its version implementation 'com.google.android.gms:play-services-auth:20.2.0'
    }

    Kotlin+KTX

    dependencies {
        // Import the BoM for the Firebase platform
        implementation platform('com.google.firebase:firebase-bom:30.1.0')
    
        // Declare 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-ktx'
    // Also declare the dependency for the Google Play services library and specify its version implementation 'com.google.android.gms:play-services-auth:20.2.0'
    }

    Korzystając z Firebase Android BoM , Twoja aplikacja będzie zawsze używać zgodnych wersji bibliotek Firebase Android.

    (Alternatywnie) Zadeklaruj zależności biblioteki Firebase bez użycia BoM

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

    Pamiętaj, że jeśli korzystasz z wielu bibliotek Firebase w swojej aplikacji, zdecydowanie zalecamy używanie BoM do zarządzania wersjami bibliotek, co zapewnia zgodność wszystkich wersji.

    dependencies {
        // Declare 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-ktx:21.0.6'
    // Also declare the dependency for the Google Play services library and specify its version implementation 'com.google.android.gms:play-services-auth:20.2.0'
    }

Aby logować użytkowników za pomocą linku w e-mailu, 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ę Auth .
  2. Na karcie Metoda logowania włącz dostawcę poczty e-mail/hasła . Pamiętaj, że logowanie za pomocą poczty e-mail/hasła musi być włączone, aby można było korzystać z logowania za pomocą łącza e-mail.
  3. W tej samej sekcji włącz metodę logowania przez łącze E-mail (logowanie bez hasła) .
  4. Kliknij Zapisz .

Aby zainicjować przepływ uwierzytelniania, zaprezentuj użytkownikowi interfejs, który prosi użytkownika o podanie adresu e-mail, a następnie wywołaj sendSignInLinkToEmail , aby zażądać, aby Firebase wysłał łącze uwierzytelniające na adres e-mail użytkownika.

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

    • url : precyzyjny link do umieszczenia i wszelkie dodatkowe stany do przekazania. Domena linku musi znajdować się na białej liście domen autoryzowanych w konsoli Firebase, którą można znaleźć przechodząc do zakładki Metoda logowania (Uwierzytelnianie -> Metoda logowania). Link przekieruje użytkownika do tego adresu URL, jeśli aplikacja nie jest zainstalowana na jego urządzeniu i nie można jej zainstalować.
    • androidPackageName i IOSBundleId : aplikacje używane po otwarciu linku logowania na urządzeniu z systemem Android lub Apple. Dowiedz się więcej o konfigurowaniu Linków dynamicznych Firebase, aby otwierać linki akcji w wiadomościach e-mail w aplikacjach mobilnych.
    • handleCodeInApp : Ustaw na true. Operacja logowania musi być zawsze zakończona w aplikacji, w przeciwieństwie do innych działań e-mail poza pasmem (resetowanie hasła i weryfikacja adresu e-mail). Dzieje się tak, ponieważ na końcu przepływu oczekuje się, że użytkownik zostanie zalogowany, a jego stan uwierzytelniania zostanie zachowany w aplikacji.
    • dynamicLinkDomain : jeśli dla projektu zdefiniowano wiele niestandardowych domen linków dynamicznych, określ, której należy użyć, gdy link ma zostać otwarty za pośrednictwem określonej aplikacji mobilnej (na przykład example.page.link ). W przeciwnym razie pierwsza domena jest wybierana automatycznie.

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

    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 */)
    }

    Aby dowiedzieć się więcej na temat ActionCodeSettings, zapoznaj się z sekcją Passing State in Email Actions .

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

  3. Wyślij łącze uwierzytelniające na adres e-mail użytkownika i zapisz adres e-mail użytkownika na wypadek, gdyby użytkownik zakończył logowanie do poczty e-mail na tym samym urządzeniu.

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

    Kotlin+KTX

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

Obawy dotyczące bezpieczeństwa

Aby uniemożliwić użycie linku do logowania do zalogowania 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 wysłano łącze logowania.

Możesz usprawnić ten przepływ dla użytkowników, którzy otwierają łącze logowania na tym samym urządzeniu, na którym żądają łącza, przechowując ich adres e-mail lokalnie — na przykład przy użyciu 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ć wstrzykiwanie sesji.

Po zakończeniu logowania wszelkie poprzednie 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 z tym samym adresem e-mail i hasłem, hasło użytkownika zostanie usunięte, aby zapobiec ponownemu zalogowaniu się osoby podszywającej się pod własność i utworzyła to niezweryfikowane konto za pomocą niezweryfikowanego adresu e-mail i hasła.

Upewnij się również, że używasz produkcyjnego adresu URL HTTPS, aby uniknąć potencjalnego przechwycenia linku przez serwery pośredniczące.

Kończenie logowania w aplikacji na Androida

Uwierzytelnianie Firebase używa dynamicznych linków Firebase do wysyłania linku w e-mailu na urządzenie mobilne. Aby ukończyć logowanie za pośrednictwem aplikacji mobilnej, aplikacja musi być skonfigurowana do wykrywania przychodzącego łącza do aplikacji, analizowania podstawowego łącza precyzyjnego, a następnie dokończenia logowania.

Firebase Auth używa Firebase Dynamic Links podczas wysyłania linku, który ma zostać otwarty w aplikacji mobilnej. Aby korzystać z tej funkcji, Dynamic Links musi być skonfigurowany w konsoli Firebase.

  1. Włącz Linki dynamiczne Firebase:

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

      Jeśli masz już utworzoną domenę Dynamic Links, zanotuj to. Domena Dynamic Links zazwyczaj wygląda jak w następującym przykładzie:

      example.page.link

      Ta wartość będzie potrzebna podczas konfigurowania aplikacji Apple lub Android do przechwytywania łącza przychodzącego.

  2. Konfiguracja aplikacji na Androida:

    1. Aby obsłużyć te łącza z aplikacji na Androida, w ustawieniach projektu Firebase Console należy określić nazwę pakietu dla Androida. Dodatkowo należy podać SHA-1 i SHA-256 certyfikatu aplikacji.
    2. Po dodaniu domeny łącza dynamicznego i upewnieniu się, że Twoja aplikacja na Androida jest poprawnie skonfigurowana, łącze dynamiczne przekieruje do Twojej aplikacji, zaczynając od działania programu uruchamiającego.
    3. Jeśli chcesz, aby łącze dynamiczne przekierowywało 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 działań e-mail w filtrze intencji. Domyślnie program obsługi akcji e-mail jest hostowany w domenie, jak w poniższym przykładzie:
      PROJECT_ID.firebaseapp.com/
    4. Zastrzeżenia:
      1. Nie określaj adresu URL ustawionego w actionCodeSettings w filtrze intencji.
      2. Podczas tworzenia domeny z dynamicznym linkiem mogłeś również utworzyć krótki link URL. Ten krótki adres URL nie zostanie przekazany; nie konfiguruj filtra intencji, aby wyłapywał 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ć, jaka operacja ma zostać wykonana, lub użyć metod zestawu SDK, takich jak isSignInWithEmailLink , aby sprawdzić, czy łącze otrzymane przez aplikację spełnia Twoje oczekiwania.
    5. Więcej informacji o otrzymywaniu linków dynamicznych znajdziesz w instrukcjach dotyczących odbierania linków dynamicznych na Androida .

Po otrzymaniu linku opisanego powyżej sprawdź, czy jest on przeznaczony do uwierzytelniania za pomocą łącza e-mail i zakończ logowanie.

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

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

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 również połączyć tę metodę uwierzytelniania z istniejącym użytkownikiem. Na przykład użytkownik wcześniej uwierzytelniony u innego dostawcy, taki jak numer telefonu, może dodać tę metodę logowania do swojego istniejącego konta.

Różnica byłaby w drugiej połowie operacji:

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

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

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

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

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

Jednak ponieważ 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, aby zmusić go do 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 obsługujesz logowanie za pomocą hasła i linku za pomocą poczty e-mail, aby odróżnić metodę logowania dla użytkownika hasła/linku, użyj fetchSignInMethodsForEmail . Jest to przydatne w przypadku przepływów polegających na pierwszym identyfikatorze, w których użytkownik jest najpierw proszony o podanie swojego adresu e-mail, a następnie przedstawiany jest sposób logowania:

Java

auth.fetchSignInMethodsForEmail(email)
        .addOnCompleteListener(new OnCompleteListener<SignInMethodQueryResult>() {
            @Override
            public void onComplete(@NonNull Task<SignInMethodQueryResult> task) {
                if (task.isSuccessful()) {
                    SignInMethodQueryResult result = task.getResult();
                    List<String> signInMethods = result.getSignInMethods();
                    if (signInMethods.contains(EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD)) {
                        // User can sign in with email/password
                    } else if (signInMethods.contains(EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD)) {
                        // User can sign in with email/link
                    }
                } else {
                    Log.e(TAG, "Error getting sign in methods for user", task.getException());
                }
            }
        });

Kotlin+KTX

Firebase.auth.fetchSignInMethodsForEmail(email)
        .addOnSuccessListener { result ->
            val signInMethods = result.signInMethods!!
            if (signInMethods.contains(EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD)) {
                // User can sign in with email/password
            } else if (signInMethods.contains(EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD)) {
                // User can sign in with email/link
            }
        }
        .addOnFailureListener { exception ->
            Log.e(TAG, "Error getting sign in methods for user", exception)
        }

Jak opisano powyżej, adres e-mail/hasło i adres e-mail/link są uważane za ten sam EmailAuthProvider e-mail (ten sam PROVIDER_ID ) z różnymi metodami logowania.

Następne kroki

Gdy użytkownik zaloguje się po raz pierwszy, zostanie utworzone nowe konto użytkownika i połączone 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ęść projektu Firebase i może służyć do identyfikowania użytkownika w każdej aplikacji w projekcie, niezależnie od tego, jak się on loguje.

  • W swoich 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 czasu rzeczywistego i usługi Cloud Storage Firebase możesz uzyskać unikalny identyfikator zalogowanego użytkownika ze zmiennej auth i używać go do kontrolowania, do jakich danych użytkownik może uzyskać dostęp.

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

Aby wylogować użytkownika, zadzwoń do signOut :

Java

FirebaseAuth.getInstance().signOut();

Kotlin+KTX

Firebase.auth.signOut()