Autenticarse con Firebase con un número de teléfono usando JavaScript

Puede utilizar Firebase Authentication para iniciar sesión en un usuario enviando un mensaje SMS al teléfono del usuario. El usuario inicia sesión utilizando un código de un solo uso contenido en el mensaje SMS.

La forma más sencilla de agregar el inicio de sesión con un número de teléfono a su aplicación es usar FirebaseUI , que incluye un widget de inicio de sesión directo que implementa flujos de inicio de sesión para el inicio de sesión con un número de teléfono, así como un inicio de sesión federado y basado en contraseña. -en. Este documento describe cómo implementar un flujo de inicio de sesión con un número de teléfono mediante el SDK de Firebase.

Antes de que empieces

Si aún no lo has hecho, copia el fragmento de inicialización de Firebase console a tu proyecto como se describe en Agregar Firebase a tu proyecto de JavaScript .

Preocupaciones de seguridad

La autenticación utilizando sólo un número de teléfono, si bien es conveniente, es menos segura que otros métodos disponibles, porque la posesión de un número de teléfono puede transferirse fácilmente entre usuarios. Además, en dispositivos con múltiples perfiles de usuario, cualquier usuario que pueda recibir mensajes SMS puede iniciar sesión en una cuenta utilizando el número de teléfono del dispositivo.

Si utiliza el inicio de sesión basado en un número de teléfono en su aplicación, debe ofrecerlo junto con métodos de inicio de sesión más seguros e informar a los usuarios sobre las ventajas y desventajas de seguridad que implica el uso del inicio de sesión por número de teléfono.

Habilite el inicio de sesión con número de teléfono para su proyecto de Firebase

Para iniciar sesión de usuarios mediante SMS, primero debes habilitar el método de inicio de sesión con número de teléfono para tu proyecto de Firebase:

  1. En Firebase console , abre la sección Autenticación .
  2. En la página Método de inicio de sesión , habilite el método de inicio de sesión por número de teléfono .
  3. En la misma página, si el dominio que alojará su aplicación no aparece en la sección Dominios de redireccionamiento de OAuth , agregue su dominio.

La cuota de solicitudes de inicio de sesión de números de teléfono de Firebase es lo suficientemente alta como para que la mayoría de las aplicaciones no se vean afectadas. Sin embargo, si necesita iniciar sesión en un volumen muy grande de usuarios con autenticación telefónica, es posible que deba actualizar su plan de precios. Vea la página de precios .

Configurar el verificador reCAPTCHA

Antes de poder iniciar sesión en los usuarios con sus números de teléfono, debes configurar el verificador reCAPTCHA de Firebase. Firebase usa reCAPTCHA para evitar abusos, como garantizar que la solicitud de verificación del número de teléfono provenga de uno de los dominios permitidos de su aplicación.

No es necesario configurar manualmente un cliente reCAPTCHA; Cuando usas el objeto RecaptchaVerifier del SDK de Firebase, Firebase crea y maneja automáticamente las claves y secretos de cliente necesarios.

El objeto RecaptchaVerifier admite reCAPTCHA invisible , que a menudo puede verificar al usuario sin requerir ninguna acción del usuario, así como el widget reCAPTCHA, que siempre requiere la interacción del usuario para completarse exitosamente.

El reCAPTCHA renderizado subyacente se puede localizar según las preferencias del usuario actualizando el código de idioma en la instancia de autenticación antes de renderizar el reCAPTCHA. La localización antes mencionada también se aplicará al mensaje SMS enviado al usuario, que contenga el código de verificación.

Web modular API

import { getAuth } from "firebase/auth";

const auth = getAuth();
auth.languageCode = 'it';
// To apply the default browser preference instead of explicitly setting it.
// auth.useDeviceLanguage();

Web namespaced API

firebase.auth().languageCode = 'it';
// To apply the default browser preference instead of explicitly setting it.
// firebase.auth().useDeviceLanguage();

Utilice reCAPTCHA invisible

Para usar un reCAPTCHA invisible, cree un objeto RecaptchaVerifier con el parámetro size establecido en invisible , especificando el ID del botón que envía su formulario de inicio de sesión. Por ejemplo:

Web modular API

import { getAuth, RecaptchaVerifier } from "firebase/auth";

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'sign-in-button', {
  'size': 'invisible',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    onSignInSubmit();
  }
});

Web namespaced API

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
  'size': 'invisible',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    onSignInSubmit();
  }
});

Utilice el widget reCAPTCHA

Para usar el widget reCAPTCHA visible, cree un elemento en su página para contener el widget y luego cree un objeto RecaptchaVerifier , especificando el ID del contenedor cuando lo haga. Por ejemplo:

Web modular API

import { getAuth, RecaptchaVerifier } from "firebase/auth";

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', {});

Web namespaced API

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');

Opcional: especifique los parámetros de reCAPTCHA

Opcionalmente, puede configurar funciones de devolución de llamada en el objeto RecaptchaVerifier que se llaman cuando el usuario resuelve el reCAPTCHA o el reCAPTCHA caduca antes de que el usuario envíe el formulario:

Web modular API

import { getAuth, RecaptchaVerifier } from "firebase/auth";

const auth = getAuth();
window.recaptchaVerifier = new RecaptchaVerifier(auth, 'recaptcha-container', {
  'size': 'normal',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    // ...
  },
  'expired-callback': () => {
    // Response expired. Ask user to solve reCAPTCHA again.
    // ...
  }
});

Web namespaced API

window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container', {
  'size': 'normal',
  'callback': (response) => {
    // reCAPTCHA solved, allow signInWithPhoneNumber.
    // ...
  },
  'expired-callback': () => {
    // Response expired. Ask user to solve reCAPTCHA again.
    // ...
  }
});

Opcional: renderice previamente el reCAPTCHA

Si desea prerenderizar el reCAPTCHA antes de enviar una solicitud de inicio de sesión, llame a render :

Web modular API

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

Web namespaced API

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

Después de que render , obtienes el ID del widget de reCAPTCHA, que puedes usar para realizar llamadas a la API de reCAPTCHA :

Web modular API

const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);

Web namespaced API

const recaptchaResponse = grecaptcha.getResponse(recaptchaWidgetId);

Enviar un código de verificación al teléfono del usuario

Para iniciar el inicio de sesión con el número de teléfono, presente al usuario una interfaz que le solicite que proporcione su número de teléfono y luego llame a signInWithPhoneNumber para solicitar que Firebase envíe un código de autenticación al teléfono del usuario por SMS:

  1. Obtenga el número de teléfono del usuario.

    Los requisitos legales varían, pero como práctica recomendada y para establecer expectativas para sus usuarios, debe informarles que si utilizan el inicio de sesión por teléfono, es posible que reciban un mensaje SMS para verificación y se aplicarán tarifas estándar.

  2. Llame signInWithPhoneNumber , pasándole el número de teléfono del usuario y el RecaptchaVerifier que creó anteriormente.

    Web modular API

    import { getAuth, signInWithPhoneNumber } from "firebase/auth";
    
    const phoneNumber = getPhoneNumberFromUserInput();
    const appVerifier = window.recaptchaVerifier;
    
    const auth = getAuth();
    signInWithPhoneNumber(auth, phoneNumber, appVerifier)
        .then((confirmationResult) => {
          // SMS sent. Prompt user to type the code from the message, then sign the
          // user in with confirmationResult.confirm(code).
          window.confirmationResult = confirmationResult;
          // ...
        }).catch((error) => {
          // Error; SMS not sent
          // ...
        });

    Web namespaced API

    const phoneNumber = getPhoneNumberFromUserInput();
    const appVerifier = window.recaptchaVerifier;
    firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
        .then((confirmationResult) => {
          // SMS sent. Prompt user to type the code from the message, then sign the
          // user in with confirmationResult.confirm(code).
          window.confirmationResult = confirmationResult;
          // ...
        }).catch((error) => {
          // Error; SMS not sent
          // ...
        });
    Si signInWithPhoneNumber genera un error, restablezca el reCAPTCHA para que el usuario pueda intentarlo nuevamente:
    grecaptcha.reset(window.recaptchaWidgetId);
    
    // Or, if you haven't stored the widget ID:
    window.recaptchaVerifier.render().then(function(widgetId) {
      grecaptcha.reset(widgetId);
    });
    

El método signInWithPhoneNumber emite el desafío reCAPTCHA al usuario y, si el usuario supera el desafío, solicita que Firebase Authentication envíe un mensaje SMS que contenga un código de verificación al teléfono del usuario.

Inicia sesión como usuario con el código de verificación.

Después de que la llamada para iniciar signInWithPhoneNumber sea exitosa, solicite al usuario que escriba el código de verificación que recibió por SMS. Luego, inicie sesión como usuario pasando el código al método confirm del objeto ConfirmationResult que se pasó al controlador de cumplimiento de signInWithPhoneNumber (es decir, su bloque then ). Por ejemplo:

Web modular API

const code = getCodeFromUserInput();
confirmationResult.confirm(code).then((result) => {
  // User signed in successfully.
  const user = result.user;
  // ...
}).catch((error) => {
  // User couldn't sign in (bad verification code?)
  // ...
});

Web namespaced API

const code = getCodeFromUserInput();
confirmationResult.confirm(code).then((result) => {
  // User signed in successfully.
  const user = result.user;
  // ...
}).catch((error) => {
  // User couldn't sign in (bad verification code?)
  // ...
});

Si la llamada para confirm tuvo éxito, el usuario inició sesión correctamente.

Obtenga el objeto AuthCredential intermedio

Si necesita obtener un objeto AuthCredential para la cuenta del usuario, pase el código de verificación del resultado de la confirmación y el código de verificación a PhoneAuthProvider.credential en lugar de llamar confirm :

var credential = firebase.auth.PhoneAuthProvider.credential(confirmationResult.verificationId, code);

Luego, puede iniciar sesión como usuario con la credencial:

firebase.auth().signInWithCredential(credential);

Prueba con números de teléfono ficticios

Puedes configurar números de teléfono ficticios para el desarrollo a través de Firebase console. Las pruebas con números de teléfono ficticios brindan estos beneficios:

  • Pruebe la autenticación del número de teléfono sin consumir su cuota de uso.
  • Pruebe la autenticación del número de teléfono sin enviar un mensaje SMS real.
  • Realiza pruebas consecutivas con el mismo número de teléfono sin que te limiten. Esto minimiza el riesgo de rechazo durante el proceso de revisión de la tienda de aplicaciones si el revisor utiliza el mismo número de teléfono para la prueba.
  • Pruebe fácilmente en entornos de desarrollo sin ningún esfuerzo adicional, como la capacidad de desarrollar en un simulador de iOS o un emulador de Android sin los servicios de Google Play.
  • Escriba pruebas de integración sin verse bloqueado por controles de seguridad que normalmente se aplican a números de teléfono reales en un entorno de producción.

Los números de teléfono ficticios deben cumplir estos requisitos:

  1. Asegúrese de utilizar números de teléfono que sean realmente ficticios y que no existan ya. Firebase Authentication no le permite configurar números de teléfono existentes utilizados por usuarios reales como números de prueba. Una opción es utilizar números con prefijo 555 como números de teléfono de prueba de EE. UU., por ejemplo: +1 650-555-3434
  2. Los números de teléfono deben tener el formato correcto según la longitud y otras restricciones. Seguirán pasando por la misma validación que el número de teléfono de un usuario real.
  3. Puede agregar hasta 10 números de teléfono para el desarrollo.
  4. Utilice números/códigos de teléfono de prueba que sean difíciles de adivinar y cámbielos con frecuencia.

Crea números de teléfono ficticios y códigos de verificación.

  1. En Firebase console , abre la sección Autenticación .
  2. En la pestaña Método de inicio de sesión , habilite el Proveedor de teléfono si aún no lo ha hecho.
  3. Abra el menú Números de teléfono para probar el acordeón.
  4. Proporcione el número de teléfono que desea probar, por ejemplo: +1 650-555-3434 .
  5. Proporcione el código de verificación de 6 dígitos para ese número específico, por ejemplo: 654321 .
  6. Añade el número. Si es necesario, puedes eliminar el número de teléfono y su código colocando el cursor sobre la fila correspondiente y haciendo clic en el icono de la papelera.

Prueba manual

Puede comenzar a usar directamente un número de teléfono ficticio en su aplicación. Esto le permite realizar pruebas manuales durante las etapas de desarrollo sin tener problemas de cuotas ni limitaciones. También puedes realizar la prueba directamente desde un simulador de iOS o un emulador de Android sin tener instalados los servicios de Google Play.

Cuando proporciona el número de teléfono ficticio y envía el código de verificación, no se envía ningún SMS real. En su lugar, debe proporcionar el código de verificación configurado previamente para completar el inicio de sesión.

Al finalizar el inicio de sesión, se crea un usuario de Firebase con ese número de teléfono. El usuario tiene el mismo comportamiento y propiedades que un usuario de número de teléfono real y puede acceder a Realtime Database/Cloud Firestore y otros servicios de la misma manera. El token de identificación acuñado durante este proceso tiene la misma firma que un usuario de número de teléfono real.

Otra opción es establecer un rol de prueba mediante reclamos personalizados para estos usuarios para diferenciarlos como usuarios falsos si desea restringir aún más el acceso.

Pruebas de integración

Además de las pruebas manuales, Firebase Authentication proporciona API para ayudar a escribir pruebas de integración para las pruebas de autenticación telefónica. Estas API desactivan la verificación de aplicaciones al desactivar el requisito de reCAPTCHA en la web y las notificaciones push silenciosas en iOS. Esto hace que las pruebas de automatización sean posibles en estos flujos y más fáciles de implementar. Además, ayudan a brindar la capacidad de probar flujos de verificación instantánea en Android.

En la web, configura appVerificationDisabledForTesting en true antes de renderizar firebase.auth.RecaptchaVerifier . Esto resuelve el reCAPTCHA automáticamente, permitiéndole pasar el número de teléfono sin resolverlo manualmente. Tenga en cuenta que, aunque reCAPTCHA esté deshabilitado, el uso de un número de teléfono no ficticio no permitirá completar el inicio de sesión. Solo se pueden usar números de teléfono ficticios con esta API.

// Turn off phone auth app verification.
firebase.auth().settings.appVerificationDisabledForTesting = true;

var phoneNumber = "+16505554567";
var testVerificationCode = "123456";

// This will render a fake reCAPTCHA as appVerificationDisabledForTesting is true.
// This will resolve after rendering without app verification.
var appVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
// signInWithPhoneNumber will call appVerifier.verify() which will resolve with a fake
// reCAPTCHA response.
firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier)
    .then(function (confirmationResult) {
      // confirmationResult can resolve with the fictional testVerificationCode above.
      return confirmationResult.confirm(testVerificationCode)
    }).catch(function (error) {
      // Error; SMS not sent
      // ...
    });

Los verificadores simulados de aplicaciones reCAPTCHA visibles e invisibles se comportan de manera diferente cuando la verificación de aplicaciones está deshabilitada:

  • ReCAPTCHA visible : cuando el reCAPTCHA visible se procesa a través de appVerifier.render() , se resuelve automáticamente después de una fracción de segundo de retraso. Esto equivale a que un usuario haga clic en reCAPTCHA inmediatamente después de renderizar. La respuesta reCAPTCHA caducará después de un tiempo y luego se resolverá automáticamente nuevamente.
  • ReCAPTCHA invisible : el reCAPTCHA invisible no se resuelve automáticamente al renderizar, sino que lo hace en la llamada appVerifier.verify() o cuando se hace clic en el botón de anclaje del reCAPTCHA después de una fracción de segundo de retraso. De manera similar, la respuesta caducará después de un tiempo y solo se resolverá automáticamente después de la llamada a appVerifier.verify() o cuando se haga clic nuevamente en el botón ancla del reCAPTCHA.

Siempre que se resuelve un reCAPTCHA simulado, la función de devolución de llamada correspondiente se activa como se esperaba con la respuesta falsa. Si también se especifica una devolución de llamada de vencimiento, se activará al vencimiento.

Próximos pasos

Después de que un usuario inicia sesión por primera vez, se crea una nueva cuenta de usuario y se vincula a las credenciales (es decir, el nombre de usuario y la contraseña, el número de teléfono o la información del proveedor de autenticación) con las que el usuario inició sesión. Esta nueva cuenta se almacena como parte de su proyecto de Firebase y se puede usar para identificar a un usuario en cada aplicación de su proyecto, independientemente de cómo inicie sesión el usuario.

  • En sus aplicaciones, la forma recomendada de conocer el estado de autenticación de su usuario es configurar un observador en el objeto Auth . Luego puede obtener la información básica del perfil del usuario desde el objeto User . Consulte Administrar usuarios .

  • En las reglas de seguridad de Firebase Realtime Database y Cloud Storage, puede obtener el ID de usuario único del usuario que inició sesión a partir de la variable auth y usarlo para controlar a qué datos puede acceder un usuario.

Puede permitir que los usuarios inicien sesión en su aplicación utilizando múltiples proveedores de autenticación vinculando las credenciales del proveedor de autenticación a una cuenta de usuario existente.

Para cerrar la sesión de un usuario, llame signOut :

Web modular API

import { getAuth, signOut } from "firebase/auth";

const auth = getAuth();
signOut(auth).then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});

Web namespaced API

firebase.auth().signOut().then(() => {
  // Sign-out successful.
}).catch((error) => {
  // An error happened.
});