Użyj Uwierzytelniania 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 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 przejść na logowanie się tylko za pomocą adresu e-mail. Na przykład użytkownik, który zapomniał hasło, może się zalogować bez konieczności jego resetowania.
Zanim zaczniesz
Skopiuj fragment kodu inicjalizacji z Firebase konsoli do projektu zgodnie z instrukcjami podanymi w artykule Dodaj Firebase do projektu JavaScript.
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:
- W konsoli Firebase otwórz sekcję Autoryzacja.
- 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.
- W tej samej sekcji włącz metodę logowania Link w e-mailu (logowanie bez hasła).
- Kliknij Zapisz.
Wysyłanie linku uwierzytelniania na adres e-mail użytkownika
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.
Utwórz obiekt
ActionCodeSettings
, który zawiera instrukcje dotyczące tworzenia linku e-maila. Ustaw wartości w tych polach:url
: precyzyjny link do osadzenia i dodatkowe stany, które mają być przekazywane. Domena linku musi zostać dodana do listy autoryzowanych domen w konsoli Firebase. Znajdziesz ją na karcie Metoda logowania (Uwierzytelnianie -> Ustawienia).android
iios
: 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.Web
const actionCodeSettings = { // URL you want to redirect back to. The domain (www.example.com) for this // URL must be in the authorized domains list in the Firebase Console. url: 'https://www.example.com/finishSignUp?cartId=1234', // This must be true. handleCodeInApp: true, iOS: { bundleId: 'com.example.ios' }, android: { packageName: 'com.example.android', installApp: true, minimumVersion: '12' }, dynamicLinkDomain: 'example.page.link' };
Web
var actionCodeSettings = { // URL you want to redirect back to. The domain (www.example.com) for this // URL must be in the authorized domains list in the Firebase Console. url: 'https://www.example.com/finishSignUp?cartId=1234', // This must be true. handleCodeInApp: true, iOS: { bundleId: 'com.example.ios' }, android: { packageName: 'com.example.android', installApp: true, minimumVersion: '12' }, dynamicLinkDomain: 'example.page.link' };
Więcej informacji o
ActionCodeSettings
znajdziesz w sekcji Przekazywanie stanu w działaniach e-mail.Poproś użytkownika o adres e-mail.
Wyślij link uwierzytelniania na adres e-mail użytkownika i zapisz ten adres na wypadek, gdyby użytkownik chciał zalogować się za pomocą adresu e-mail na tym samym urządzeniu.
Web
import { getAuth, sendSignInLinkToEmail } from "firebase/auth"; const auth = getAuth(); sendSignInLinkToEmail(auth, email, actionCodeSettings) .then(() => { // The link was successfully sent. Inform the user. // Save the email locally so you don't need to ask the user for it again // if they open the link on the same device. window.localStorage.setItem('emailForSignIn', email); // ... }) .catch((error) => { const errorCode = error.code; const errorMessage = error.message; // ... });
Web
firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings) .then(() => { // The link was successfully sent. Inform the user. // Save the email locally so you don't need to ask the user for it again // if they open the link on the same device. window.localStorage.setItem('emailForSignIn', email); // ... }) .catch((error) => { var errorCode = error.code; var errorMessage = error.message; // ... });
Zaloguj się, klikając link w e-mailu
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 adres e-mail lokalnie (np. za pomocą localStorage lub plików cookie) podczas wysyłania e-maila z linkiem. 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.
Zalogowanie się na stronie
Format precyzyjnego linku do e-maila jest taki sam jak format używany do działań e-mail poza kanałem (weryfikacja adresu e-mail, resetowanie hasła i odwoływanie zmiany adresu e-mail).
Firebase Auth upraszcza to sprawdzanie, udostępniając interfejs API isSignInWithEmailLink
, który umożliwia sprawdzenie, czy link to link logowania za pomocą adresu e-mail.
Aby dokończyć logowanie na stronie docelowej, zadzwoń pod numer signInWithEmailLink
, podając adres e-mail użytkownika i link do e-maila zawierającego kod jednorazowy.
Web
import { getAuth, isSignInWithEmailLink, signInWithEmailLink } from "firebase/auth"; // Confirm the link is a sign-in with email link. const auth = getAuth(); if (isSignInWithEmailLink(auth, window.location.href)) { // Additional state parameters can also be passed via URL. // This can be used to continue the user's intended action before triggering // the sign-in operation. // Get the email if available. This should be available if the user completes // the flow on the same device where they started it. let email = window.localStorage.getItem('emailForSignIn'); if (!email) { // User opened the link on a different device. To prevent session fixation // attacks, ask the user to provide the associated email again. For example: email = window.prompt('Please provide your email for confirmation'); } // The client SDK will parse the code from the link for you. signInWithEmailLink(auth, email, window.location.href) .then((result) => { // Clear email from storage. window.localStorage.removeItem('emailForSignIn'); // You can access the new user by importing getAdditionalUserInfo // and calling it with result: // getAdditionalUserInfo(result) // You can access the user's profile via: // getAdditionalUserInfo(result)?.profile // You can check if the user is new or existing: // getAdditionalUserInfo(result)?.isNewUser }) .catch((error) => { // Some error occurred, you can inspect the code: error.code // Common errors could be invalid email and invalid or expired OTPs. }); }
Web
// Confirm the link is a sign-in with email link. if (firebase.auth().isSignInWithEmailLink(window.location.href)) { // Additional state parameters can also be passed via URL. // This can be used to continue the user's intended action before triggering // the sign-in operation. // Get the email if available. This should be available if the user completes // the flow on the same device where they started it. var email = window.localStorage.getItem('emailForSignIn'); if (!email) { // User opened the link on a different device. To prevent session fixation // attacks, ask the user to provide the associated email again. For example: email = window.prompt('Please provide your email for confirmation'); } // The client SDK will parse the code from the link for you. firebase.auth().signInWithEmailLink(email, window.location.href) .then((result) => { // Clear email from storage. window.localStorage.removeItem('emailForSignIn'); // You can access the new user via result.user // Additional user info profile not available via: // result.additionalUserInfo.profile == null // You can check if the user is new or existing: // result.additionalUserInfo.isNewUser }) .catch((error) => { // Some error occurred, you can inspect the code: error.code // Common errors could be invalid email and invalid or expired OTPs. }); }
Logowanie w aplikacji mobilnej
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ący link aplikacji, analizowała podłączony precyzyjny link, a następnie przeprowadzała logowanie w taki sam sposób jak w przepływie internetowym.
Więcej informacji o logowaniu się za pomocą linku e-mail w aplikacji na Androida znajdziesz w przewodniku po Androidzie.
Więcej informacji o logowaniu się za pomocą linku e-mail w aplikacji Apple znajdziesz w przewodniku po platformach Apple.
Łączenie/ponowne uwierzytelnianie za pomocą linku e-maila
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:
Web
import { getAuth, linkWithCredential, EmailAuthProvider } from "firebase/auth"; // Construct the email link credential from the current URL. const credential = EmailAuthProvider.credentialWithLink( email, window.location.href); // Link the credential to the current user. const auth = getAuth(); linkWithCredential(auth.currentUser, credential) .then((usercred) => { // The provider is now successfully linked. // The phone user can now sign in with their phone number or email. }) .catch((error) => { // Some error occurred. });
Web
// Construct the email link credential from the current URL. var credential = firebase.auth.EmailAuthProvider.credentialWithLink( email, window.location.href); // Link the credential to the current user. firebase.auth().currentUser.linkWithCredential(credential) .then((usercred) => { // The provider is now successfully linked. // The phone user can now sign in with their phone number or email. }) .catch((error) => { // Some error occurred. });
Można go też użyć do ponownego uwierzytelnienia użytkownika, który używa linku e-mail, przed wykonaniem operacji wrażliwej.
Web
import { getAuth, reauthenticateWithCredential, EmailAuthProvider } from "firebase/auth"; // Construct the email link credential from the current URL. const credential = EmailAuthProvider.credentialWithLink( email, window.location.href); // Re-authenticate the user with this credential. const auth = getAuth(); reauthenticateWithCredential(auth.currentUser, credential) .then((usercred) => { // The user is now successfully re-authenticated and can execute sensitive // operations. }) .catch((error) => { // Some error occurred. });
Web
// Construct the email link credential from the current URL. var credential = firebase.auth.EmailAuthProvider.credentialWithLink( email, window.location.href); // Re-authenticate the user with this credential. firebase.auth().currentUser.reauthenticateWithCredential(credential) .then((usercred) => { // The user is now successfully re-authenticated and can execute sensitive // operations. }) .catch((error) => { // Some error occurred. });
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).
Odradzane: rozróżnianie adresu e-mail i hasła od linku e-mail
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.
Domyślny szablon e-maila do logowania z użyciem linku
Domyślny szablon e-maila zawiera sygnaturę czasową w temacie i treści e-maila, aby kolejne e-maile nie były łączone w jeden wątek, a link nie był ukryty.
Ten szablon dotyczy tych języków:
Kod | Język |
---|---|
ar | arabski |
zh-CN | chiński (uproszczony) |
zh-TW | chiński (tradycyjny) |
nl | niderlandzki |
en | angielski |
en-GB | angielski (Wlk. Brytania) |
fr | francuski |
de | niemiecki |
id | Indonezyjski |
jego | włoski |
ja | japoński |
ko | koreański |
pl | polski |
pt-BR | portugalski (Brazylia) |
pt-PT | portugalski (Portugalia) |
ru | rosyjski |
es | hiszpański |
es-419 | hiszpański (Ameryka Łacińska) |
th | tajski |
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 aplikacjach zalecany sposób sprawdzania stanu uwierzytelniania użytkownika to ustawienie obserwatora w obiekcie
Auth
. Następnie możesz uzyskać podstawowe informacje o profilu użytkownika z obiektuUser
. Zobacz Zarządzanie użytkownikami. W regułach Firebase Realtime Database i Cloud 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
:
Web
import { getAuth, signOut } from "firebase/auth"; const auth = getAuth(); signOut(auth).then(() => { // Sign-out successful. }).catch((error) => { // An error happened. });
Web
firebase.auth().signOut().then(() => { // Sign-out successful. }).catch((error) => { // An error happened. });