웹 앱에 TOTP 다중 인증(MFA)을 추가합니다.

Identity Platform을 사용하여 Firebase 인증으로 업그레이드한 경우 시간 기반 일회용 비밀번호(TOTP) 다중 인증(MFA)을 앱에 추가할 수 있습니다.

Identity Platform에서 Firebase 인증을 사용하면 MFA의 추가 요소로 TOTP를 사용할 수 있습니다. 이 기능을 사용 설정하면 앱에 로그인하려는 사용자에게 TOTP 요청이 표시됩니다. 이를 생성하려면 Google OTP와 같이 유효한 TOTP 코드를 생성할 수 있는 OTP 앱을 사용해야 합니다.

시작하기 전에

  1. MFA를 지원하는 하나 이상의 제공업체를 사용 설정하세요. 다음을 제외한 모든 제공업체는 MFA를 지원합니다.

    • 전화 인증
    • 익명 인증
    • 커스텀 인증 토큰
    • Apple Game Center
  2. 앱에서 사용자 이메일 주소를 인증해야 합니다. MFA를 사용하려면 이메일 인증이 필요합니다. 이를 통해 악의적인 행위자가 자신이 소유하지 않은 이메일 주소에 서비스를 등록한 후 두 번째 단계를 추가하여 이메일 주소의 실제 소유자의 접근을 막는 일을 방지할 수 있습니다.

  3. 아직 설치하지 않았다면 Firebase JavaScript SDK를 설치합니다.

    TOTP MFA는 모듈식 웹 SDK 버전 v9.19.1 이상에서만 지원됩니다.

  4. 아직 설치하지 않았다면 Firebase Admin SDK를 설치합니다.

    TOTP MFA는 Firebase Admin SDK 버전 11.6.0 이상에서만 지원됩니다.

TOTP MFA 사용 설정

TOTP를 두 번째 단계로 사용 설정하려면 Admin SDK를 사용하거나 프로젝트 구성 REST 엔드포인트를 호출하세요.

Admin SDK를 사용하려면 다음을 실행합니다.

import { getAuth } from 'firebase-admin/auth';

getAuth().projectConfigManager().updateProjectConfig(
{
      multiFactorConfig: {
          providerConfigs: [{
              state: "ENABLED",
              totpProviderConfig: {
                  adjacentIntervals: {
                      NUM_ADJ_INTERVALS
                  },
              }
          }]
      }
})

다음을 바꿉니다.

  • NUM_ADJ_INTERVALS: 기간 간격(0~10). 기본값은 5입니다.

REST API를 사용하여 TOTP MFA를 사용 설정하려면 다음을 실행합니다.

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"
            }
          }]
       }
    }'

다음을 바꿉니다.

  • PROJECT_ID: 프로젝트 ID
  • NUM_ADJ_INTERVALS: 기간 간격(0~10). 기본값은 5입니다.

등록 패턴 선택

앱에 다중 인증(MFA)이 필요한지 여부 및 사용자 등록 방법과 시기를 선택할 수 있습니다. 일반적인 패턴은 다음과 같습니다.

  • 등록 시 사용자의 두 번째 단계를 등록합니다. 앱이 모든 사용자에게 다중 인증(MFA)을 요구한다면 이 방법을 사용하세요.

  • 등록 시 건너뛸 수 있는 옵션으로 두 번째 단계를 등록하는 옵션을 제공하세요. 앱에서 다중 인증(MFA)을 권고하지만 필수가 아닌 경우 이 방법을 사용할 수 있습니다.

  • 가입 화면이 아닌 사용자의 계정 또는 프로필 관리 페이지에서 두 번째 단계를 추가할 수 있도록 합니다. 이렇게 하면 등록 프로세스 중에 발생하는 마찰을 최소화하면서도 보안에 민감한 사용자에게 다중 인증(MFA)을 제공할 수 있습니다.

  • 사용자가 보안 요구사항이 향상된 기능에 액세스하려고 할 때 두 번째 단계를 점진적으로 추가하도록 합니다.

TOTP MFA에 사용자 등록

앱의 두 번째 단계로 TOTP MFA를 사용 설정한 후 클라이언트 측 로직을 구현하여 TOTP MFA에 사용자를 등록합니다.

  1. 필수 MFA 클래스 및 함수를 가져옵니다.

    import {
      multiFactor,
      TotpMultiFactorGenerator,
      TotpSecret,
      getAuth,
    } from "firebase/auth";
    
  2. 사용자를 다시 인증합니다.

  3. 인증된 사용자를 위한 TOTP 비밀번호를 생성합니다.

    // Generate a TOTP secret.
    const multiFactorSession = await multiFactor(currentUser).getSession();
    const totpSecret = await TotpMultiFactorGenerator.generateSecret(
      multiFactorSession
    );
    
  4. 보안 비밀을 사용자에게 표시하고 OTP 앱에 입력하라는 메시지를 표시합니다.

    많은 OTP 앱에서 사용자는 Google OTP 호환 키 URI를 나타내는 QR 코드를 스캔하여 새 TOTP 보안 비밀을 빠르게 추가할 수 있습니다. 이를 위해 QR 코드를 생성하려면 generateQrCodeUrl()로 URI를 생성한 다음 원하는 QR 코드 라이브러리를 사용하여 URI를 인코딩하세요. 예를 들면 다음과 같습니다.

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

    QR 코드 표시 여부와 관계없이 항상 보안 비밀 키를 표시하여 QR 코드를 읽을 수 없는 OTP 앱을 지원합니다.

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

    사용자가 OTP 앱에 보안 비밀을 추가하면 TOTP가 생성되기 시작합니다.

  5. 사용자에게 OTP 앱에 표시된 TOTP를 입력하고 이를 사용하여 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);
    

두 번째 단계 인증으로 사용자 로그인 처리

TOTP MFA로 사용자를 로그인시키려면 다음 코드를 사용합니다.

  1. 필수 MFA 클래스 및 함수를 가져옵니다.

    import {
        getAuth,
        getMultiFactorResolver,
        TotpMultiFactorGenerator,
    } from "firebase/auth";
    
  2. MFA를 사용하지 않을 때와 마찬가지로 signInWith 메서드 중 하나를 호출합니다. (예: signInWithEmailAndPassword()) 메서드에서 auth/multi-factor-auth-required 오류가 발생하면 앱의 MFA 흐름을 시작합니다.

    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. 앱의 MFA 흐름에서 먼저 사용자에게 사용하려는 두 번째 단계를 선택하라는 메시지를 표시해야 합니다. MultiFactorResolver 인스턴스의 hints 속성을 검사하여 지원되는 두 번째 단계 목록을 가져올 수 있습니다.

    const mfaResolver = getMultiFactorResolver(getAuth(), error);
    const enrolledFactors = mfaResolver.hints.map(info => info.displayName);
    
  4. 사용자가 TOTP 사용을 선택하면 OTP 앱에 표시된 TOTP를 입력하고 이를 사용하여 로그인하라는 메시지를 표시합니다.

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

TOTP MFA 등록 해제

이 섹션에서는 TOTP MFA 등록 해제 사용자를 처리하는 방법을 설명합니다.

사용자가 여러 MFA 옵션에 가입했고, 가장 최근에 사용 설정된 옵션에서 등록 해제한 경우 auth/user-token-expired를 수신하고 로그아웃됩니다. 사용자는 다시 로그인하여 기존 사용자 인증 정보(예: 이메일 주소, 비밀번호)를 확인해야 합니다.

사용자를 등록 해제하고 오류를 처리하고 재인증을 트리거하려면 다음 코드를 사용하세요.

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

try {
    // Unenroll from TOTP MFA.
    await multiFactor(currentUser).unenroll(TotpMultiFactorGenerator.FACTOR_ID);
} 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
        );
    }
}

다음 단계