Acompanhe as novidades sobre tudo o que foi anunciado no Firebase Summit e saiba como o Firebase pode ajudar a acelerar o desenvolvimento de apps e executá-los com confiança. Saiba mais

Adicione autenticação multifator ao seu aplicativo web

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

Se você atualizou para o Firebase Authentication com Identity Platform, pode adicionar a autenticação multifator SMS ao seu aplicativo da web.

A autenticação multifator aumenta a segurança do seu aplicativo. Embora os invasores muitas vezes comprometam senhas e contas sociais, interceptar uma mensagem de texto é mais difícil.

Antes de você começar

  1. Habilite pelo menos um provedor que ofereça suporte à autenticação multifator. Todos os provedores suportam MFA, exceto autenticação por telefone, autenticação anônima e Apple Game Center.

  2. Certifique-se de que seu aplicativo esteja verificando os e-mails do usuário. MFA requer verificação de e-mail. Isso evita que atores mal-intencionados se registrem em um serviço com um e-mail que não possuam e, em seguida, bloqueiem o verdadeiro proprietário adicionando um segundo fator.

Usando multilocação

Se você estiver habilitando a autenticação multifator para uso em um ambiente multilocatário , conclua as etapas a seguir (além do restante das instruções neste documento):

  1. No Console do GCP, selecione o locatário com o qual deseja trabalhar.

  2. Em seu código, defina o campo tenantId na instância Auth para a ID do seu locatário. Por exemplo:

    Web version 9

    import { getAuth } from "firebase/auth";
    
    const auth = getAuth(app);
    auth.tenantId = "myTenantId1";
    

    Web version 8

    firebase.auth().tenantId = 'myTenantId1';
    

Ativando a autenticação multifator

  1. Abra a página Autenticação > Método de login do console do Firebase.

  2. Na seção Avançado , habilite a Autenticação Multifator SMS .

    Você também deve inserir os números de telefone com os quais testará seu aplicativo. Embora opcional, registrar números de telefone de teste é altamente recomendado para evitar limitação durante o desenvolvimento.

  3. Se você ainda não autorizou o domínio do seu aplicativo, adicione-o à lista de permissões na página Autenticação > Configurações do Firebase console.

Escolhendo 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:

  • Inscrever 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 pulável para inscrever um segundo fator durante o registro. Os aplicativos que desejam incentivar, mas não exigem, a autenticação multifator podem preferir essa 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 em que disponibiliza a autenticação multifator para usuários sensíveis à segurança.

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

Configurando o verificador reCAPTCHA

Antes de poder enviar códigos SMS, você precisa configurar um verificador reCAPTCHA. O Firebase usa o reCAPTCHA para evitar abusos, garantindo que as solicitações de verificação de número de telefone venham de um dos domínios permitidos do seu aplicativo.

Você não precisa configurar manualmente um cliente reCAPTCHA; o objeto RecaptchaVerifier do SDK do cliente cria e inicializa automaticamente quaisquer chaves e segredos do cliente necessários.

Usando o reCAPTCHA invisível

O objeto RecaptchaVerifier oferece suporte ao reCAPTCHA invisível , que geralmente pode verificar o usuário sem exigir nenhuma interação. Para usar um reCAPTCHA invisível, crie um RecaptchaVerifier com o parâmetro size definido como invisible e especifique o ID do elemento da interface do usuário que inicia o registro multifator:

Web version 9

import { RecaptchaVerifier } from "firebase/auth";

const recaptchaVerifier = new RecaptchaVerifier("sign-in-button", {
    "size": "invisible",
    "callback": function(response) {
        // reCAPTCHA solved, you can proceed with
        // phoneAuthProvider.verifyPhoneNumber(...).
        onSolvedRecaptcha();
    }
}, auth);

Web version 8

var recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
'size': 'invisible',
'callback': function(response) {
  // reCAPTCHA solved, you can proceed with phoneAuthProvider.verifyPhoneNumber(...).
  onSolvedRecaptcha();
}
});

Usando o widget reCAPTCHA

Para usar um widget reCAPTCHA visível, crie um elemento HTML para conter o widget e, em seguida, crie um objeto RecaptchaVerifier com o ID do contêiner de interface do usuário. Você também pode, opcionalmente, definir retornos de chamada que são invocados quando o reCAPTCHA é resolvido ou expira:

Web version 9

import { RecaptchaVerifier } from "firebase/auth";

const recaptchaVerifier = new RecaptchaVerifier(
    "recaptcha-container",

    // Optional reCAPTCHA parameters.
    {
      "size": "normal",
      "callback": function(response) {
        // reCAPTCHA solved, you can proceed with 
        // phoneAuthProvider.verifyPhoneNumber(...).
        onSolvedRecaptcha();
      },
      "expired-callback": function() {
        // Response expired. Ask user to solve reCAPTCHA again.
        // ...
      }
    }, auth
);

Web version 8

var recaptchaVerifier = new firebase.auth.RecaptchaVerifier(
  'recaptcha-container',
  // Optional reCAPTCHA parameters.
  {
    'size': 'normal',
    'callback': function(response) {
      // reCAPTCHA solved, you can proceed with phoneAuthProvider.verifyPhoneNumber(...).
      // ...
      onSolvedRecaptcha();
    },
    'expired-callback': function() {
      // Response expired. Ask user to solve reCAPTCHA again.
      // ...
    }
  });

Pré-renderizando o reCAPTCHA

Opcionalmente, você pode pré-renderizar o reCAPTCHA antes de iniciar o registro de dois fatores:

Web version 9

recaptchaVerifier.render()
    .then(function (widgetId) {
        window.recaptchaWidgetId = widgetId;
    });

Web version 8

recaptchaVerifier.render()
  .then(function(widgetId) {
    window.recaptchaWidgetId = widgetId;
  });

Após a resolução de render() , você obtém o ID do widget do reCAPTCHA, que pode ser usado para fazer chamadas para a API do reCAPTCHA :

var recaptchaResponse = grecaptcha.getResponse(window.recaptchaWidgetId);

RecaptchaVerifier abstrai essa lógica com o método de verificação , então você não precisa manipular a variável grecaptcha diretamente.

Inscrevendo um segundo fator

Para inscrever um novo fator secundário para um usuário:

  1. Reautentique o usuário.

  2. Peça ao usuário para inserir seu número de telefone.

  3. Inicialize o verificador reCAPTCHA conforme ilustrado na seção anterior. Ignore esta etapa se uma instância RecaptchaVerifier já estiver configurada:

    Web version 9

    import { RecaptchaVerifier } from "firebase/auth";
    
    const recaptchaVerifier = new RecaptchaVerifier('recaptcha-container-id', undefined, auth);
    

    Web version 8

    var recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container-id');
    
  4. Obtenha uma sessão multifator para o usuário:

    Web version 9

    import { multiFactor } from "firebase/auth";
    
    multiFactor(user).getSession().then(function (multiFactorSession) {
        // ...
    });
    

    Web version 8

    user.multiFactor.getSession().then(function(multiFactorSession) {
      // ...
    })
    
  5. Inicialize um objeto PhoneInfoOptions com o número de telefone do usuário e a sessão multifator:

    Web version 9

    // Specify the phone number and pass the MFA session.
    const phoneInfoOptions = {
      phoneNumber: phoneNumber,
      session: multiFactorSession
    };
    

    Web version 8

    // Specify the phone number and pass the MFA session.
    var phoneInfoOptions = {
      phoneNumber: phoneNumber,
      session: multiFactorSession
    };
    
  6. Envie uma mensagem de verificação para o telefone do usuário:

    Web version 9

    import { PhoneAuthProvider } from "firebase/auth";
    
    const phoneAuthProvider = new PhoneAuthProvider(auth);
    phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
        .then(function (verificationId) {
            // verificationId will be needed to complete enrollment.
        });
    

    Web version 8

    var phoneAuthProvider = new firebase.auth.PhoneAuthProvider();
    // Send SMS verification code.
    return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
      .then(function(verificationId) {
        // verificationId will be needed for enrollment completion.
      })
    

    Embora não seja obrigatório, é uma prática recomendada informar aos usuários com antecedência que eles receberão uma mensagem SMS e que as taxas padrão se aplicam.

  7. Se a solicitação falhar, redefina o reCAPTCHA e repita a etapa anterior para que o usuário possa tentar novamente. Observe que verifyPhoneNumber() redefinirá automaticamente o reCAPTCHA quando ele gerar um erro, pois os tokens reCAPTCHA são usados ​​apenas uma vez.

    Web version 9

    recaptchaVerifier.clear();
    

    Web version 8

    recaptchaVerifier.clear();
    
  8. Uma vez enviado o código SMS, peça ao usuário para verificar o código:

    Web version 9

    // Ask user for the verification code. Then:
    const cred = PhoneAuthProvider.credential(verificationId, verificationCode);
    

    Web version 8

    // Ask user for the verification code. Then:
    var cred = firebase.auth.PhoneAuthProvider.credential(verificationId, verificationCode);
    
  9. Inicialize um objeto MultiFactorAssertion com o PhoneAuthCredential :

    Web version 9

    import { PhoneMultiFactorGenerator } from "firebase/auth";
    
    const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);
    

    Web version 8

    var multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred);
    
  10. Conclua a inscrição. Opcionalmente, você pode especificar um nome de exibição para o segundo fator. Isso é útil para usuários com vários fatores de segundo, pois o número de telefone é mascarado durante o fluxo de autenticação (por exemplo, +1******1234).

    Web version 9

    // Complete enrollment. This will update the underlying tokens
    // and trigger ID token change listener.
    multiFactor(user).enroll(multiFactorAssertion, "My personal phone number");
    

    Web version 8

    // Complete enrollment. This will update the underlying tokens
    // and trigger ID token change listener.
    user.multiFactor.enroll(multiFactorAssertion, 'My personal phone number');
    

O código abaixo mostra um exemplo completo de inscrição de um segundo fator:

Web version 9

import {
    multiFactor, PhoneAuthProvider, PhoneMultiFactorGenerator,
    RecaptchaVerifier
} from "firebase/auth";

const recaptchaVerifier = new RecaptchaVerifier('recaptcha-container-id', undefined, auth);
multiFactor(user).getSession()
    .then(function (multiFactorSession) {
        // Specify the phone number and pass the MFA session.
        const phoneInfoOptions = {
            phoneNumber: phoneNumber,
            session: multiFactorSession
        };

        const phoneAuthProvider = new PhoneAuthProvider(auth);

        // Send SMS verification code.
        return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier);
    }).then(function (verificationId) {
        // Ask user for the verification code. Then:
        const cred = PhoneAuthProvider.credential(verificationId, verificationCode);
        const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);

        // Complete enrollment.
        return multiFactor(user).enroll(multiFactorAssertion, mfaDisplayName);
    });

Web version 8

var recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container-id');
user.multiFactor.getSession().then(function(multiFactorSession) {
  // Specify the phone number and pass the MFA session.
  var phoneInfoOptions = {
    phoneNumber: phoneNumber,
    session: multiFactorSession
  };
  var phoneAuthProvider = new firebase.auth.PhoneAuthProvider();
  // Send SMS verification code.
  return phoneAuthProvider.verifyPhoneNumber(
      phoneInfoOptions, recaptchaVerifier);
})
.then(function(verificationId) {
  // Ask user for the verification code.
  var cred = firebase.auth.PhoneAuthProvider.credential(verificationId, verificationCode);
  var multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred);
  // Complete enrollment.
  return user.multiFactor.enroll(multiFactorAssertion, mfaDisplayName);
});

Parabéns! Você registrou com sucesso um segundo fator de autenticação para um usuário.

Conectando usuários com um segundo fator

Para fazer login de um usuário com verificação por SMS de dois fatores:

  1. Faça o login do usuário com seu primeiro fator e, em seguida, capture o erro auth/multi-factor-auth-required . Este erro contém um resolvedor, dicas sobre os segundos fatores inscritos e uma sessão subjacente provando que o usuário foi autenticado com sucesso com o primeiro fator.

    Por exemplo, se o primeiro fator do usuário for um e-mail e senha:

    Web version 9

    import { getAuth, getMultiFactorResolver} from "firebase/auth";
    
    const auth = getAuth();
    signInWithEmailAndPassword(auth, email, password)
        .then(function (userCredential) {
            // User successfully signed in and is not enrolled with a second factor.
        })
        .catch(function (error) {
            if (error.code == 'auth/multi-factor-auth-required') {
                // The user is a multi-factor user. Second factor challenge is required.
                resolver = getMultiFactorResolver(auth, error);
                // ...
            } else if (error.code == 'auth/wrong-password') {
                // Handle other errors such as wrong password.
            }
    });
    

    Web version 8

    firebase.auth().signInWithEmailAndPassword(email, password)
      .then(function(userCredential) {
        // User successfully signed in and is not enrolled with a second factor.
      })
      .catch(function(error) {
        if (error.code == 'auth/multi-factor-auth-required') {
          // The user is a multi-factor user. Second factor challenge is required.
          resolver = error.resolver;
          // ...
        } else if (error.code == 'auth/wrong-password') {
          // Handle other errors such as wrong password.
        } ...
      });
    

    Se o primeiro fator do usuário for um provedor federado, como OAuth, SAML ou OIDC, detecte o erro após chamar signInWithPopup() ou signInWithRedirect() .

  2. Se o usuário tiver vários fatores secundários inscritos, pergunte qual deles usar:

    Web version 9

    // Ask user which second factor to use.
    // You can get the masked phone number via resolver.hints[selectedIndex].phoneNumber
    // You can get the display name via resolver.hints[selectedIndex].displayName
    
    if (resolver.hints[selectedIndex].factorId === PhoneMultiFactorGenerator.FACTOR_ID) {
        // User selected a phone second factor.
        // ...
    } else {
        // Unsupported second factor.
        // Note that only phone second factors are currently supported.
    }
    

    Web version 8

    // Ask user which second factor to use.
    // You can get the masked phone number via resolver.hints[selectedIndex].phoneNumber
    // You can get the display name via resolver.hints[selectedIndex].displayName
    if (resolver.hints[selectedIndex].factorId === firebase.auth.PhoneMultiFactorGenerator.FACTOR_ID) {
      // User selected a phone second factor.
      // ...
    } else {
      // Unsupported second factor.
      // Note that only phone second factors are currently supported.
    }
    
  3. Inicialize o verificador reCAPTCHA conforme ilustrado na seção anterior. Ignore esta etapa se uma instância RecaptchaVerifier já estiver configurada:

    Web version 9

    import { RecaptchaVerifier } from "firebase/auth";
    
    recaptchaVerifier = new RecaptchaVerifier('recaptcha-container-id', undefined, auth);
    

    Web version 8

    var recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container-id');
    
  4. Inicialize um objeto PhoneInfoOptions com o número de telefone do usuário e a sessão multifator. Esses valores estão contidos no objeto resolver passado para o erro auth/multi-factor-auth-required :

    Web version 9

    const phoneInfoOptions = {
        multiFactorHint: resolver.hints[selectedIndex],
        session: resolver.session
    };
    

    Web version 8

    var phoneInfoOptions = {
      multiFactorHint: resolver.hints[selectedIndex],
      session: resolver.session
    };
    
  5. Envie uma mensagem de verificação para o telefone do usuário:

    Web version 9

    // Send SMS verification code.
    const phoneAuthProvider = new PhoneAuthProvider(auth);
    phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
        .then(function (verificationId) {
            // verificationId will be needed for sign-in completion.
        });
    

    Web version 8

    var phoneAuthProvider = new firebase.auth.PhoneAuthProvider();
    // Send SMS verification code.
    return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
      .then(function(verificationId) {
        // verificationId will be needed for sign-in completion.
      })
    
  6. Se a solicitação falhar, redefina o reCAPTCHA e repita a etapa anterior para que o usuário possa tentar novamente:

    Web version 9

    recaptchaVerifier.clear();
    

    Web version 8

    recaptchaVerifier.clear();
    
  7. Uma vez enviado o código SMS, peça ao usuário para verificar o código:

    Web version 9

    const cred = PhoneAuthProvider.credential(verificationId, verificationCode);
    

    Web version 8

    // Ask user for the verification code. Then:
    var cred = firebase.auth.PhoneAuthProvider.credential(verificationId, verificationCode);
    
  8. Inicialize um objeto MultiFactorAssertion com o PhoneAuthCredential :

    Web version 9

    const multiFactorAssertion = PhoneMultiFactorGenerator.assertion(cred);
    

    Web version 8

    var multiFactorAssertion = firebase.auth.PhoneMultiFactorGenerator.assertion(cred);
    
  9. Chame resolver.resolveSignIn() para concluir a autenticação secundária. Você pode então acessar o resultado do login original, que inclui os dados específicos do provedor padrão e as credenciais de autenticação:

    Web version 9

    // Complete sign-in. This will also trigger the Auth state listeners.
    resolver.resolveSignIn(multiFactorAssertion)
        .then(function (userCredential) {
            // userCredential will also contain the user, additionalUserInfo, optional
            // credential (null for email/password) associated with the first factor sign-in.
    
            // For example, if the user signed in with Google as a first factor,
            // userCredential.additionalUserInfo will contain data related to Google 
            // provider that the user signed in with.
            // - user.credential contains the Google OAuth credential.
            // - user.credential.accessToken contains the Google OAuth access token.
            // - user.credential.idToken contains the Google OAuth ID token.
        });
    

    Web version 8

    // Complete sign-in. This will also trigger the Auth state listeners.
    resolver.resolveSignIn(multiFactorAssertion)
      .then(function(userCredential) {
        // userCredential will also contain the user, additionalUserInfo, optional
        // credential (null for email/password) associated with the first factor sign-in.
        // For example, if the user signed in with Google as a first factor,
        // userCredential.additionalUserInfo will contain data related to Google provider that
        // the user signed in with.
        // user.credential contains the Google OAuth credential.
        // user.credential.accessToken contains the Google OAuth access token.
        // user.credential.idToken contains the Google OAuth ID token.
      });
    

O código abaixo mostra um exemplo completo de login de um usuário multifator:

Web version 9

import {
    getAuth,
    getMultiFactorResolver,
    PhoneAuthProvider,
    PhoneMultiFactorGenerator,
    RecaptchaVerifier,
    signInWithEmailAndPassword
} from "firebase/auth";

const recaptchaVerifier = new RecaptchaVerifier('recaptcha-container-id', undefined, auth);

const auth = getAuth();
signInWithEmailAndPassword(auth, email, password)
    .then(function (userCredential) {
        // User is not enrolled with a second factor and is successfully
        // signed in.
        // ...
    })
    .catch(function (error) {
        if (error.code == 'auth/multi-factor-auth-required') {
            const resolver = getMultiFactorResolver(auth, error);
            // Ask user which second factor to use.
            if (resolver.hints[selectedIndex].factorId ===
                PhoneMultiFactorGenerator.FACTOR_ID) {
                const phoneInfoOptions = {
                    multiFactorHint: resolver.hints[selectedIndex],
                    session: resolver.session
                };
                const phoneAuthProvider = new PhoneAuthProvider(auth);
                // Send SMS verification code
                return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
                    .then(function (verificationId) {
                        // Ask user for the SMS verification code. Then:
                        const cred = PhoneAuthProvider.credential(
                            verificationId, verificationCode);
                        const multiFactorAssertion =
                            PhoneMultiFactorGenerator.assertion(cred);
                        // Complete sign-in.
                        return resolver.resolveSignIn(multiFactorAssertion)
                    })
                    .then(function (userCredential) {
                        // User successfully signed in with the second factor phone number.
                    });
            } else {
                // Unsupported second factor.
            }
        } else if (error.code == 'auth/wrong-password') {
            // Handle other errors such as wrong password.
        }
    });

Web version 8

var resolver;
firebase.auth().signInWithEmailAndPassword(email, password)
  .then(function(userCredential) {
    // User is not enrolled with a second factor and is successfully signed in.
    // ...
  })
  .catch(function(error) {
    if (error.code == 'auth/multi-factor-auth-required') {
      resolver = error.resolver;
      // Ask user which second factor to use.
      if (resolver.hints[selectedIndex].factorId ===
          firebase.auth.PhoneMultiFactorGenerator.FACTOR_ID) {
        var phoneInfoOptions = {
          multiFactorHint: resolver.hints[selectedIndex],
          session: resolver.session
        };
        var phoneAuthProvider = new firebase.auth.PhoneAuthProvider();
        // Send SMS verification code
        return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions, recaptchaVerifier)
          .then(function(verificationId) {
            // Ask user for the SMS verification code.
            var cred = firebase.auth.PhoneAuthProvider.credential(
                verificationId, verificationCode);
            var multiFactorAssertion =
                firebase.auth.PhoneMultiFactorGenerator.assertion(cred);
            // Complete sign-in.
            return resolver.resolveSignIn(multiFactorAssertion)
          })
          .then(function(userCredential) {
            // User successfully signed in with the second factor phone number.
          });
      } else {
        // Unsupported second factor.
      }
    } else if (error.code == 'auth/wrong-password') {
      // Handle other errors such as wrong password.
    } ...
  });

Parabéns! Você fez login com sucesso em um usuário usando a autenticação multifator.

Qual é o próximo