Zaawansowane funkcje uwierzytelniania

1. Skonfiguruj

Pobieranie kodu źródłowego

W tym ćwiczeniu zaczniesz od prawie ukończonej wersji przykładowej aplikacji Friendly Chat. Najpierw musisz sklonować kod źródłowy:

$ git clone https://github.com/firebase/codelab-friendlychat-web --branch security

Następnie przejdź do katalogu security-start, w którym będziesz pracować przez resztę tego laboratorium:

$ cd codelab-friendlychat-web/security-start

Teraz zainstaluj zależności, aby móc uruchomić kod. Jeśli korzystasz z wolniejszego połączenia internetowego, może to potrwać minutę lub dwie:

$ npm install && (cd functions && npm install)

Poznaj to repozytorium

Katalog security-solution/ zawiera pełny kod przykładowej aplikacji. Katalog security-start to miejsce, w którym będziesz pracować nad kursem programowania. Brakuje w nim kilku ważnych elementów implementacji uwierzytelniania. Najważniejsze pliki i funkcje w security-start/security-solution/ to:

  • functions/index.js zawiera kod Cloud Functions i to w nim będziesz pisać funkcje blokujące uwierzytelnianie.
  • public/ – zawiera pliki statyczne aplikacji do czatu.
  • public/scripts/main.js – miejsce, w którym kompilowany jest kod JS aplikacji Google Chat (src/index.js).
  • src/firebase-config.js – zawiera obiekt konfiguracji Firebase, który jest używany do inicjowania aplikacji do czatu.
  • src/index.js – kod JS aplikacji do czatu

Pobieranie wiersza poleceń Firebase

Pakiet emulatorów jest częścią wiersza poleceń Firebase, który możesz zainstalować na swoim komputerze za pomocą tego polecenia:

$ npm install -g firebase-tools@latest

Skompiluj kod JavaScript za pomocą narzędzia webpack, które utworzy plik main.js w katalogu public/scripts/.

webpack build

Następnie sprawdź, czy masz najnowszą wersję interfejsu CLI. Te warsztaty działają w wersji 11.14 lub nowszej.

$ firebase --version
11.14.2

Łączenie z projektem Firebase

Tworzenie nowego projektu Firebase

  1. Zaloguj się w konsoli Firebase, korzystając ze swojego konta Google.
  2. Kliknij przycisk, aby utworzyć nowy projekt, a potem wpisz jego nazwę (np. Authentication MFA Codelab).
  3. Kliknij Dalej.
  4. Po wyświetleniu monitu przeczytaj i zaakceptuj warunki usługi Firebase, a potem kliknij Dalej.
  5. (Opcjonalnie) Włącz w konsoli Firebase pomoc AI (nazywaną „Gemini w Firebase”).
  6. W tym samouczku nie potrzebujesz Google Analytics, więc wyłącz opcję Google Analytics.
  7. Kliknij Utwórz projekt, poczekaj, aż projekt zostanie udostępniony, a następnie kliknij Dalej.

Łączenie kodu z projektem Firebase

Teraz musisz połączyć ten kod z projektem Firebase. Najpierw uruchom to polecenie, aby zalogować się w wierszu poleceń Firebase:

$ firebase login

Następnie uruchom to polecenie, aby utworzyć alias projektu. Zastąp $YOUR_PROJECT_ID identyfikatorem projektu Firebase.

$ firebase use $YOUR_PROJECT_ID

Możesz teraz uruchomić aplikację.

2. Uruchamianie emulatorów

W tej sekcji uruchomisz aplikację lokalnie. Oznacza to, że nadszedł czas na uruchomienie pakietu emulatorów.

Uruchamianie emulatorów

W katalogu źródłowym codelabu uruchom to polecenie, aby uruchomić emulatory:

$ firebase emulators:start

Aplikacja będzie dostępna pod adresem http://127.0.0.1:5170, a kod źródłowy będzie się stale przebudowywać w miarę wprowadzania zmian. Aby zobaczyć zmiany, wystarczy odświeżyć stronę w przeglądarce (Ctrl+Shift+R).

Powinny się wyświetlić dane wyjściowe podobne do tych:

i  emulators: Starting emulators: auth, functions, firestore, hosting, storage
✔  functions: Using node@16 from host.
i  firestore: Firestore Emulator logging to firestore-debug.log
✔  firestore: Firestore Emulator UI websocket is running on 9150.
i  hosting[demo-example]: Serving hosting files from: ./public
✔  hosting[demo-example]: Local server: http://127.0.0.1:5170
i  ui: Emulator UI logging to ui-debug.log
i  functions: Watching "[...]" for Cloud Functions...
✔  functions: Loaded functions definitions from source: beforecreated.
✔  functions[us-central1-beforecreated]: providers/cloud.auth/eventTypes/user.beforeCreate function initialized (http://127.0.0.1:5011/[...]/us-central1/beforecreated).
i  Running script: npm start
 
> security@1.0.0 start
> webpack --watch --progress
[...]
webpack 5.50.0 compiled with 1 warning in 990 ms

Gdy zobaczysz komunikat All emulators ready (Wszystkie emulatory są gotowe), aplikacja będzie gotowa do użycia.

3. Wdrażanie MFA

W tym repozytorium uwierzytelnianie wieloskładnikowe zostało wdrożone częściowo. Najpierw dodasz kod, aby zarejestrować użytkownika w MFA, a potem, aby poprosić użytkowników zarejestrowanych w MFA o podanie drugiego czynnika.

W edytorze otwórz plik src/index.js i znajdź metodę startEnrollMultiFactor(). Dodaj ten kod, aby skonfigurować weryfikator reCAPTCHA, który będzie zapobiegać nadużyciom związanym z telefonem (weryfikator reCAPTCHA jest ustawiony jako niewidoczny i nie będzie widoczny dla użytkowników):

async function startEnrollMultiFactor(phoneNumber) {
  const recaptchaVerifier = new RecaptchaVerifier(
    "recaptcha",
    { size: "invisible" },
    getAuth()
  );

Następnie znajdź metodę finishEnrollMultiFactor() i dodaj te informacje, aby zarejestrować drugi składnik:

// Completes MFA enrollment once a verification code is obtained.
async function finishEnrollMultiFactor(verificationCode) {
  // Ask user for the verification code. Then:
  const cred = PhoneAuthProvider.credential(verificationId, verificationCode);
  const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);
 
  // Complete enrollment.
  await multiFactor(getAuth().currentUser)
    .enroll(multiFactorAssertion)
    .catch(function (error) {
      alert(`Error finishing second factor enrollment. ${error}`);
      throw error;
    });
  verificationId = null;
}

Następnie znajdź funkcję signIn i dodaj ten przepływ sterowania, który wyświetla użytkownikom zarejestrowanym w MFA prośbę o wpisanie drugiego składnika:

async function signIn() {
  // Sign in Firebase using popup auth and Google as the identity provider.
  var provider = new GoogleAuthProvider();
  await signInWithPopup(getAuth(), provider)
    .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") {
        multiFactorResolver = getMultiFactorResolver(getAuth(), error);
        displaySecondFactor(multiFactorResolver.hints);
      } else {
        alert(`Error signing in user. ${error}`);
      }
    });
}

Pozostała część implementacji, w tym wywoływane tu funkcje, jest już gotowa. Aby zobaczyć, jak działają, przejrzyj resztę pliku.

4. Wypróbuj logowanie z użyciem MFA w emulatorach

Teraz wypróbuj implementację MFA. Sprawdź, czy emulatory nadal działają, i otwórz aplikację hostowaną lokalnie pod adresem localhost:5170. Spróbuj się zalogować. Gdy pojawi się prośba o podanie kodu uwierzytelniania dwuskładnikowego, zobaczysz go w oknie terminala.

Emulatory w pełni obsługują uwierzytelnianie dwuskładnikowe, więc środowisko deweloperskie może być całkowicie samodzielne.

Więcej informacji o wdrażaniu uwierzytelniania dwuskładnikowego znajdziesz w naszej dokumentacji referencyjnej.

5. Tworzenie funkcji blokującej

Niektóre aplikacje są przeznaczone do użytku tylko przez określoną grupę użytkowników. W takich przypadkach warto mieć możliwość tworzenia niestandardowych wymagań, które użytkownik musi spełnić, aby zarejestrować się lub zalogować w aplikacji.

Funkcje blokujące umożliwiają tworzenie niestandardowych wymagań dotyczących uwierzytelniania. Są to funkcje Cloud Functions, ale w przeciwieństwie do większości funkcji działają synchronicznie, gdy użytkownik próbuje się zarejestrować lub zalogować.

Aby utworzyć funkcję blokowania, otwórz functions/index.js w edytorze i znajdź zakomentowaną funkcję beforecreated.

Zastąp go tym kodem, który umożliwia tworzenie kont tylko użytkownikom z domeną example.com:

exports.beforecreated = beforeUserCreated((event) => {
  const user = event.data;
  // Only users of a specific domain can sign up.
  if (!user.email || !user.email.endsWith("@example.com")) {
    throw new HttpsError("invalid-argument", "Unauthorized email");
  }
});

6. Wypróbuj funkcję blokowania w emulatorach

Aby wypróbować funkcję blokowania, upewnij się, że emulatory są uruchomione, a w aplikacji internetowej na stronie localhost:5170 wyloguj się.

Następnie spróbuj utworzyć konto, używając adresu e-mail, który nie kończy się na example.com. Funkcja blokująca uniemożliwi wykonanie tej operacji.

Spróbuj ponownie, używając adresu e-mail, który kończy się na example.com. Konto zostanie utworzone.

Dzięki funkcjom blokowania możesz tworzyć dowolne ograniczenia dotyczące uwierzytelniania. Więcej informacji znajdziesz w dokumentacji.

Podsumowanie

Brawo! Do aplikacji internetowej dodano uwierzytelnianie wielopoziomowe, aby pomóc użytkownikom w zabezpieczeniu konta. Następnie utworzono niestandardowe wymagania dotyczące rejestracji użytkowników za pomocą funkcji blokujących. Zasługujesz na GIF-a.

gif przedstawiający osoby z biura tańczące „raise the roof”