Adicione autenticação multifator TOTP ao seu aplicativo da web

Se você tiver atualizado para o Firebase Authentication com Identity Platform, poderá adicionar autenticação multifator (MFA) de senha única baseada em tempo (TOTP) ao seu aplicativo.

O Firebase Authentication com Identity Platform permite usar um TOTP como um fator adicional para MFA. Quando você habilita esse recurso, os usuários que tentam fazer login no seu aplicativo veem uma solicitação de TOTP. Para gerá-lo, eles devem utilizar um aplicativo autenticador capaz de gerar códigos TOTP válidos, como o Google Authenticator .

Antes de você começar

  1. Habilite pelo menos um provedor que ofereça suporte à MFA. Observe que todos os provedores , exceto os seguintes, oferecem suporte a MFA:

    • Autenticação de telefone
    • Autenticação anônima
    • Tokens de autenticação personalizados
    • Centro de jogos da Apple
  2. Certifique-se de que seu aplicativo verifique os endereços de e-mail dos usuários. A MFA requer verificação de e-mail. Isso evita que agentes mal-intencionados se registrem em um serviço com um endereço de e-mail que não lhes pertence e, em seguida, bloqueiem o proprietário real do endereço de e-mail adicionando um segundo fator.

  3. Caso ainda não tenha feito isso, instale o SDK JavaScript do Firebase .

    TOTP MFA é compatível apenas com o Web SDK modular, versões v9.19.1 e superiores.

Habilitar TOTP MFA

Para habilitar o TOTP como um segundo fator, use o SDK Admin ou chame o endpoint REST de configuração do projeto.

Para usar o Admin SDK, faça o seguinte:

  1. Caso ainda não tenha feito isso, instale o SDK Admin Node.js do Firebase .

    TOTP MFA é compatível apenas com o SDK Admin Node.js do Firebase versões 11.6.0 e superiores.

  2. Execute o seguinte:

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

    Substitua o seguinte:

    • NUM_ADJ_INTERVALS : O número de intervalos de janela de tempo adjacentes a partir dos quais aceitar TOTPs, de zero a dez. O padrão é cinco.

      Os TOTPs funcionam garantindo que quando duas partes (o provador e o validador) geram OTPs dentro da mesma janela de tempo (normalmente 30 segundos de duração), elas geram a mesma senha. No entanto, para acomodar o desvio do relógio entre as partes e o tempo de resposta humana, você pode configurar o serviço TOTP para também aceitar TOTPs de janelas adjacentes.

Para ativar o TOTP MFA usando a API REST, execute o seguinte:

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

Substitua o seguinte:

  • PROJECT_ID : o ID do projeto.
  • NUM_ADJ_INTERVALS : O número de intervalos de janela de tempo, de zero a dez. O padrão é cinco.

    Os TOTPs funcionam garantindo que quando duas partes (o provador e o validador) geram OTPs dentro da mesma janela de tempo (normalmente 30 segundos de duração), elas geram a mesma senha. No entanto, para acomodar o desvio do relógio entre as partes e o tempo de resposta humana, você pode configurar o serviço TOTP para também aceitar TOTPs de janelas adjacentes.

Escolha um padrão de inscrição

Você pode escolher se seu aplicativo requer autenticação multifator e como e quando inscrever seus usuários. Alguns padrões comuns incluem o seguinte:

  • Inscreva o segundo fator do usuário como parte do registro. Use este método se seu aplicativo exigir autenticação multifator para todos os usuários.

  • Ofereça uma opção ignorável para inscrever um segundo fator durante o registro. Se quiser incentivar, mas não exigir, autenticação multifator em seu aplicativo, você pode usar esta abordagem.

  • Forneça a capacidade de adicionar um segundo fator da conta do usuário ou da página de gerenciamento de perfil, em vez da tela de inscrição. Isso minimiza o atrito durante o processo de registro, ao mesmo tempo que disponibiliza a autenticação multifator para usuários sensíveis à segurança.

  • Exigir a adição incremental de um segundo fator quando o usuário desejar acessar recursos com maiores requisitos de segurança.

Inscrever usuários no TOTP MFA

Depois de ativar o TOTP MFA como um segundo fator para seu aplicativo, implemente a lógica do lado do cliente para inscrever usuários no TOTP MFA:

  1. Importe as classes e funções de MFA necessárias:

    import {
      multiFactor,
      TotpMultiFactorGenerator,
      TotpSecret,
      getAuth,
    } from "firebase/auth";
    
  2. Autentique novamente o usuário.

  3. Gere um segredo TOTP para o usuário autenticado:

    // Generate a TOTP secret.
    const multiFactorSession = await multiFactor(currentUser).getSession();
    const totpSecret = await TotpMultiFactorGenerator.generateSecret(
      multiFactorSession
    );
    
  4. Exiba o segredo ao usuário e solicite que ele o insira no aplicativo autenticador.

    Com muitos aplicativos autenticadores, os usuários podem adicionar rapidamente novos segredos TOTP digitalizando um código QR que representa um URI de chave compatível com o Google Authenticator . Para gerar um código QR para esta finalidade, gere o URI com generateQrCodeUrl() e depois codifique-o usando a biblioteca de códigos QR de sua escolha. Por exemplo:

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

    Independentemente de você exibir um código QR, sempre exiba a chave secreta para oferecer suporte a aplicativos autenticadores que não conseguem ler códigos QR:

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

    Depois que o usuário adicionar seu segredo ao aplicativo autenticador, ele começará a gerar TOTPs.

  5. Solicite ao usuário que digite o TOTP exibido no aplicativo autenticador e use-o para finalizar o registro do 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);
    

Faça login de usuários com um segundo fator

Para conectar usuários com TOTP MFA, use o seguinte código:

  1. Importe as classes e funções de MFA necessárias:

    import {
        getAuth,
        getMultiFactorResolver,
        TotpMultiFactorGenerator,
    } from "firebase/auth";
    
  2. Chame um dos métodos signInWith - como faria se não estivesse usando MFA. (Por exemplo, signInWithEmailAndPassword() .) Se o método gerar um erro auth/multi-factor-auth-required , inicie o fluxo de MFA do seu aplicativo.

    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. O fluxo de MFA do seu aplicativo deve primeiro solicitar que o usuário escolha o segundo fator que deseja usar. Você pode obter uma lista de segundos fatores suportados examinando a propriedade hints de uma instância MultiFactorResolver :

    const mfaResolver = getMultiFactorResolver(getAuth(), error);
    const enrolledFactors = mfaResolver.hints.map(info => info.displayName);
    
  4. Se o usuário optar por usar o TOTP, solicite que ele digite o TOTP exibido no aplicativo autenticador e use-o para fazer login:

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

Cancelar inscrição no TOTP MFA

Esta seção descreve como lidar com o cancelamento da inscrição de um usuário no TOTP MFA.

Se um usuário se inscreveu em várias opções de MFA e cancelou a inscrição na opção habilitada mais recentemente, ele receberá um auth/user-token-expired e será desconectado. O usuário deve fazer login novamente e verificar as credenciais existentes, por exemplo, um endereço de e-mail e uma senha.

Para cancelar a inscrição do usuário, tratar o erro e acionar a reautenticação, use o seguinte código:

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

Qual é o próximo