Join us in person and online for Firebase Summit on October 18, 2022. Learn how Firebase can help you accelerate app development, release your app with confidence, and scale with ease. Register now

Uwierzytelnij się w Firebase za pomocą linku e-mail w JavaScript

Zadbaj o dobrą organizację dzięki kolekcji Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.

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

Jeśli jeszcze tego nie zrobiłeś, skopiuj fragment inicjujący z konsoli Firebase do swojego projektu zgodnie z opisem w sekcji Dodawanie Firebase do projektu JavaScript .

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. Domenę linku należy dodać do listy autoryzowanych domen Konsoli Firebase, którą można znaleźć przechodząc do zakładki Metoda logowania (Uwierzytelnianie -> Metoda logowania).
    • android i ios : aplikacje używane po otwarciu linku do 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.

      Web version 9

      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 version 8

      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'
      };

    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.

    Web version 9

    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 version 8

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

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ą link do logowania na tym samym urządzeniu, na którym żądają linku, przechowując ich adres e-mail lokalnie — na przykład przy użyciu localStorage lub plików cookie — 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 na stronie internetowej

Format głębokiego linku w e-mailu jest taki sam, jak format używany w przypadku działań e-mail poza pasmem (weryfikacja adresu e-mail, resetowanie hasła i odwoływanie zmiany adresu e-mail). Firebase Auth upraszcza to sprawdzenie, udostępniając interfejs API isSignInWithEmailLink do sprawdzania, czy link jest linkiem do logowania za pomocą adresu e-mail.

Aby zakończyć logowanie na stronie docelowej, zadzwoń do signInWithEmailLink z adresem e-mail użytkownika i rzeczywistym linkiem e-mail zawierającym kod jednorazowy.

Web version 9

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

Web version 8

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

Kończenie logowania w aplikacji mobilnej

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, przeanalizowania podstawowego łącza precyzyjnego, a następnie dokończenia logowania tak, jak odbywa się to za pośrednictwem przepływu internetowego.

Aby dowiedzieć się więcej o tym, jak obsługiwać logowanie za pomocą łącza e-mail w aplikacji na Androida, zapoznaj się z przewodnikiem po systemie Android .

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 .

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:

Web version 9

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 version 8

// 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 to również wykorzystać do ponownego uwierzytelnienia użytkownika łącza e-mail przed uruchomieniem poufnej operacji.

Web version 9

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 version 8

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

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:

Web version 9

import { getAuth, fetchSignInMethodsForEmail, EmailAuthProvider} from "firebase/auth";

// After asking the user for their email.
const email = window.prompt('Please provide your email');

const auth = getAuth();
fetchSignInMethodsForEmail(auth, email)
  .then((signInMethods) => {
    // This returns the same array as fetchProvidersForEmail but for email
    // provider identified by 'password' string, signInMethods would contain 2
    // different strings:
    // 'emailLink' if the user previously signed in with an email/link
    // 'password' if the user has a password.
    // A user could have both.
    if (signInMethods.indexOf(EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/password.
    }
    if (signInMethods.indexOf(EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/link.
    }
  })
  .catch((error) => {
    // Some error occurred, you can inspect the code: error.code
  });

Web version 8

// After asking the user for their email.
var email = window.prompt('Please provide your email');
firebase.auth().fetchSignInMethodsForEmail(email)
  .then((signInMethods) => {
    // This returns the same array as fetchProvidersForEmail but for email
    // provider identified by 'password' string, signInMethods would contain 2
    // different strings:
    // 'emailLink' if the user previously signed in with an email/link
    // 'password' if the user has a password.
    // A user could have both.
    if (signInMethods.indexOf(
            firebase.auth.EmailAuthProvider.EMAIL_PASSWORD_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/password.
    }
    if (signInMethods.indexOf(
            firebase.auth.EmailAuthProvider.EMAIL_LINK_SIGN_IN_METHOD) != -1) {
      // User can sign in with email/link.
    }
  })
  .catch((error) => {
    // Some error occurred, you can inspect the code: error.code
  });

Jak opisano powyżej, adres e-mail/hasło i adres e-mail/link są uważane za ten sam firebase.auth.EmailAuthProvider (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 aplikacjach zalecanym sposobem poznania stanu uwierzytelniania użytkownika jest ustawienie obserwatora na obiekcie Auth . Następnie można uzyskać podstawowe informacje o profilu użytkownika z obiektu User . 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 :

Web version 9

import { getAuth, signOut } from "firebase/auth";

const auth = getAuth();
signOut(auth).then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});

Web version 8

firebase.auth().signOut().then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});