Dodaj uwierzytelnianie wielopoziomowe TOTP do swojej aplikacji internetowej

Po przejściu na Uwierzytelnianie Firebase z Identity Platform możesz dodać hasło jednorazowe na czas. uwierzytelnianie wielopoziomowe (MFA) aplikacji (TOTP).

Uwierzytelnianie Firebase na platformie Identity Platform umożliwia stosowanie TOTP jako dodatkowego czynnika uwierzytelniania MFA. Gdy włącz tę funkcję, użytkownicy próbujący zalogować się w Twojej aplikacji zobaczą TOTP. Aby go wygenerować, musi użyć aplikacji uwierzytelniającej, która potrafi wygenerować prawidłowe kody TOTP, np. Google Authenticator.

Zanim zaczniesz

  1. Włącz co najmniej 1 dostawcę, który obsługuje MFA. Pamiętaj, że wszyscy dostawcy oprócz tych obsługujących MFA:

    • Uwierzytelnianie telefonu
    • Anonimowe uwierzytelnianie
    • Niestandardowe tokeny uwierzytelniania
    • Apple Game Center
  2. Upewnij się, że aplikacja weryfikuje adresy e-mail użytkowników. MFA wymaga adresu e-mail weryfikacji danych. Dzięki temu hakerzy nie będą mogli zarejestrować się w usłudze za pomocą cudzego adresu e-mail, a następnie zablokować właściciela adresu e-mail, dodając drugi składnik.

  3. Zainstaluj Pakiet SDK Firebase JavaScript.

    Protokół TOTP MFA jest obsługiwany tylko przez modułowy pakiet Web SDK w wersjach 9.19.1 i powyżej.

Włącz TOTP MFA

Aby włączyć TOTP jako drugi czynnik, użyj pakietu Admin SDK lub wywołaj projekt konfiguracji punktu końcowego REST.

Aby używać pakietu Admin SDK, wykonaj te czynności:

  1. Zainstaluj Pakiet SDK Firebase Admin Node.js.

    Protokół TOTP MFA jest obsługiwany tylko przez pakiet SDK Firebase Admin Node.js w wersji 11.6.0 oraz powyżej.

  2. Wykonaj zapytanie:

    import { getAuth } from 'firebase-admin/auth';
    
    getAuth().projectConfigManager().updateProjectConfig(
    {
          multiFactorConfig: {
              providerConfigs: [{
                  state: "ENABLED",
                  totpProviderConfig: {
                      adjacentIntervals: NUM_ADJ_INTERVALS
                  }
              }]
          }
    })
    

    Zastąp następujące elementy:

    • NUM_ADJ_INTERVALS: liczba sąsiadujących ze sobą przedziały czasu, w których mają być akceptowane hasła TOTP, od 0 do 10. domyślna wartość to 5.

      Skrypty TOTP działają tak, aby, gdy dwie strony (zalecający i walidatorowi) generować hasła jednorazowe w tym samym przedziale czasu (zwykle 30 sekund, generują to samo hasło. Jednak aby dostosować jeśli występują różnice między podmiotami a czasem reakcji ludzi, możesz skonfigurować TOTP aby akceptować także TOTP z sąsiednich okien.

Aby włączyć TOTP MFA za pomocą interfejsu API REST, uruchom to polecenie:

curl -X PATCH "https://identitytoolkit.googleapis.com/admin/v2/projects/PROJECT_ID/config?updateMask=mfa" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    -H "Content-Type: application/json" \
    -H "X-Goog-User-Project: PROJECT_ID" \
    -d \
    '{
        "mfa": {
          "providerConfigs": [{
            "state": "ENABLED",
            "totpProviderConfig": {
              "adjacentIntervals": NUM_ADJ_INTERVALS
            }
          }]
       }
    }'

Zastąp następujące elementy:

  • PROJECT_ID: identyfikator projektu.
  • NUM_ADJ_INTERVALS: liczba przedziałów czasu w odstępach czasowych od 0 do 10. Wartością domyślną jest 5.

    Skrypty TOTP działają tak, aby, gdy dwie strony (zalecający i walidatorowi) generować hasła jednorazowe w tym samym przedziale czasu (zwykle 30 sekund, generują to samo hasło. Jednak aby dostosować jeśli występują różnice między podmiotami a czasem reakcji ludzi, możesz skonfigurować TOTP aby akceptować także TOTP z sąsiednich okien.

Wybierz wzorzec rejestracji

Możesz zdecydować, czy Twoja aplikacja wymaga uwierzytelniania wielopoziomowego i w jaki sposób i kiedy zarejestrować użytkowników. Oto niektóre typowe wzorce:

  • 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. Jeśli chcesz zachęcić do uwierzytelniania wielopoziomowego w aplikacji, ale nie wymagać od Ciebie jej stosowania, może zastosować 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.

Rejestrowanie użytkowników w TOTP MFA

Po włączeniu protokołu TOTP MFA jako drugiego składnika w aplikacji wdróż konfigurację po stronie klienta logic do rejestrowania użytkowników w TOTP MFA:

  1. Zaimportuj wymagane klasy i funkcje MFA:

    import {
      multiFactor,
      TotpMultiFactorGenerator,
      TotpSecret,
      getAuth,
    } from "firebase/auth";
    
  2. Ponownie uwierzytelnij użytkownika.

  3. Wygeneruj tajny klucz TOTP dla uwierzytelnionego użytkownika:

    // Generate a TOTP secret.
    const multiFactorSession = await multiFactor(currentUser).getSession();
    const totpSecret = await TotpMultiFactorGenerator.generateSecret(
      multiFactorSession
    );
    
  4. Wyświetl użytkownikowi tajny klucz i poproś go o jego podanie aplikacja uwierzytelniająca.

    Dzięki wielu aplikacjom uwierzytelniającym użytkownicy mogą szybko dodawać nowe obiekty tajne TOTP, skanując kod QR, który reprezentuje Identyfikator URI klucza zgodny z Google Authenticator. Aby w tym celu wygenerować kod QR, wygeneruj identyfikator URI z generateQrCodeUrl(), a potem zakoduj go, korzystając z biblioteki kodów QR na swoim wyboru. Przykład:

    const totpUri = totpSecret.generateQrCodeUrl(
        currentUser.email,
        "Your App's Name"
    );
    await QRExampleLib.toCanvas(totpUri, qrElement);
    

    Zawsze wyświetlaj tajny klucz niezależnie od tego, czy jest wyświetlany kod QR aby obsługiwać aplikacje uwierzytelniające, które nie potrafią odczytywać kodów QR:

    // Also display this key:
    const secret = totpSecret.secretKey;
    

    Gdy użytkownik doda swój tajny klucz do aplikacji uwierzytelniającej, zostanie uruchomiony i generowanie tagów TOTP.

  5. poproś użytkownika o wpisanie TOTP wyświetlonego w aplikacji uwierzytelniającej użyj go, aby zakończyć rejestrację MFA:

    // Ask the user for a verification code from the authenticator app.
    const verificationCode = // Code from user input.
    
    // Finalize the enrollment.
    const multiFactorAssertion = TotpMultiFactorGenerator.assertionForEnrollment(
      totpSecret,
      verificationCode
    );
    await multiFactor(currentUser).enroll(multiFactorAssertion, mfaDisplayName);
    

Logowanie użytkowników za pomocą drugiego składnika

Aby zalogować użytkowników za pomocą TOTP MFA, użyj tego kodu:

  1. Zaimportuj wymagane klasy i funkcje MFA:

    import {
        getAuth,
        getMultiFactorResolver,
        TotpMultiFactorGenerator,
    } from "firebase/auth";
    
  2. Wywołaj jedną z metod signInWith w taki sam sposób, jak w przypadku nieużywania MFA. (np. signInWithEmailAndPassword()). Jeśli metoda zwróci błąd Błąd auth/multi-factor-auth-required, uruchom proces MFA aplikacji.

    try {
        const userCredential = await signInWithEmailAndPassword(
            getAuth(),
            email,
            password
        );
        // If the user is not enrolled with a second factor and provided valid
        // credentials, sign-in succeeds.
    
        // (If your app requires MFA, this could be considered an error
        // condition, which you would resolve by forcing the user to enroll a
        // second factor.)
    
        // ...
    } catch (error) {
        switch (error.code) {
            case "auth/multi-factor-auth-required":
                // Initiate your second factor sign-in flow. (See next step.)
                // ...
                break;
            case ...:  // Handle other errors, such as wrong passwords.
                break;
        }
    }
    
  3. Procedura MFA aplikacji powinna najpierw zachęcić użytkownika do wyboru drugiego składnika których nie chce używać. Listę obsługiwanych drugich czynników możesz sprawdzić, badanie właściwości hints instancji MultiFactorResolver:

    const mfaResolver = getMultiFactorResolver(getAuth(), error);
    const enrolledFactors = mfaResolver.hints.map(info => info.displayName);
    
  4. Jeśli użytkownik zdecyduje się na użycie protokołu TOTP, poproś go o wpisanie tagu TOTP wyświetlanego na stronie jej aplikację uwierzytelniającą i użyć jej do zalogowania się:

    switch (mfaResolver.hints[selectedIndex].factorId) {
        case TotpMultiFactorGenerator.FACTOR_ID:
            const otpFromAuthenticator = // OTP typed by the user.
            const multiFactorAssertion =
                TotpMultiFactorGenerator.assertionForSignIn(
                    mfaResolver.hints[selectedIndex].uid,
                    otpFromAuthenticator
                );
            try {
                const userCredential = await mfaResolver.resolveSignIn(
                    multiFactorAssertion
                );
                // Successfully signed in!
            } catch (error) {
                // Invalid or expired OTP.
            }
            break;
        case PhoneMultiFactorGenerator.FACTOR_ID:
            // Handle SMS second factor.
            break;
        default:
            // Unsupported second factor?
            break;
    }
    

Wyrejestruj się z TOTP MFA

Ta sekcja zawiera informacje o tym, jak postępować w przypadku użytkownika wyrejestrującego się z TOTP MFA.

Jeśli użytkownik zarejestrował się w wielu opcjach MFA i jeśli się wyrejestrował wybierając spośród ostatnio włączonej opcji, otrzyma auth/user-token-expired i są wylogowani. Użytkownik musi zalogować się ponownie i zweryfikować istniejących danych logowania, takich jak adres e-mail i hasło.

Aby wyrejestrować użytkownika, naprawić błąd i aktywować ponowne uwierzytelnianie, skorzystaj z ten kod:

import {
    EmailAuthProvider,
    TotpMultiFactorGenerator,
    getAuth,
    multiFactor,
    reauthenticateWithCredential,
} from "firebase/auth";

try {
    // Unenroll from TOTP MFA.
    await multiFactor(currentUser).unenroll(mfaEnrollmentId);
} catch  (error) {
    if (error.code === 'auth/user-token-expired') {
        // If the user was signed out, re-authenticate them.

        // For example, if they signed in with a password, prompt them to
        // provide it again, then call `reauthenticateWithCredential()` as shown
        // below.

        const credential = EmailAuthProvider.credential(email, password);
        await reauthenticateWithCredential(
            currentUser,
            credential
        );
    }
}

Co dalej?