Ir a la consola

Autentica con Firebase en iOS mediante un número de teléfono

Puedes usar Firebase Authentication para hacer que un usuario acceda mediante el envío de un mensaje SMS a su teléfono. El usuario accede con un código único que se incluye en el mensaje SMS.

La forma más fácil de agregar un acceso con número de teléfono a la app es usar FirebaseUI, que incluye un widget de acceso directo que implementa flujos de acceso con número de teléfono, además de acceso federado y con contraseña. En este documento, se describe cómo implementar un flujo de acceso con el número de teléfono mediante el uso del SDK de Firebase.

Antes de comenzar

  1. Agrega Firebase a tu proyecto de iOS.
  2. Incluye los siguientes pods en tu Podfile:
    pod 'Firebase/Auth'
  3. Si aún no conectaste la app al proyecto de Firebase, puedes hacerlo desde Firebase console.

Preocupaciones de seguridad

Si bien la autenticación con solo un número de teléfono es conveniente, es menos segura que otros métodos disponibles, ya que la posesión de un número de teléfono se puede transferir con facilidad entre usuarios. Además, en los dispositivos con varios perfiles de usuario, cualquier usuario que reciba mensajes SMS puede acceder a una cuenta con el número de teléfono del dispositivo.

Si usas el acceso con número de teléfono en la app, deberías ofrecerlo junto con métodos de acceso más seguros, además de informar a los usuarios acerca de las desventajas de usar el acceso con número de teléfono.

Habilita el acceso con número de teléfono para el proyecto de Firebase

Para que los usuarios accedan a través de SMS, primero debes habilitar el método de acceso con el número de teléfono para el proyecto de Firebase:

  1. En Firebase console, abre la sección Authentication.
  2. En la página Método de acceso, habilita el método de acceso Número de teléfono.

La cuota de solicitudes de acceso con el número de teléfono de Firebase es lo suficientemente alta para que la mayoría de las apps no tengan problemas. Sin embargo, si necesitas permitir el acceso de un gran volumen de usuarios con autenticación por teléfono, es posible que debas actualizar tu plan de precios. Consulta la página de precios.

Habilita la verificación de la app

Para usar la autenticación con número de teléfono, Firebase debe poder verificar que las solicitudes de acceso con número de teléfono provienen de la app. Firebase Authentication hace esto de dos maneras:

  • Notificaciones silenciosas del APN: Cuando un usuario accede con su número de teléfono por primera vez en un dispositivo, Firebase Authentication envía un token al dispositivo mediante una notificación push silenciosa. Si la aplicación recibe correctamente la notificación de Firebase, se puede acceder con el número de teléfono.

    Para iOS 8.0 y versiones más recientes, las notificaciones silenciosas no necesitan el consentimiento explícito del usuario y; por lo tanto, no se ven afectadas si un usuario rechaza recibir notificaciones del APN en la app.3 Por lo tanto, no es necesario que la app solicite permiso del usuario para recibir notificaciones push cuando se implementa la autenticación con Firebase mediante el número de teléfono.

  • Verificación con reCAPTCHA: En el caso de que no sea posible enviar o recibir una notificación push silenciosa, como cuando el usuario inhabilita la actualización en segundo plano para la aplicación o cuando la prueba en un simulador de iOS, Firebase Authentication utiliza la verificación con reCAPTCHA para completar el flujo del acceso con número de teléfono. El desafío de reCAPTCHA a menudo se puede completar sin que el usuario tenga que resolver nada.

Si las notificaciones push silenciosas están configuradas correctamente, solo un porcentaje muy bajo de los usuarios tendrá que realizar la verificación con reCAPTCHA. No obstante, debes asegurarte de que el acceso con el número de teléfono funcione correctamente, independientemente de si las notificaciones push silenciosas están disponibles o no.

Comienza a recibir notificaciones silenciosas

Para habilitar las notificaciones del APN a fin de usarlas con Firebase Authentication, haz lo siguiente:

  1. En Xcode, habilita las notificaciones push para el proyecto.
  2. Sube la clave de autenticación del APN a Firebase. Si aún no tienes una clave de autenticación del APN, consulta cómo configurar el APN con FCM.

    1. Dentro del proyecto en Firebase console, selecciona el ícono de ajustes, selecciona Configuración del proyecto y, luego, la pestaña Cloud Messaging.

    2. En Clave de autenticación del APN, bajo configuración de app de iOS, haz clic en el botón Subir.

    3. Busca la ubicación donde guardaste la clave, selecciónala y haz clic en Abrir. Agrega el ID de clave correspondiente (disponible en Certificados, identificadores y perfiles en el Centro de miembros desarrolladores de Apple) y haz clic en Subir.

    Si ya tienes un certificado de APN, puedes subirlo para completar el proceso.

Configura la verificación de reCAPTCHA

Para permitir que el SDK de Firebase use la verificación de reCAPTCHA:

  1. Agrega esquemas de URL personalizadas al proyecto de Xcode:
    1. Abre la configuración del proyecto: haz doble clic en el nombre del proyecto en la vista de árbol a la izquierda. Selecciona la app en la sección OBJETIVOS, haz clic en la pestaña Información y expande la sección Tipos de URL.
    2. Haz clic en el botón + y agrega un esquema de URL para tu ID de cliente invertido. A fin de obtener este valor, abre el archivo de configuración GoogleService-Info.plist, y busca la clave REVERSED_CLIENT_ID. Copia el valor de esa clave y pégalo en el recuadro Esquemas de URL en la página de configuración. Deja los demás campos en blanco.

      Cuando termines, tu configuración debería ser similar a la que se muestra a continuación (pero con los valores específicos de la aplicación):

  2. Opcional: Si deseas personalizar la forma en que tu app presenta SFSafariViewController o UIWebView cuando se le muestra el reCAPTCHA al usuario, crea una clase personalizada conforme al protocolo FIRAuthUIDelegate y pásala a verifyPhoneNumber:UIDelegate:completion:.

Envía un código de verificación al teléfono del usuario

Para iniciar el acceso con número de teléfono, muéstrale al usuario una interfaz que le pida ingresar su número de teléfono y después llama a verifyPhoneNumber:UIDelegate:completion: para solicitar que Firebase envíe un código de autenticación al teléfono del usuario mediante SMS:

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

    Los requisitos legales varían, pero es recomendable establecer las expectativas de los usuarios informándoles que, si usan el acceso con el teléfono, es posible que reciban un mensaje SMS para la verificación y que se aplicarán las tarifas estándar.

  2. Llama a verifyPhoneNumber:UIDelegate:completion: y pásale el número de teléfono del usuario.

    Swift

    PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: nil) { (verificationID, error) in
      if let error = error {
        self.showMessagePrompt(error.localizedDescription)
        return
      }
      // Sign in using the verificationID and the code sent to the user
      // ...
    }

    Objective-C

    [[FIRPhoneAuthProvider provider] verifyPhoneNumber:userInput
                                            UIDelegate:nil
                                            completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
      if (error) {
        [self showMessagePrompt:error.localizedDescription];
        return;
      }
      // Sign in using the verificationID and the code sent to the user
      // ...
    }];

    Cuando llamas a verifyPhoneNumber:UIDelegate:completion:, Firebase envía una notificación push silenciosa a la app o le muestra un desafío de reCAPTCHA al usuario. Cuando la app recibe la notificación o el usuario completa el desafío de reCAPTCHA, Firebase envía un mensaje de SMS que contiene un código de autenticación al número de teléfono especificado y pasa un ID de verificación a la función de finalización. Para que el usuario acceda, necesitarás el código de verificación y el ID de verificación.

    El mensaje SMS que envía Firebase también puede localizarse si especificas el idioma de autenticación en la propiedad languageCode en tu instancia de Auth.

    Swift

     // Change language code to french.
     Auth.auth().languageCode = "fr";
    

    Objective-C

     // Change language code to french.
     [FIRAuth auth].languageCode = @"fr";
    
  3. Guarda el ID de verificación y restablécelo cuando se cargue la app. Así te aseguras de tener un ID de verificación válido incluso si la app se cierra antes de que el usuario complete el flujo de acceso (por ejemplo, cuando cambia a la app de SMS).

    Puedes conservar el ID de verificación de la manera que desees. Una manera sencilla es guardar el ID de verificación con el objeto NSUserDefaults:

    Swift

    UserDefaults.standard.set(verificationID, forKey: "authVerificationID")
    

    Objective-C

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:verificationID forKey:@"authVerificationID"];
    

    A continuación, puedes restablecer el valor guardado:

    Swift

    let verificationID = UserDefaults.standard.string(forKey: "authVerificationID")
    

    Objective-C

    NSString *verificationID = [defaults stringForKey:@"authVerificationID"];
    

Si la llamada a verifyPhoneNumber:UIDelegate:completion: se ejecuta correctamente, puedes pedirle al usuario que ingrese el código de verificación cuando lo reciba en el mensaje SMS.

Permite el acceso del usuario con el código de verificación

Después de que el usuario ingrese en la app el código de verificación que recibió en el mensaje SMS, haz que acceda. Para ello, crea el objeto FIRPhoneAuthCredential a partir del código y el ID de verificación y pásalo a signInWithCredential:completion:

  1. Obtén el código de verificación del usuario.
  2. Crea un objeto FIRPhoneAuthCredential a partir del código de verificación y el ID de verificación.

    Swift

    let credential = PhoneAuthProvider.provider().credential(
        withVerificationID: verificationID,
        verificationCode: verificationCode)

    Objective-C

    FIRAuthCredential *credential = [[FIRPhoneAuthProvider provider]
        credentialWithVerificationID:verificationID
                    verificationCode:userInput];
  3. Haz que el usuario acceda con el objeto FIRPhoneAuthCredential:

    Swift

    Auth.auth().signInAndRetrieveData(with: credential) { (authResult, error) in
      if let error = error {
        // ...
        return
      }
      // User is signed in
      // ...
    }

    Objective-C

    [[FIRAuth auth] signInAndRetrieveDataWithCredential:credential
                                             completion:^(FIRAuthDataResult * _Nullable authResult,
                                                          NSError * _Nullable error) {
      if (error) {
        // ...
        return;
      }
      // User successfully signed in. Get user data from the FIRUser object
      if (authResult == nil) { return; }
      FIRUser *user = authResult.user;
      // ...
    }];

Prueba con números de teléfono incluidos en la lista blanca

Puedes incluir números de teléfono para desarrollo en la lista blanca a través de Firebase console. Una lista blanca de números de teléfono ofrece los siguientes beneficios:

  • Prueba la autenticación del número de teléfono sin consumir tu cuota de uso.
  • Prueba la autenticación del número de teléfono sin enviar un mensaje SMS real.
  • Ejecuta pruebas consecutivas con el mismo número de teléfono sin regulación. 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 las pruebas.
  • Realiza pruebas con facilidad en entornos de desarrollo sin ningún esfuerzo adicional, por ejemplo, obtén la capacidad de desarrollar en un simulador de iOS o un emulador de Android sin los Servicios de Google Play.
  • Escribe pruebas de integración sin ser bloqueado por los controles de seguridad que normalmente se aplican a los números de teléfono reales en un entorno de producción.

Para incluir números de teléfono en la lista blanca, es necesario cumplir estos requisitos:

  1. Asegúrate de usar números ficticios que aún no existan. Firebase Authentication no permite incluir en la lista blanca números de teléfono existentes, que tengan usuarios reales. Una opción es usar números con el 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 adecuado de longitud y otras restricciones. Estos números pasarán por la misma validación que el número de teléfono de un usuario real.
  3. Puedes agregar hasta 10 números de teléfono.
  4. Usa códigos o números de teléfono de prueba que sean difíciles de adivinar y cámbialos con frecuencia.

Incluye números de teléfono y códigos de verificación en la lista blanca

  1. En Firebase console, abre la sección Authentication.
  2. En la pestaña Método de acceso, habilita el proveedor de telefonía, si todavía no lo has hecho.
  3. Abre el menú de acordeón Números de teléfono para la prueba.
  4. Proporciona el número de teléfono que deseas probar, por ejemplo: +1 650-555-3434.
  5. Proporciona el código de verificación de 6 dígitos para ese número específico, por ejemplo: 654321.
  6. Agrega el número. Si es necesario, puedes desplazarte sobre la fila correspondiente y hacer clic en el ícono de papelera para borrar el número de teléfono y su código.

Pruebas manuales

En tu aplicación, puedes comenzar a usar directamente un número de teléfono incluido en la lista blanca. Esto te permite realizar pruebas manuales durante las etapas de desarrollo sin que te encuentres con problemas de cuota o regulación. También puedes realizar pruebas directamente desde un simulador de iOS o un emulador de Android sin tener los Servicios de Google Play instalados.

Cuando se proporciona el número de teléfono incluido en la lista blanca y se envía el código de verificación, no se envía ningún SMS real. En lugar de eso, es necesario proporcionar el código de verificación previamente configurado para completar el acceso.

Cuando se completa el acceso, se crea un usuario de Firebase con ese número de teléfono. El usuario tiene el mismo comportamiento y las mismas propiedades que el usuario de un número de teléfono real, y puede acceder de la misma manera a Realtime Database, Cloud Firestore y otros servicios. El token de ID emitido durante este proceso tiene la misma firma que el usuario de un número de teléfono real.

Otra opción es configurar una función de prueba mediante reclamaciones personalizadas en estos usuarios para diferenciarlos como usuarios falsos si se desea restringir más el acceso.

Pruebas de integración

Además de las pruebas manuales, Firebase Authentication proporciona las API con las que es posible escribir pruebas de integración para la autenticación del teléfono. Para inhabilitar la verificación de app, estas API inhabilitan el requisito reCAPTCHA en las notificaciones push silenciosas y web en iOS. Esto permite que se realicen las pruebas de automatización en estos flujos y facilita su implementación. Además, las API proporcionan la capacidad de probar flujos de verificación instantánea en Android.

En iOS, la configuración appVerificationDisabledForTesting debe establecerse como TRUE antes de llamar a verifyPhoneNumber. Esto se procesa sin requerir un token de APN o sin enviar notificaciones push silenciosas en segundo plano, lo que facilita realizar la prueba en un simulador. Esto también inhabilita el flujo de resguardo de reCAPTCHA.

Ten en cuenta que incluso si la verificación de app está inhabilitada, el uso de un número de teléfono que no esté en la lista blanca no completará el acceso. Solo se pueden usar números de teléfono incluidos en la lista blanca con esta API.

Swift

let phoneNumber = "+16505554567"

// This test verification code is specified for the given test phone number in the developer console.
let testVerificationCode = "123456"

Auth.auth().settings.isAppVerificationDisabledForTesting = TRUE
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate:nil) {
                                                            verificationID, error in
    if (error) {
      // Handles error
      self.handleError(error)
      return
    }
    let credential = PhoneAuthProvider.provider().credential(withVerificationID: verificationID ?? "",
                                                               verificationCode: testVerificationCode)
    Auth.auth().signInAndRetrieveData(with: credential) { authData, error in
      if (error) {
        // Handles error
        self.handleError(error)
        return
      }
      _user = authData.user
    }];
}];

Objective-C

NSString *phoneNumber = @"+16505554567";

// This test verification code is specified for the given test phone number in the developer console.
NSString *testVerificationCode = @"123456";

[FIRAuth auth].settings.appVerificationDisabledForTesting = YES;
[[FIRPhoneAuthProvider provider] verifyPhoneNumber:phoneNumber
                                        completion:^(NSString *_Nullable verificationID,
                                                     NSError *_Nullable error) {
    if (error) {
      // Handles error
      [self handleError:error];
      return;
    }
    FIRAuthCredential *credential =
        [FIRPhoneAuthProvider credentialWithVerificationID:verificationID
                                          verificationCode:testVerificationCode];
    [FIRAuth auth] signInWithAndRetrieveDataWithCredential:credential
                                                completion:^(FIRUser *_Nullable user,
                                                             NSError *_Nullable error) {
      if (error) {
        // Handles error
        [self handleError:error];
        return;
      }
      _user = user;
    }];
}];

Apéndice: Usa el acceso con número de teléfono sin referencia

Firebase Authentication usa las referencias de métodos para obtener automáticamente el token de la app para el APN, para administrar las notificaciones push silenciosas que Firebase envía a la app y para interceptar los redireccionamientos personalizados de la página de verificación de reCAPTCHA durante la verificación.

Si prefieres no usar referencias, puedes inhabilitarlas. Para ello, agrega la marca FirebaseAppDelegateProxyEnabled al archivo Info.plist de la app y asígnale el valor NO. Ten en cuenta que asignarle el valor NO a esta marca también inhabilita las referencias de otros productos de Firebase, incluido Firebase Cloud Messaging.

Si inhabilitas las referencias, debes pasar el token de dispositivo del APN, las notificaciones push y la URL de redireccionamiento del esquema personalizado de manera explícita a Firebase Authentication.

Para obtener el token de dispositivo del APN, implementa el método application:didRegisterForRemoteNotificationsWithDeviceToken: y pasa el token de dispositivo al método setAPNSToken:type: de FIRAuth.

Swift

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
  // Pass device token to auth
  Auth.auth().setAPNSToken(deviceToken, type: AuthAPNSTokenTypeProd)

  // Further handling of the device token if needed by the app
  // ...
}

Objective-C

- (void)application:(UIApplication *)application
    didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  // Pass device token to auth.
  [[FIRAuth auth] setAPNSToken:deviceToken type:FIRAuthAPNSTokenTypeProd];
  // Further handling of the device token if needed by the app.
}

Para manejar notificaciones push, en el método application:didReceiveRemoteNotification:fetchCompletionHandler:, llama al método canHandleNotification: de FIRAuth a fin de verificar si hay notificaciones relacionadas de Firebase Authentication.

Swift

func application(_ application: UIApplication,
    didReceiveRemoteNotification notification: [AnyHashable : Any],
    fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
  if Auth.auth().canHandleNotification(notification) {
    completionHandler(UIBackgroundFetchResultNoData)
    return
  }
  // This notification is not auth related, developer should handle it.
}

Objective-C

- (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)notification
          fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  // Pass notification to auth and check if they can handle it.
  if ([[FIRAuth auth] canHandleNotification:notification]) {
    completionHandler(UIBackgroundFetchResultNoData);
    return;
  }
  // This notification is not auth related, developer should handle it.
}

Para manejar la URL de redireccionamiento del esquema personalizado, implementa el método application:openURL:sourceApplication:annotation: para los dispositivos que usen iOS 8 o versiones anteriores, y el método application:openURL:options: para los dispositivos que usen iOS 9 u otras versiones posteriores. En ellos, pasa la URL al método canHandleURL de FIRAuth.

Swift

// For iOS 9+
func application(_ application: UIApplication, open url: URL,
    options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool {
  if Auth.auth().canHandle(url) {
    return true
  }
  // URL not auth related, developer should handle it.
}

// For iOS 8-
func application(_ application: UIApplication,
                 open url: URL,
                 sourceApplication: String?,
                 annotation: Any) -> Bool {
  if Auth.auth().canHandle(url) {
    Return true
  }
  // URL not auth related, developer should handle it.
}

Objective-C

// For iOS 9+
- (BOOL)application:(UIApplication *)app
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options {
  if ([[FIRAuth auth] canHandleURL:url]) {
    return YES;
  }
  // URL not auth related, developer should handle it.
}

// For iOS 8-
- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
  if ([[FIRAuth auth] canHandleURL:url]) {
    return YES;
  }
  // URL not auth related, developer should handle it.
}

Pasos siguientes

Cuando un usuario accede por primera vez, se crea una cuenta de usuario nueva y se la vincula con las credenciales (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 accedió el usuario. Esta cuenta nueva se almacena como parte del proyecto de Firebase y puede usarse para identificar a un usuario en todas las apps del proyecto, sin importar el método de acceso que se use.

  • En las apps, puedes obtener la información básica del perfil del usuario a partir del objeto FIRUser. Consulta Cómo administrar usuarios.

  • En las reglas de seguridad de Firebase Realtime Database y Cloud Storage, puedes obtener el ID único del usuario que accedió a partir de la variable auth y usarlo para controlar los datos a los que tiene acceso.

Para permitir que los usuarios accedan a tu app con varios proveedores de autenticación, puedes vincular las credenciales de proveedores de autenticación con una cuenta de usuario existente.

Para salir de la sesión de un usuario, llama a signOut:.

Swift

    let firebaseAuth = Auth.auth()
do {
  try firebaseAuth.signOut()
} catch let signOutError as NSError {
  print ("Error signing out: %@", signOutError)
}  

Objective-C

    NSError *signOutError;
BOOL status = [[FIRAuth auth] signOut:&signOutError];
if (!status) {
  NSLog(@"Error signing out: %@", signOutError);
  return;
}

Tal vez sea conveniente que agregues código de administración de errores para todos los errores de autenticación. Consulta Maneja errores.