Uwierzytelniaj w Firebase za pomocą numeru telefonu z użyciem JavaScriptu

Możesz użyć Firebase Authentication, aby zalogować użytkownika, wysyłając SMS-a na jego telefon. Użytkownik loguje się za pomocą jednorazowego kodu zawartego w SMS-ie.

Najłatwiejszym sposobem dodania do aplikacji logowania za pomocą numeru telefonu jest skorzystanie z FirebaseUI, które zawiera gotowy widget logowania, który wdraża przepływy logowania za pomocą numeru telefonu, a także logowania na podstawie hasła i logowania sfederowanego. Ten dokument opisuje, jak za pomocą pakietu SDK Firebase wdrożyć proces logowania za pomocą numeru telefonu.

Zanim zaczniesz

Skopiuj fragment kodu inicjalizacji z Firebase konsoli do projektu zgodnie z instrukcjami podanymi w artykule Dodaj Firebase do projektu JavaScript.

Potencjalne problemy z bezpieczeństwem

Uwierzytelnianie za pomocą tylko numeru telefonu jest wygodne, ale mniej bezpieczne niż inne dostępne metody, ponieważ numer telefonu można łatwo przekazać innemu użytkownikowi. Ponadto na urządzeniach z wieloma profilami użytkowników każdy użytkownik, który może odbierać SMS-y, może zalogować się na konto za pomocą numeru telefonu urządzenia.

Jeśli w aplikacji używasz logowania na podstawie numeru telefonu, powinnaś je oferować razem z bardziej bezpiecznymi metodami logowania i informować użytkowników o konsekwencjach zabezpieczeń związanych z logowaniem na podstawie numeru telefonu.

Włączanie logowania za pomocą numeru telefonu w projekcie Firebase

Aby umożliwić użytkownikom logowanie się za pomocą SMS-a, musisz najpierw włączyć metodę logowania za pomocą numeru telefonu w projekcie Firebase:

  1. W konsoli Firebase otwórz sekcję Uwierzytelnianie.
  2. Na stronie Metoda logowania włącz metodę logowania Numer telefonu.
  3. Na tej samej stronie, jeśli domeny, która będzie hostować Twoją aplikację, nie ma w sekcji Domeny przekierowań OAuth, dodaj swoją domenę. Pamiętaj, że localhost nie jest dozwoloną domeną hostowaną na potrzeby uwierzytelniania przez telefon.

Konfigurowanie weryfikatora reCAPTCHA

Zanim umożliwisz użytkownikom logowanie się za pomocą numerów telefonów, musisz skonfigurować weryfikator reCAPTCHA w Firebase. Firebase używa reCAPTCHA, aby zapobiegać nadużyciom, np. przez zapewnienie, że żądanie weryfikacji numeru telefonu pochodzi z jednej z dozwolonych domen aplikacji.

Nie musisz ręcznie konfigurować klienta reCAPTCHA. Gdy używasz obiektu RecaptchaVerifier pakietu Firebase SDK, Firebase automatycznie tworzy i obsługuje wszystkie niezbędne klucze i klucze tajne klienta.

Obiekt RecaptchaVerifier obsługuje niewidoczny reCAPTCHA, który często może zweryfikować użytkownika bez konieczności podejmowania przez niego żadnych działań, a także widżet reCAPTCHA, który zawsze wymaga interakcji użytkownika, aby zakończyć proces.

Wyrenderowany reCAPTCHA może być zlokalizowany zgodnie z preferencjami użytkownika przez zaktualizowanie kodu języka w instancji Auth przed wyrenderowaniem reCAPTCHA. Powyższe tłumaczenie będzie też stosowane w wiadomości SMS wysyłanej do użytkownika z kodem weryfikacyjnym.

Web

import { getAuth } from "firebase/auth";

const auth = getAuth();
auth.languageCode = 'it';
// To apply the default browser preference instead of explicitly setting it.
// auth.useDeviceLanguage();

Web

firebase.auth().languageCode = 'it';
// To apply the default browser preference instead of explicitly setting it.
// firebase.auth().useDeviceLanguage();

Korzystanie z niewidocznej usługi reCAPTCHA

Aby użyć niewidocznego reCAPTCHA, utwórz obiekt RecaptchaVerifier z parametrem size ustawionym na invisible, podając identyfikator przycisku, który przesyła formularz logowania. Przykład:

Web

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

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'sign-in-button', {
  'size': 'invisible',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    onSignInSubmit();
  }
});

Web

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
  'size': 'invisible',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    onSignInSubmit();
  }
});

Korzystanie z widżetu reCAPTCHA

Aby użyć widocznego widżetu reCAPTCHA, utwórz na stronie element, który będzie go zawierał, a potem obiekt RecaptchaVerifier, podając identyfikator kontenera.

Web

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

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', {});

Web

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');

Opcjonalnie: określ parametry reCAPTCHA

Opcjonalnie możesz ustawić w obiekcie RecaptchaVerifier funkcje wywołania zwrotnego, które są wywoływane, gdy użytkownik rozwiąże CAPTCHA lub gdy reCAPTCHA wygaśnie, zanim użytkownik prześle formularz:

Web

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

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', {
  'size': 'normal',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    // ...
  },
  'expired-callback': () => {
    // Response expired. Ask user to solve reCAPTCHA again.
    // ...
  }
});

Web

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container', {
  'size': 'normal',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    // ...
  },
  'expired-callback': () => {
    // Response expired. Ask user to solve reCAPTCHA again.
    // ...
  }
});

Opcjonalnie: wstępnie renderuj reCAPTCHA

Jeśli chcesz zrenderować reCAPTCHA przed przesłaniem żądania logowania, wywołaj funkcję render:

Web

recaptchaVerifier.render().then((widgetId) => {
  window.recaptchaWidgetId = widgetId;
});

Web

recaptchaVerifier.render().then((widgetId) => {
  window.recaptchaWidgetId = widgetId;
});

Po zakończeniu działania funkcji render otrzymasz identyfikator widgeta reCAPTCHA, którego możesz użyć do wywołania interfejsu reCAPTCHA API:

Web

const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);

Web

const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);

Wysyłanie kodu weryfikacyjnego na telefon użytkownika

Aby rozpocząć logowanie za pomocą numeru telefonu, wyświetl użytkownikowi interfejs z prośbą o podanie numeru telefonu, a potem wywołaj funkcjęsignInWithPhoneNumber, aby poprosić Firebase o wysłanie kodu uwierzytelniania do telefonu użytkownika SMS-em:

  1. Uzyskaj numer telefonu użytkownika.

    Wymagania prawne różnią się w zależności od kraju, ale zgodnie ze sprawdzoną metodą i aby określić oczekiwania użytkowników, należy ich poinformować, że jeśli korzystają z logowania przez telefon, mogą otrzymać SMS-a z weryfikacją i standardowymi opłatami.

  2. Wywołaj funkcję signInWithPhoneNumber, przekazując jej numer telefonu użytkownika i utworzony wcześniej parametr RecaptchaVerifier.

    Web

    import { getAuth, signInWithPhoneNumber } from "firebase/auth";
    
    const phoneNumber = getPhoneNumberFromUserInput();
    const appVerifier = window.recaptchaVerifier;
    
    const auth = getAuth();
    signInWithPhoneNumber(auth, phoneNumber, appVerifier)
        .then((confirmationResult) => {
          // SMS sent. Prompt user to type the code from the message, then sign the
          // user in with confirmationResult.confirm(code).
          window.confirmationResult = confirmationResult;
          // ...
        }).catch((error) => {
          // Error; SMS not sent
          // ...
        });

    Web

    const phoneNumber = getPhoneNumberFromUserInput();
    const appVerifier = window.recaptchaVerifier;
    firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
        .then((confirmationResult) => {
          // SMS sent. Prompt user to type the code from the message, then sign the
          // user in with confirmationResult.confirm(code).
          window.confirmationResult = confirmationResult;
          // ...
        }).catch((error) => {
          // Error; SMS not sent
          // ...
        });
    Jeśli signInWithPhoneNumber spowoduje błąd, zresetuj reCAPTCHA, aby użytkownik mógł spróbować ponownie:
    grecaptcha.reset(window.recaptchaWidgetId);
    
    // Or, if you haven't stored the widget ID:
    window.recaptchaVerifier.render().then(function(widgetId) {
      grecaptcha.reset(widgetId);
    });

Metoda signInWithPhoneNumber wysyła użytkownikowi wyzwanie reCAPTCHA, a jeśli użytkownik je przejdzie, Firebase Authentication wysyła SMS-a z kodem weryfikacyjnym na telefon użytkownika.

Logowanie użytkownika za pomocą kodu weryfikacyjnego

Po zakończeniu wywołania funkcji signInWithPhoneNumber poproś użytkownika o wpisanie kodu weryfikacyjnego otrzymanego SMS-em. Następnie zaloguj użytkownika, przekazując kod do metody confirm obiektu ConfirmationResult przekazanego do obsługi realizacji signInWithPhoneNumber (czyli do bloku then). Przykład:

Web

const code = getCodeFromUserInput();
confirmationResult.confirm(code).then((result) => {
  // User signed in successfully.
  const user = result.user;
  // ...
}).catch((error) => {
  // User couldn't sign in (bad verification code?)
  // ...
});

Web

const code = getCodeFromUserInput();
confirmationResult.confirm(code).then((result) => {
  // User signed in successfully.
  const user = result.user;
  // ...
}).catch((error) => {
  // User couldn't sign in (bad verification code?)
  // ...
});

Jeśli wywołanie funkcji confirm zakończyło się powodzeniem, użytkownik został zalogowany.

Pobieranie pośredniego obiektu AuthCredential

Jeśli chcesz pobrać obiekt AuthCredential z konta użytkownika, prześlij kod weryfikacyjny z wyniku potwierdzenia i kod weryfikacyjny do PhoneAuthProvider.credential zamiast wywoływać funkcję confirm:

var credential = firebase.auth.PhoneAuthProvider.credential(confirmationResult.verificationId, code);

Następnie możesz zalogować użytkownika przy użyciu danych logowania:

firebase.auth().signInWithCredential(credential);

Testowanie z fikcyjnymi numerami telefonów

Na potrzeby programowania możesz skonfigurować fikcyjne numery telefonów w konsoli Firebase. Testowanie z użyciem fikcyjnych numerów telefonów ma te zalety:

  • Testowanie uwierzytelniania numeru telefonu bez zużywania limitu użycia.
  • Testowanie uwierzytelniania numeru telefonu bez wysyłania SMS-a.
  • Przeprowadzanie kolejnych testów z tym samym numerem telefonu bez ograniczenia przepustowości. Pozwala to zminimalizować ryzyko odrzucenia aplikacji podczas procesu sprawdzania w App Store, jeśli recenzent użyje tego samego numeru telefonu do testowania.
  • testowanie w środowiskach programistycznych bez konieczności wprowadzania dodatkowych zmian, na przykład możliwość tworzenia aplikacji w symulatorze iOS lub emulatorze Androida bez Usług Google Play;
  • pisać testy integracyjne bez blokowania przez zabezpieczenia stosowane zwykle w rzeczywistych środowiskach produkcyjnych;

Fikcyjne numery telefonów muszą spełniać te wymagania:

  1. Upewnij się, że używasz numerów telefonów, które są fikcyjne i nie istnieją. Firebase Authentication nie pozwala na ustawienie istniejących numerów telefonów używanych przez prawdziwych użytkowników jako numerów testowych. Możesz na przykład użyć numerów z prefiksem 555 jako testowych numerów telefonów w Stanach Zjednoczonych, np.: +1 650-555-3434
  2. Numery telefonów muszą być sformatowane zgodnie z ograniczeniami dotyczącymi długości i innych ograniczeń. Nadal będą one podlegać takiej samej weryfikacji jak numer telefonu rzeczywistego użytkownika.
  3. Możesz dodać maksymalnie 10 numerów telefonów na potrzeby programowania.
  4. Używaj testowych numerów telefonów i kodów, które są trudne do odgadnięcia i często się zmieniają.

Tworzenie fikcyjnych numerów telefonów i kodów weryfikacyjnych

  1. W konsoli Firebase otwórz sekcję Uwierzytelnianie.
  2. Na karcie Metoda logowania włącz opcję Dostawca telefonu, jeśli nie została jeszcze włączona.
  3. Otwórz menu Numery telefonu do testowania.
  4. Podaj numer telefonu, który chcesz przetestować, np. +1 650-555-3434.
  5. Podaj 6-cyfrowy kod weryfikacyjny dla tego numeru, np. 654321.
  6. Dodaj numer. W razie potrzeby możesz usunąć numer telefonu i jego kod, najeżdżając kursorem na odpowiedni wiersz i klikając ikonę kosza.

Testowanie ręczne

Możesz od razu zacząć używać fikcyjnego numeru telefonu w aplikacji. Dzięki temu możesz przeprowadzać ręczne testy na etapie tworzenia aplikacji bez problemów z limitem lub ograniczeniem szybkości. Możesz też przetestować aplikację bezpośrednio na symulatorze iOS lub emulatorze Androida bez instalowania Usług Google Play.

Gdy podasz fikcyjny numer telefonu i wyślesz kod weryfikacyjny, nie wyślemy SMS-a. Aby się zalogować, musisz podać skonfigurowany wcześniej kod weryfikacyjny.

Po zakończeniu logowania tworzymy użytkownika Firebase z tym numerem telefonu. Użytkownik ma takie same właściwości i takie samo zachowanie jak użytkownik z prawdziwym numerem telefonu. Może też w taki sam sposób korzystać z usługi Realtime Database/Cloud Firestore i innych usług. Podczas tego procesu token identyfikacyjny ma ten sam podpis co użytkownik z prawdziwym numerem telefonu.

Inną opcją jest ustawienie roli testowej za pomocą roszczeń niestandardowych dla tych użytkowników, aby odróżnić ich jako fałszywych użytkowników, jeśli chcesz jeszcze bardziej ograniczyć dostęp.

Testowanie integracji

Oprócz testów ręcznych Firebase Authentication udostępnia interfejsy API, które ułatwiają tworzenie testów integracyjnych na potrzeby testowania uwierzytelniania przez telefon. Te interfejsy API wyłączają weryfikację aplikacji przez wyłączenie wymagań reCAPTCHA w internecie i cichych powiadomień push na iOS. Dzięki temu testowanie automatyzacji jest możliwe w tych procesach i łatwiej je wdrożyć. Dodatkowo umożliwiają testowanie procesów weryfikacji błyskawicznej na urządzeniach z Androidem.

W internecie ustaw appVerificationDisabledForTesting na true przed wyrenderowaniem firebase.auth.RecaptchaVerifier. Dzięki temu test reCAPTCHA zostanie rozwiązany automatycznie, co pozwoli Ci podać numer telefonu bez konieczności ręcznego rozwiązywania testu. Pamiętaj, że nawet jeśli usługa reCAPTCHA jest wyłączona, zalogowanie się z użyciem numeru telefonu niefikcyjnego nie będzie możliwe. Z tym interfejsem API można używać tylko fikcyjnych numerów telefonów.

// Turn off phone auth app verification.
firebase.auth().settings.appVerificationDisabledForTesting = true;

var phoneNumber = "+16505554567";
var testVerificationCode = "123456";

// This will render a fake reCAPTCHA as appVerificationDisabledForTesting is true.
// This will resolve after rendering without app verification.
var appVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
// signInWithPhoneNumber will call appVerifier.verify() which will resolve with a fake
// reCAPTCHA response.
firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
    .then(function (confirmationResult) {
      // confirmationResult can resolve with the fictional testVerificationCode above.
      return confirmationResult.confirm(testVerificationCode)
    }).catch(function (error) {
      // Error; SMS not sent
      // ...
    });

Testy weryfikujące aplikacje z widoczną i niewidoczną niewłaściwą odpowiedzią reCAPTCHA działają inaczej, gdy weryfikacja aplikacji jest wyłączona:

  • Widoczny test reCAPTCHA: gdy widoczny test reCAPTCHA jest renderowany za pomocą appVerifier.render(), automatycznie rozwiązuje się po ułamku sekundy. Jest to równoznaczne z kliknięciem przez użytkownika testu reCAPTCHA bezpośrednio po jego wyświetleniu. Po pewnym czasie odpowiedź reCAPTCHA wygaśnie i problem zostanie automatycznie rozwiązany.
  • Niewidoczna reCAPTCHA: niewidoczna reCAPTCHA nie rozwiązuje automatycznie podczas renderowania, lecz dopiero po wywołaniu funkcji appVerifier.verify() lub po kliknięciu przycisku kotwicy reCAPTCHA po ułamku sekundy. Podobnie odpowiedź wygaśnie po pewnym czasie i zostanie automatycznie rozwiązana dopiero po wywołaniu funkcji appVerifier.verify() lub ponownym kliknięciu przycisku reCAPTCHA.

Gdy symulowany test reCAPTCHA zostanie rozwiązany, odpowiednia funkcja wywołania zwrotnego zostanie wywołana zgodnie z oczekiwaniami z fałszywą odpowiedzią. Jeśli ustawisz też wywołanie po upływie ważności, zostanie ono wywołane po upływie ważności.

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 sprawdzić stan uwierzytelniania użytkownika, ustawiając obserwatora na obiekcie Auth. Następnie możesz uzyskać podstawowe informacje o profilu użytkownika z obiektu User. Zobacz 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żyć go do kontrolowania, do jakich danych ma on dostęp.

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