Adicione autenticação multifator TOTP ao seu aplicativo iOS

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 atores 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 Firebase Apple SDK .

    TOTP MFA é compatível apenas com o Apple SDK versão v10.12.0 e superior e apenas no iOS.

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. Autentique novamente o usuário.

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

    // Generate a TOTP secret.
    guard let mfaSession = try? await currentUser.multiFactor.session() else { return }
    guard let totpSecret = try? await TOTPMultiFactorGenerator.generateSecret(with: mfaSession) else { return }
    
    // Display the secret to the user and prompt them to enter it into their
    // authenticator app. (See the next step.)
    
  3. Exiba o segredo ao usuário e solicite que ele o insira no aplicativo autenticador:

    // Display this key:
    let secret = totpSecret.sharedSecretKey()
    

    Além de exibir a chave secreta, você pode tentar adicioná-la automaticamente ao aplicativo autenticador padrão do dispositivo. Para fazer isso, gere um URI de chave compatível com o Google Authenticator e passe-o para openInOTPApp(withQRCodeURL:) :

    let otpAuthUri = totpSecret.generateQRCodeURL(
        withAccountName: currentUser.email ?? "default account",
        issuer: "Your App Name")
    totpSecret.openInOTPApp(withQRCodeURL: otpAuthUri)
    

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

  4. Solicite ao usuário que digite o TOTP exibido pelo aplicativo autenticador e use-o para finalizar o registro do MFA:

    // Ask the user for a verification code from the authenticator app.
    let verificationCode = // Code from user input.
    
    // Finalize the enrollment.
    let multiFactorAssertion = TOTPMultiFactorGenerator.assertionForEnrollment(
        with: totpSecret,
        oneTimePassword: verificationCode)
    do {
        try await currentUser.multiFactor.enroll(
            with: multiFactorAssertion,
            displayName: "TOTP")
    } catch {
        // Wrong or expired OTP. Re-prompt the user.
    }
    

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

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

  1. Chame um dos métodos signIn(with...:) - como faria se não estivesse usando MFA (por exemplo, signIn(withEmail:password:) ). Se o método gerar um erro com o código secondFactorRequired , inicie o fluxo de MFA do seu aplicativo.

    do {
        let authResult = try await Auth.auth().signIn(withEmail: email, password: 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 let error as AuthErrorCode where error.code == .secondFactorRequired {
        // Initiate your second factor sign-in flow. (See next step.)
        // ...
    } catch {
        // Other auth error.
        throw error
    }
    
  2. 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 :

    let mfaKey = AuthErrorUserInfoMultiFactorResolverKey
    guard let resolver = error.userInfo[mfaKey] as? MultiFactorResolver else { return }
    let enrolledFactors = resolver.hints.map(\.displayName)
    
  3. 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:

    let multiFactorInfo = resolver.hints[selectedIndex]
    switch multiFactorInfo.factorID {
    case TOTPMultiFactorID:
        let otpFromAuthenticator = // OTP typed by the user.
        let assertion = TOTPMultiFactorGenerator.assertionForSignIn(
            withEnrollmentID: multiFactorInfo.uid,
            oneTimePassword: otpFromAuthenticator)
        do {
            let authResult = try await resolver.resolveSignIn(with: assertion)
        } catch {
            // Wrong or expired OTP. Re-prompt the user.
        }
    default:
        return
    }
    

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:

guard let currentUser = Auth.auth().currentUser else { return }

// Prompt the user to select a factor to unenroll, from this array:
currentUser.multiFactor.enrolledFactors

// ...

// Unenroll the second factor.
let multiFactorInfo = currentUser.multiFactor.enrolledFactors[selectedIndex]
do {
    try await currentUser.multiFactor.unenroll(with: multiFactorInfo)
} catch let error as AuthErrorCode where error.code == .invalidUserToken {
    // Second factor unenrolled, but the user was signed out. Re-authenticate
    // them.
}

Qual é o próximo