Jeśli korzystasz już z Firebase Authentication with Identity Platform, możesz włączyć uwierzytelnianie wielopoziomowe z użyciem SMS-ów. do aplikacji internetowej.
Uwierzytelnianie wielopoziomowe zwiększa bezpieczeństwo aplikacji. Osoby przeprowadzające atak często wykradają hasła i konta społecznościowe, przechwytywanie SMS-a jest co jest utrudnione.
Zanim zaczniesz
- Włącz co najmniej 1 dostawcę, który obsługuje uwierzytelnianie wielopoziomowe. Każdy dostawca obsługuje MFA z wyjątkiem uwierzytelniania telefonicznego, uwierzytelniania anonimowego i Apple Game Center 
- Włącz regiony, w których chcesz używać uwierzytelniania SMS. Firebase używa całkowicie blokujących zasad dotyczących regionów SMS-ów, które pomaga domyślnie tworzyć projekty w bezpieczniejszym stanie. 
- Upewnij się, że Twoja aplikacja weryfikuje adresy e-mail użytkowników. MFA wymaga weryfikacji adresu e-mail. Dzięki temu hakerzy nie będą mogli zarejestrować się w usłudze za pomocą adresu e-mail. których nie należy, a następnie zablokować rzeczywistego właściciela, dodając współczynnik konwersji. 
Korzystanie ze środowiska wielu najemców
Jeśli włączysz uwierzytelnianie wielopoziomowe w aplikacji wielu najemców, upewnij się, aby wykonać poniższe czynności (oprócz pozostałych instrukcji w tym dokumencie):
- W konsoli Google Cloud wybierz najemcę, z którym chcesz współpracować. 
- W kodzie ustaw pole - tenantIdw wystąpieniu- Authna identyfikator najemcy. Przykład:- Web- import { getAuth } from "firebase/auth"; const auth = getAuth(app); auth.tenantId = "myTenantId1";- Web- firebase.auth().tenantId = 'myTenantId1';
Włączanie uwierzytelniania wielopoziomowego
- Otwórz sekcję Uwierzytelnianie > Metoda logowania stronie konsoli Firebase. 
- W sekcji Zaawansowane włącz Uwierzytelnianie wielopoziomowe przez SMS-y. - Wpisz też numery telefonów, które będą używane podczas testowania aplikacji. Chociaż jest to opcjonalne, zdecydowanie zalecamy zarejestrowanie testowych numerów telefonów, i uniknąć ograniczenia w trakcie programowania. 
- Jeśli domena aplikacji nie została jeszcze autoryzowana, dodaj ją do zezwolenia na liście Uwierzytelnianie > Ustawienia stronie konsoli Firebase. 
Wybór wzorca rejestracji
Możesz zdecydować, czy Twoja aplikacja wymaga uwierzytelniania wielopoziomowego i w jaki sposób i kiedy zarejestrować użytkowników. Oto kilka często spotykanych wzorców:
- Zarejestruj drugi składnik logowania użytkownika w ramach rejestracji. Użyj tej , jeśli Twoja aplikacja wymaga uwierzytelniania wielopoziomowego dla wszystkich użytkowników. 
- Zaoferować możliwą do pominięcia opcję rejestracji drugiego składnika podczas rejestracji. aplikacji; które chcą zachęcić do uwierzytelniania wielopoziomowego, ale nie wymagają tego, preferować tę metodę. 
- umożliwia dodanie drugiego składnika z konta lub profilu użytkownika. na stronie zarządzania, a nie na ekranie rejestracji. Pozwala to zminimalizować tarcie podczas rejestracji, a jednocześnie stosować uwierzytelnianie dwuskładnikowe. dostępna dla użytkowników, którzy zwracają uwagę na bezpieczeństwo. 
- Wymagaj stopniowego dodawania drugiego składnika, gdy użytkownik chce uzyskać dostęp funkcje o wyższych wymaganiach w zakresie bezpieczeństwa. 
Konfigurowanie weryfikatora reCAPTCHA
Zanim będzie można wysyłać kody SMS, musisz skonfigurować weryfikatora reCAPTCHA. Firebase używa reCAPTCHA, aby zapobiegać nadużyciom, sprawdzając, czy: prośby o weryfikację numeru telefonu pochodzą z jednej z dozwolonych domen w Twojej aplikacji.
Nie musisz ręcznie konfigurować klienta reCAPTCHA. pakiet SDK klienta
Obiekt RecaptchaVerifier automatycznie tworzy i inicjuje niezbędne
Klucze i tajne klucze klienta.
Używanie niewidocznego reCAPTCHA
Obiekt RecaptchaVerifier obsługuje
niewidoczne reCAPTCHA,
które często weryfikują użytkownika bez konieczności interakcji. Aby użyć
niewidoczna reCAPTCHA, utwórz RecaptchaVerifier z zestawem parametrów size
na invisible i podaj identyfikator elementu interfejsu, który rozpoczyna uwierzytelnianie wielopoziomowe
rejestracja:
Web
import { RecaptchaVerifier, getAuth } from "firebase/auth";
const recaptchaVerifier = new RecaptchaVerifier(getAuth(), "sign-in-button", {
    "size": "invisible",
    "callback": function(response) {
        // reCAPTCHA solved, you can proceed with
        // phoneAuthProvider.verifyPhoneNumber(...).
        onSolvedRecaptcha();
    }
});
Web
var recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
'size': 'invisible',
'callback': function(response) {
  // reCAPTCHA solved, you can proceed with phoneAuthProvider.verifyPhoneNumber(...).
  onSolvedRecaptcha();
}
});
Korzystanie z widżetu reCAPTCHA
Aby użyć widocznego widżetu reCAPTCHA, utwórz element HTML do umieszczenia
widżet, a potem utwórz obiekt RecaptchaVerifier z identyfikatorem tego interfejsu.
kontenera. Możesz też opcjonalnie ustawić wywołania zwrotne, które są wywoływane, gdy
reCAPTCHA jest rozwiązany lub wygasa:
Web
import { RecaptchaVerifier, getAuth } from "firebase/auth";
const recaptchaVerifier = new RecaptchaVerifier(
    getAuth(),
    "recaptcha-container",
    // Optional reCAPTCHA parameters.
    {
      "size": "normal",
      "callback": function(response) {
        // reCAPTCHA solved, you can proceed with
        // phoneAuthProvider.verifyPhoneNumber(...).
        onSolvedRecaptcha();
      },
      "expired-callback": function() {
        // Response expired. Ask user to solve reCAPTCHA again.
        // ...
      }
    }
);
Web
var recaptchaVerifier = new firebase.auth.RecaptchaVerifier(
  'recaptcha-container',
  // Optional reCAPTCHA parameters.
  {
    'size': 'normal',
    'callback': function(response) {
      // reCAPTCHA solved, you can proceed with phoneAuthProvider.verifyPhoneNumber(...).
      // ...
      onSolvedRecaptcha();
    },
    'expired-callback': function() {
      // Response expired. Ask user to solve reCAPTCHA again.
      // ...
    }
  });
Wstępne renderowanie reCAPTCHA
Opcjonalnie możesz wstępnie wyrenderować reCAPTCHA przed uruchomieniem dwuskładnikowego rejestracja:
Web
recaptchaVerifier.render()
    .then(function (widgetId) {
        window.recaptchaWidgetId = widgetId;
    });
Web
recaptchaVerifier.render()
  .then(function(widgetId) {
    window.recaptchaWidgetId = widgetId;
  });
Po rozwiązaniu problemu render() otrzymasz identyfikator widżetu reCAPTCHA, którego możesz użyć
dzwonić pod numery
Interfejs API reCAPTCHA:
var recaptchaResponse = grecaptcha.getResponse(window.recaptchaWidgetId);
RecaptchaVerifier wyodrębnia tę logikę przy użyciu metody verify, więc nie musisz bezpośrednio obsługiwać zmiennej grecaptcha.
Rejestrowanie drugiego składnika
Aby zarejestrować nowy czynnik dodatkowy dla użytkownika:
- Ponownie uwierzytelnij użytkownika. 
- Poproś użytkownika o podanie numeru telefonu. 
- Zainicjuj weryfikatora reCAPTCHA zgodnie z instrukcjami w poprzedniej sekcji. Pomiń ten krok, jeśli instancja RecaptchaVerifier jest już skonfigurowana: - Web- import { RecaptchaVerifier, getAuth } from "firebase/auth"; const recaptchaVerifier = new RecaptchaVerifier( getAuth(),'recaptcha-container-id', undefined);- Web- var recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container-id');
- Pobierz sesję wielopoziomową dla użytkownika: - Web- import { multiFactor } from "firebase/auth"; multiFactor(user).getSession().then(function (multiFactorSession) { // ... });- Web- user.multiFactor.getSession().then(function(multiFactorSession) { // ... })
- Zainicjuj obiekt - PhoneInfoOptionsnumerem telefonu użytkownika sesja wielopoziomowa:- Web- // Specify the phone number and pass the MFA session. const phoneInfoOptions = { phoneNumber: phoneNumber, session: multiFactorSession };- Web- // Specify the phone number and pass the MFA session. var phoneInfoOptions = { phoneNumber: phoneNumber, session: multiFactorSession };
- Wyślij wiadomość weryfikacyjną na telefon użytkownika: - Web- import { PhoneAuthProvider } from "firebase/auth"; const phoneAuthProvider = new PhoneAuthProvider(auth); phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier) .then(function (verificationId) { // verificationId will be needed to complete enrollment. });- Web- var phoneAuthProvider = new firebase.auth.PhoneAuthProvider(); // Send SMS verification code. return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier) .then(function(verificationId) { // verificationId will be needed for enrollment completion. })- Chociaż nie jest to wymagane, warto wcześniej poinformować użytkowników, że otrzyma SMS-a, co spowoduje naliczenie standardowej opłaty. 
- Jeśli żądanie się nie powiedzie, zresetuj reCAPTCHA i powtórz poprzedni krok. aby użytkownik mógł spróbować jeszcze raz. Pamiętaj, że - verifyPhoneNumber()będzie automatycznie resetuje reCAPTCHA po zgłoszeniu błędu, jak Tokeny reCAPTCHA są przeznaczone tylko do jednorazowego użytku.- Web- recaptchaVerifier.clear();- Web- recaptchaVerifier.clear();
- Gdy zostanie wysłany SMS, poproś użytkownika o jego potwierdzenie: - Web- // Ask user for the verification code. Then: const cred = PhoneAuthProvider.credential(verificationId, verificationCode);- Web- // Ask user for the verification code. Then: var cred = firebase.auth.PhoneAuthProvider.credential(verificationId, verificationCode);
- Zainicjuj obiekt - MultiFactorAssertionza pomocą interfejsu- PhoneAuthCredential:- Web- import { PhoneMultiFactorGenerator } from "firebase/auth"; const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);- Web- var multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred);
- Dokończ rejestrację. Opcjonalnie możesz określić wyświetlaną nazwę dla atrybutu drugiego czynnika. Jest to przydatne w przypadku użytkowników z wieloma współczynnikami sekundowymi, ponieważ podczas uwierzytelniania numer telefonu jest maskowany (na np. +1******1234). - Web- // Complete enrollment. This will update the underlying tokens // and trigger ID token change listener. multiFactor(user).enroll(multiFactorAssertion, "My personal phone number");- Web- // Complete enrollment. This will update the underlying tokens // and trigger ID token change listener. user.multiFactor.enroll(multiFactorAssertion, 'My personal phone number');
Poniżej znajdziesz pełny przykład rejestrowania drugiego składnika:
Web
import {
    multiFactor, PhoneAuthProvider, PhoneMultiFactorGenerator,
    RecaptchaVerifier, getAuth
} from "firebase/auth";
const recaptchaVerifier = new RecaptchaVerifier(getAuth(),
    'recaptcha-container-id', undefined);
multiFactor(user).getSession()
    .then(function (multiFactorSession) {
        // Specify the phone number and pass the MFA session.
        const phoneInfoOptions = {
            phoneNumber: phoneNumber,
            session: multiFactorSession
        };
        const phoneAuthProvider = new PhoneAuthProvider(auth);
        // Send SMS verification code.
        return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier);
    }).then(function (verificationId) {
        // Ask user for the verification code. Then:
        const cred = PhoneAuthProvider.credential(verificationId, verificationCode);
        const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);
        // Complete enrollment.
        return multiFactor(user).enroll(multiFactorAssertion, mfaDisplayName);
    });
Web
var recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container-id');
user.multiFactor.getSession().then(function(multiFactorSession) {
  // Specify the phone number and pass the MFA session.
  var phoneInfoOptions = {
    phoneNumber: phoneNumber,
    session: multiFactorSession
  };
  var phoneAuthProvider = new firebase.auth.PhoneAuthProvider();
  // Send SMS verification code.
  return phoneAuthProvider.verifyPhoneNumber(
      phoneInfoOptions, recaptchaVerifier);
})
.then(function(verificationId) {
  // Ask user for the verification code.
  var cred = firebase.auth.PhoneAuthProvider.credential(verificationId, verificationCode);
  var multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred);
  // Complete enrollment.
  return user.multiFactor.enroll(multiFactorAssertion, mfaDisplayName);
});
Gratulacje! Udało Ci się zarejestrować drugi etap uwierzytelniania dla użytkownika.
Logowanie użytkowników przy użyciu drugiego składnika
Aby zalogować użytkownika za pomocą weryfikacji dwuetapowej przez SMS:
- Zaloguj użytkownika na podstawie pierwszego składnika, a potem przechwyć - auth/multi-factor-auth-requiredbłąd. Ten błąd zawiera resolver, wskazówki dotyczące zarejestrowanych drugich czynników oraz bazowa sesja (udało się uwierzytelnić użytkownika za pomocą pierwszego składnika).- Jeśli np. pierwszym czynnikiem były adres e-mail i hasło użytkownika: - Web- import { getAuth, signInWithEmailAndPassword, getMultiFactorResolver} from "firebase/auth"; const auth = getAuth(); signInWithEmailAndPassword(auth, email, password) .then(function (userCredential) { // User successfully signed in and is not enrolled with a second factor. }) .catch(function (error) { if (error.code == 'auth/multi-factor-auth-required') { // The user is a multi-factor user. Second factor challenge is required. resolver = getMultiFactorResolver(auth, error); // ... } else if (error.code == 'auth/wrong-password') { // Handle other errors such as wrong password. } });- Web- firebase.auth().signInWithEmailAndPassword(email, password) .then(function(userCredential) { // User successfully signed in and is not enrolled with a second factor. }) .catch(function(error) { if (error.code == 'auth/multi-factor-auth-required') { // The user is a multi-factor user. Second factor challenge is required. resolver = error.resolver; // ... } else if (error.code == 'auth/wrong-password') { // Handle other errors such as wrong password. } ... });- Jeśli pierwszym składnikiem użytkownika jest dostawca sfederowany, taki jak OAuth, SAML lub OIDC, wykryj błąd po wywołaniu usługi - signInWithPopup()lub- signInWithRedirect()
- Jeśli użytkownik ma zarejestrowanych kilka czynników dodatkowych, zapytaj go, który do użycia: - Web- // Ask user which second factor to use. // You can get the masked phone number via resolver.hints[selectedIndex].phoneNumber // You can get the display name via resolver.hints[selectedIndex].displayName if (resolver.hints[selectedIndex].factorId === PhoneMultiFactorGenerator.FACTOR_ID) { // User selected a phone second factor. // ... } else if (resolver.hints[selectedIndex].factorId === TotpMultiFactorGenerator.FACTOR_ID) { // User selected a TOTP second factor. // ... } else { // Unsupported second factor. }- Web- // Ask user which second factor to use. // You can get the masked phone number via resolver.hints[selectedIndex].phoneNumber // You can get the display name via resolver.hints[selectedIndex].displayName if (resolver.hints[selectedIndex].factorId === firebase.auth.PhoneMultiFactorGenerator.FACTOR_ID) { // User selected a phone second factor. // ... } else if (resolver.hints[selectedIndex].factorId === firebase.auth.TotpMultiFactorGenerator.FACTOR_ID) { // User selected a TOTP second factor. // ... } else { // Unsupported second factor. }
- Zainicjuj weryfikatora reCAPTCHA zgodnie z instrukcjami w poprzedniej sekcji. Pomiń ten krok, jeśli instancja RecaptchaVerifier jest już skonfigurowana: - Web- import { RecaptchaVerifier, getAuth } from "firebase/auth"; recaptchaVerifier = new RecaptchaVerifier(getAuth(), 'recaptcha-container-id', undefined);- Web- var recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container-id');
- Zainicjuj obiekt - PhoneInfoOptionsnumerem telefonu użytkownika sesji wielopoziomowej. Wartości te znajdują się w sekcji- resolverobiekt przekazany do błędu- auth/multi-factor-auth-required:- Web- const phoneInfoOptions = { multiFactorHint: resolver.hints[selectedIndex], session: resolver.session };- Web- var phoneInfoOptions = { multiFactorHint: resolver.hints[selectedIndex], session: resolver.session };
- Wyślij wiadomość weryfikacyjną na telefon użytkownika: - Web- // Send SMS verification code. const phoneAuthProvider = new PhoneAuthProvider(auth); phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier) .then(function (verificationId) { // verificationId will be needed for sign-in completion. });- Web- var phoneAuthProvider = new firebase.auth.PhoneAuthProvider(); // Send SMS verification code. return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier) .then(function(verificationId) { // verificationId will be needed for sign-in completion. })
- Jeśli żądanie się nie powiedzie, zresetuj reCAPTCHA i powtórz poprzedni krok. aby użytkownik mógł spróbować ponownie: - Web- recaptchaVerifier.clear();- Web- recaptchaVerifier.clear();
- Gdy zostanie wysłany SMS, poproś użytkownika o jego potwierdzenie: - Web- const cred = PhoneAuthProvider.credential(verificationId, verificationCode);- Web- // Ask user for the verification code. Then: var cred = firebase.auth.PhoneAuthProvider.credential(verificationId, verificationCode);
- Zainicjuj obiekt - MultiFactorAssertionza pomocą interfejsu- PhoneAuthCredential:- Web- const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);- Web- var multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred);
- Wywołaj - resolver.resolveSignIn(), aby ukończyć dodatkowe uwierzytelnianie. Następnie możesz uzyskać dostęp do pierwotnych wyników logowania, które obejmują standardowe dane uwierzytelniające i dane uwierzytelniające specyficzne dla dostawcy:- Web- // Complete sign-in. This will also trigger the Auth state listeners. resolver.resolveSignIn(multiFactorAssertion) .then(function (userCredential) { // userCredential will also contain the user, additionalUserInfo, optional // credential (null for email/password) associated with the first factor sign-in. // For example, if the user signed in with Google as a first factor, // userCredential.additionalUserInfo will contain data related to Google // provider that the user signed in with. // - user.credential contains the Google OAuth credential. // - user.credential.accessToken contains the Google OAuth access token. // - user.credential.idToken contains the Google OAuth ID token. });- Web- // Complete sign-in. This will also trigger the Auth state listeners. resolver.resolveSignIn(multiFactorAssertion) .then(function(userCredential) { // userCredential will also contain the user, additionalUserInfo, optional // credential (null for email/password) associated with the first factor sign-in. // For example, if the user signed in with Google as a first factor, // userCredential.additionalUserInfo will contain data related to Google provider that // the user signed in with. // user.credential contains the Google OAuth credential. // user.credential.accessToken contains the Google OAuth access token. // user.credential.idToken contains the Google OAuth ID token. });
Poniżej znajdziesz pełny przykład logowania użytkownika wielopoziomowego:
Web
import {
    getAuth,
    getMultiFactorResolver,
    PhoneAuthProvider,
    PhoneMultiFactorGenerator,
    RecaptchaVerifier,
    signInWithEmailAndPassword
} from "firebase/auth";
const recaptchaVerifier = new RecaptchaVerifier(getAuth(),
    'recaptcha-container-id', undefined);
const auth = getAuth();
signInWithEmailAndPassword(auth, email, password)
    .then(function (userCredential) {
        // User is not enrolled with a second factor and is successfully
        // signed in.
        // ...
    })
    .catch(function (error) {
        if (error.code == 'auth/multi-factor-auth-required') {
            const resolver = getMultiFactorResolver(auth, error);
            // Ask user which second factor to use.
            if (resolver.hints[selectedIndex].factorId ===
                PhoneMultiFactorGenerator.FACTOR_ID) {
                const phoneInfoOptions = {
                    multiFactorHint: resolver.hints[selectedIndex],
                    session: resolver.session
                };
                const phoneAuthProvider = new PhoneAuthProvider(auth);
                // Send SMS verification code
                return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
                    .then(function (verificationId) {
                        // Ask user for the SMS verification code. Then:
                        const cred = PhoneAuthProvider.credential(
                            verificationId, verificationCode);
                        const multiFactorAssertion =
                            PhoneMultiFactorGenerator.assertion(cred);
                        // Complete sign-in.
                        return resolver.resolveSignIn(multiFactorAssertion)
                    })
                    .then(function (userCredential) {
                        // User successfully signed in with the second factor phone number.
                    });
            } else if (resolver.hints[selectedIndex].factorId ===
                       TotpMultiFactorGenerator.FACTOR_ID) {
                // Handle TOTP MFA.
                // ...
            } else {
                // Unsupported second factor.
            }
        } else if (error.code == 'auth/wrong-password') {
            // Handle other errors such as wrong password.
        }
    });
Web
var resolver;
firebase.auth().signInWithEmailAndPassword(email, password)
  .then(function(userCredential) {
    // User is not enrolled with a second factor and is successfully signed in.
    // ...
  })
  .catch(function(error) {
    if (error.code == 'auth/multi-factor-auth-required') {
      resolver = error.resolver;
      // Ask user which second factor to use.
      if (resolver.hints[selectedIndex].factorId ===
          firebase.auth.PhoneMultiFactorGenerator.FACTOR_ID) {
        var phoneInfoOptions = {
          multiFactorHint: resolver.hints[selectedIndex],
          session: resolver.session
        };
        var phoneAuthProvider = new firebase.auth.PhoneAuthProvider();
        // Send SMS verification code
        return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
          .then(function(verificationId) {
            // Ask user for the SMS verification code.
            var cred = firebase.auth.PhoneAuthProvider.credential(
                verificationId, verificationCode);
            var multiFactorAssertion =
                firebase.auth.PhoneMultiFactorGenerator.assertion(cred);
            // Complete sign-in.
            return resolver.resolveSignIn(multiFactorAssertion)
          })
          .then(function(userCredential) {
            // User successfully signed in with the second factor phone number.
          });
      } else if (resolver.hints[selectedIndex].factorId ===
        firebase.auth.TotpMultiFactorGenerator.FACTOR_ID) {
        // Handle TOTP MFA.
        // ...
      } else {
        // Unsupported second factor.
      }
    } else if (error.code == 'auth/wrong-password') {
      // Handle other errors such as wrong password.
    } ...
  });
Gratulacje! Udało Ci się zalogować użytkownika za pomocą uwierzytelniania wielopoziomowego uwierzytelnianie.
Co dalej?
- Zarządzanie użytkownikami uwierzytelniania wielopoziomowego automatycznie za pomocą Admin SDK.