为应用启用 TOTP MFA

本文档介绍如何向应用添加基于时间的动态密码 (TOTP) 多重身份验证 (MFA)。

借助 Identity Platform,您可以将 TOTP 用作 MFA 的其他因素。启用此功能后,尝试登录您的应用的用户会看到系统要求提供 TOTP。要生成 TOTP,用户必须使用可生成有效 TOTP 代码的身份验证器应用,例如 Google 身份验证器

须知事项

  1. 请至少启用一个支持 MFA 的提供方。请注意,除下列情况之外的所有提供方都支持 MFA:

    • 电话身份验证
    • 匿名身份验证
    • 自定义身份验证令牌
    • Apple 游戏中心
  2. 确保您的应用验证用户电子邮件地址。MFA 要求验证电子邮件地址。这样可以防止恶意操作者使用别人的电子邮件地址注册服务,然后通过添加第二重身份验证阻止实际的电子邮件地址所有者注册。

  3. 确保您使用的是正确的平台版本。只有以下 SDK 版本支持 TOTP MFA:

    平台 版本
    Web SDK v9.19.1+
    Android SDK 22.1.0+
    iOS SDK 10.12.0+

在项目级层启用 TOTP MFA

如需启用 TOTP 作为第二重身份验证,请使用 Admin SDK 或调用项目配置 REST 端点。

如需使用 Admin SDK,请执行以下操作:

  1. 如果您尚未安装 Firebase Admin Node.js SDK,请进行安装。

    只有 Firebase Admin Node.js SDK 11.6.0 版及更高版本支持 TOTP MFA。

  2. 运行以下命令:

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

    替换以下内容:

    • NUM_ADJ_INTERVALS:接受 TOTP 的相邻时间范围间隔数(从 0 到 10)。默认值为 5。

      TOTP 的工作原理是确保两方(证明器和验证器)在同一时间范围内(通常为 30 秒)生成动态密码时,两者会生成相同的密码。但是,为了适应各方和人工响应时间之间的时钟偏移,您可以将 TOTP 服务配置为也接受相邻时间范围的 TOTP。

如需使用 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。

    TOTP 的工作原理是确保两方(证明器和验证器)在同一时间范围内(通常为 30 秒)生成动态密码时,两者会生成相同的密码。但是,为了适应各方和人工响应时间之间的时钟偏移,您可以将 TOTP 服务配置为也接受相邻时间范围的 TOTP。

在租户级层启用 TOTP MFA

如需在租户级启用 TOTP 作为 MFA 的第二重身份验证,请使用以下代码:

getAuth().tenantManager().updateTenant(TENANT_ID,
{
      multiFactorConfig: {
          state: 'ENABLED',
          providerConfigs: [{
              totpProviderConfig: {
                  adjacentIntervals: NUM_ADJ_INTERVALS
              }
          }]
      }
})

替换以下内容:

  • TENANT_ID:字符串租户 ID。
  • NUM_ADJ_INTERVALS:时间范围间隔数(从 0 到 10)。默认值为 5。

如需在租户级层使用 REST API 启用 TOTP MFA,请运行以下代码:

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

替换以下内容:

  • PROJECT_ID:项目 ID。
  • TENANT_ID:租户 ID。
  • NUM_ADJ_INTERVALS:时间范围间隔数(从 0 到 10)。默认值为 5。

选择注册模式

您可以选择应用是否要求多重身份验证,以及何时和如何注册用户。一些常见模式包括:

  • 在注册过程中注册用户的第二重身份验证。如果应用要求所有用户进行多重身份验证,请使用此方法。

  • 提供可在注册期间跳过第二重身份验证注册的选项。如果您想要建议但不要求在应用中使用多重身份验证,可以使用此方法。

  • 提供从用户的账号或个人资料管理页面(而不是注册界面)添加第二重身份验证的功能。这样可以使注册过程更顺畅,同时仍可为注重安全的用户提供多重身份验证。

  • 如果用户希望访问安全性要求更高的功能,再要求添加第二重身份验证。

为用户注册 TOTP MFA

启用 TOTP MFA 作为应用的第二重身份验证后,请实现客户端逻辑,为用户注册 TOTP MFA:

Web

import {
    multiFactor,
    TotpMultiFactorGenerator,
    TotpSecret
} from "firebase/auth";

multiFactorSession = await multiFactor(activeUser()).getSession();
totpSecret = await TotpMultiFactorGenerator.generateSecret(
    multiFactorSession
);

// Display this URL as a QR code.
const url = totpSecret.generateQrCodeUrl( <user account id> , <app name> );

// Ask the user for the verification code from the OTP app by scanning the QR
// code.
const multiFactorAssertion = TotpMultiFactorGenerator.assertionForEnrollment(
    totpSecret,
    verificationCode
);

// Finalize the enrollment.
return multiFactor(user).enroll(multiFactorAssertion, mfaDisplayName);

Java

user.getMultiFactor().getSession()
  .addOnCompleteListener(
  new OnCompleteListener<MultiFactorSession>() {
      @Override
      public void onComplete(@NonNull Task<MultiFactorSession> task) {
        if (task.isSuccessful()) {

          // Get a multi-factor session for the user.
          MultiFactorSession multiFactorSession = task.getResult();

          TotpMultiFactorGenerator.generateSecret(multiFactorSession)
              .addOnCompleteListener(
              new OnCompleteListener<TotpSecret>() {
                  @Override
                  public void onComplete(@NonNull Task<TotpSecret> task){
                    if (task.isSuccessful()) {

                      TotpSecret secret = task.getResult();

                      // Display this URL as a QR code for the user to scan.
                      String qrCodeUrl = secret.generateQrCodeUrl();

                      // Display the QR code
                      // ...

                      // Alternatively, you can automatically load the QR code
                      // into a TOTP authenticator app with either default or
                      // specified fallback URL and activity.
                      // Default fallback URL and activity.
                      secret.openInOtpApp(qrCodeUrl);

                      // Specified fallback URL and activity.
                      // secret.openInOtpApp(qrCodeUrl, fallbackUrl, activity);

                    }
                  }
              });
        }
      }
    });

  // Ask the user for the one-time password (otp) from the TOTP authenticator app.
  MultiFactorAssertion multiFactorAssertion =
    TotpMultiFactorGenerator.getAssertionForEnrollment(
    secret, otp);

  // Complete the enrollment.
  user
    .getMultiFactor()
    .enroll(multiFactorAssertion, /* displayName= */ "My TOTP second factor")
    .addOnCompleteListener(
      new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull Task<Void> task) {
          if (task.isSuccessful()) {
            showToast("Successfully enrolled TOTP second factor!");