Si actualizó a Firebase Authentication con Identity Platform, puede agregar la autenticación multifactor por SMS a su aplicación de iOS.
La autenticación multifactor aumenta la seguridad de su aplicación. Si bien los atacantes a menudo comprometen contraseñas y cuentas sociales, interceptar un mensaje de texto es más difícil.
Antes de que empieces
Habilite al menos un proveedor que admita la autenticación multifactor. Todos los proveedores admiten MFA, excepto la autenticación telefónica, la autenticación anónima y Apple Game Center.
Asegúrese de que su aplicación esté verificando los correos electrónicos de los usuarios. MFA requiere verificación de correo electrónico. Esto evita que los actores malintencionados se registren en un servicio con un correo electrónico que no les pertenece y luego bloqueen al propietario real al agregar un segundo factor.
Habilitación de la autenticación multifactor
Abra la página Autenticación > Método de inicio de sesión de Firebase console.
En la sección Avanzado , habilite la Autenticación multifactor SMS .
También debe ingresar los números de teléfono con los que probará su aplicación. Si bien es opcional, se recomienda encarecidamente registrar números de teléfono de prueba para evitar limitaciones durante el desarrollo.
Si aún no autorizó el dominio de su aplicación, agréguelo a la lista de permitidos en la página Autenticación > Configuración de Firebase console.
Verificando tu aplicación
Firebase necesita verificar que las solicitudes de SMS provengan de su aplicación. Puede hacer esto de dos maneras:
Notificaciones silenciosas de APN : cuando inicia sesión con un usuario por primera vez, Firebase puede enviar una notificación push silenciosa al dispositivo del usuario. La autenticación puede continuar si la aplicación recibe la notificación. Tenga en cuenta que, a partir de iOS 8.0, no necesita pedirle al usuario que permita las notificaciones automáticas para usar este método.
Verificación de reCAPTCHA : si no puede enviar una notificación silenciosa (por ejemplo, porque el usuario ha deshabilitado la actualización en segundo plano o está probando su aplicación en el simulador de iOS), puede usar reCAPTCHA. En muchos casos, el reCAPTCHA se resolverá automáticamente sin interacción del usuario.
Uso de notificaciones silenciosas
Para habilitar las notificaciones de APN para su uso con Firebase:
En Xcode, habilite las notificaciones push para su proyecto.
Cargue su clave de autenticación de APN con Firebase Console (sus cambios se transferirán automáticamente a Google Cloud Firebase). Si aún no tiene su clave de autenticación de APN, consulte Configuración de APN con FCM para obtener información sobre cómo obtenerla.
Abre la consola de Firebase .
Vaya a Configuración del proyecto .
Seleccione la pestaña Mensajería en la nube .
En la clave de autenticación de APN, en la sección de configuración de la aplicación iOS , haga clic en Cargar .
Seleccione su clave.
Agregue el ID de clave para la clave. Puede encontrar el ID de clave en Certificados, identificadores y perfiles en el Centro de miembros para desarrolladores de Apple .
Haga clic en Cargar .
Si ya tiene un certificado APNs, puede cargar el certificado en su lugar.
Usando la verificación reCAPTCHA
Para permitir que el SDK del cliente use reCAPTCHA:
Abra la configuración de su proyecto en Xcode.
Haga doble clic en el nombre del proyecto en la vista de árbol de la izquierda.
Seleccione su aplicación en la sección Objetivos .
Seleccione la pestaña Información .
Expanda la sección Tipos de URL .
Haga clic en el botón + .
Ingrese su ID de cliente invertida en el campo Esquemas de URL . Puede encontrar este valor en el archivo de configuración
GoogleService-Info.plist
comoREVERSED_CLIENT_ID
.
Cuando se complete, su configuración debería ser similar a la siguiente:
Opcionalmente, puede personalizar la forma en que su aplicación presenta SFSafariViewController
o UIWebView
cuando muestra reCAPTCHA. Para hacer esto, cree una clase personalizada que se ajuste al protocolo FIRAuthUIDelegate
y verifyPhoneNumber:UIDelegate:completion:
.
Elegir un patrón de inscripción
Puede elegir si su aplicación requiere autenticación multifactor y cómo y cuándo inscribir a sus usuarios. Algunos patrones comunes incluyen:
Inscriba el segundo factor del usuario como parte del registro. Utilice este método si su aplicación requiere autenticación multifactor para todos los usuarios. Tenga en cuenta que una cuenta debe tener una dirección de correo electrónico verificada para inscribir un segundo factor, por lo que su flujo de registro deberá adaptarse a esto.
Ofrezca una opción saltable para inscribir un segundo factor durante el registro. Las aplicaciones que desean fomentar, pero no exigir, la autenticación multifactor pueden preferir este enfoque.
Proporcione la capacidad de agregar un segundo factor desde la cuenta del usuario o la página de administración del perfil, en lugar de la pantalla de registro. Esto minimiza la fricción durante el proceso de registro, al mismo tiempo que hace que la autenticación de múltiples factores esté disponible para usuarios sensibles a la seguridad.
Requerir agregar un segundo factor de forma incremental cuando el usuario desee acceder a funciones con mayores requisitos de seguridad.
Inscripción de un segundo factor
Para inscribir un nuevo factor secundario para un usuario:
Vuelva a autenticar al usuario.
Pida al usuario que introduzca su número de teléfono.
Obtenga una sesión multifactor para el usuario:
Rápido
authResult.user.multiFactor.getSessionWithCompletion() { (session, error) in // ... }
C objetivo
[authResult.user.multiFactor getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session, NSError * _Nullable error) { // ... }];
Envía un mensaje de verificación al teléfono del usuario. Asegúrese de que el número de teléfono esté formateado con un
+
inicial y sin otros signos de puntuación o espacios en blanco (por ejemplo:+15105551234
)Rápido
// Send SMS verification code. PhoneAuthProvider.provider().verifyPhoneNumber( phoneNumber, uiDelegate: nil, multiFactorSession: session) { (verificationId, error) in // verificationId will be needed for enrollment completion. }
C objetivo
// Send SMS verification code. [FIRPhoneAuthProvider.provider verifyPhoneNumber:phoneNumber UIDelegate:nil multiFactorSession:session completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { // verificationId will be needed for enrollment completion. }];
Si bien no es obligatorio, es una buena práctica informar a los usuarios de antemano que recibirán un mensaje SMS y que se aplican las tarifas estándar.
El
verifyPhoneNumber()
inicia el proceso de verificación de la aplicación en segundo plano mediante una notificación push silenciosa. Si la notificación push silenciosa no está disponible, se emite un desafío reCAPTCHA en su lugar.Una vez que se envía el código SMS, solicite al usuario que verifique el código. Luego, usa su respuesta para crear una
PhoneAuthCredential
:Rápido
// Ask user for the verification code. Then: let credential = PhoneAuthProvider.provider().credential( withVerificationID: verificationId, verificationCode: verificationCode)
C objetivo
// Ask user for the SMS verification code. Then: FIRPhoneAuthCredential *credential = [FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID verificationCode:kPhoneSecondFactorVerificationCode];
Inicializar un objeto de aserción:
Rápido
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
C objetivo
FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
Completa la inscripción. Opcionalmente, puede especificar un nombre para mostrar para el segundo factor. Esto es útil para usuarios con factores de varios segundos, ya que el número de teléfono se enmascara durante el flujo de autenticación (por ejemplo, +1******1234).
Rápido
// Complete enrollment. This will update the underlying tokens // and trigger ID token change listener. user.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in // ... }
C objetivo
// Complete enrollment. This will update the underlying tokens // and trigger ID token change listener. [authResult.user.multiFactor enrollWithAssertion:assertion displayName:nil completion:^(NSError * _Nullable error) { // ... }];
El siguiente código muestra un ejemplo completo de cómo inscribir un segundo factor:
Rápido
let user = Auth.auth().currentUser
user?.multiFactor.getSessionWithCompletion({ (session, error) in
// Send SMS verification code.
PhoneAuthProvider.provider().verifyPhoneNumber(
phoneNumber,
uiDelegate: nil,
multiFactorSession: session
) { (verificationId, error) in
// verificationId will be needed for enrollment completion.
// Ask user for the verification code.
let credential = PhoneAuthProvider.provider().credential(
withVerificationID: verificationId!,
verificationCode: phoneSecondFactorVerificationCode)
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
// Complete enrollment. This will update the underlying tokens
// and trigger ID token change listener.
user?.multiFactor.enroll(with: assertion, displayName: displayName) { (error) in
// ...
}
}
})
C objetivo
FIRUser *user = FIRAuth.auth.currentUser;
[user.multiFactor getSessionWithCompletion:^(FIRMultiFactorSession * _Nullable session,
NSError * _Nullable error) {
// Send SMS verification code.
[FIRPhoneAuthProvider.provider
verifyPhoneNumber:phoneNumber
UIDelegate:nil
multiFactorSession:session
completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) {
// verificationId will be needed for enrollment completion.
// Ask user for the verification code.
// ...
// Then:
FIRPhoneAuthCredential *credential =
[FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID
verificationCode:kPhoneSecondFactorVerificationCode];
FIRMultiFactorAssertion *assertion =
[FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
// Complete enrollment. This will update the underlying tokens
// and trigger ID token change listener.
[user.multiFactor enrollWithAssertion:assertion
displayName:displayName
completion:^(NSError * _Nullable error) {
// ...
}];
}];
}];
¡Felicidades! Ha registrado correctamente un segundo factor de autenticación para un usuario.
Inicio de sesión de usuarios con un segundo factor
Para iniciar sesión en un usuario con verificación de SMS de dos factores:
Inicie sesión con el usuario con su primer factor, luego detecte un error que indica que se requiere autenticación de múltiples factores. Este error contiene una resolución, sugerencias sobre los segundos factores inscritos y una sesión subyacente que prueba que el usuario se autenticó correctamente con el primer factor.
Por ejemplo, si el primer factor del usuario fue un correo electrónico y una contraseña:
Rápido
Auth.auth().signIn( withEmail: email, password: password ) { (result, error) in let authError = error as NSError if authError?.code == AuthErrorCode.secondFactorRequired.rawValue { // The user is a multi-factor user. Second factor challenge is required. let resolver = authError!.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver // ... } else { // Handle other errors such as wrong password. } }
C objetivo
[FIRAuth.auth signInWithEmail:email password:password completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error == nil || error.code != FIRAuthErrorCodeSecondFactorRequired) { // User is not enrolled with a second factor and is successfully signed in. // ... } else { // The user is a multi-factor user. Second factor challenge is required. } }];
Si el primer factor del usuario es un proveedor federado, como OAuth, detecte el error después de llamar a
getCredentialWith()
.Si el usuario tiene varios factores secundarios inscritos, pregúntele cuál usar. Puede obtener el número de teléfono enmascarado con
resolver.hints[selectedIndex].phoneNumber
y el nombre para mostrar conresolver.hints[selectedIndex].displayName
.Rápido
// Ask user which second factor to use. Then: if resolver.hints[selectedIndex].factorID == PhoneMultiFactorID { // User selected a phone second factor. // ... } else { // Unsupported second factor. // Note that only phone second factors are currently supported. }
C objetivo
FIRMultiFactorResolver *resolver = (FIRMultiFactorResolver *) error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey]; // Ask user which second factor to use. Then: FIRPhoneMultiFactorInfo *hint = (FIRPhoneMultiFactorInfo *) resolver.hints[selectedIndex]; if (hint.factorID == FIRPhoneMultiFactorID) { // User selected a phone second factor. // ... } else { // Unsupported second factor. // Note that only phone second factors are currently supported. }
Envía un mensaje de verificación al teléfono del usuario:
Rápido
// Send SMS verification code. let hint = resolver.hints[selectedIndex] as! PhoneMultiFactorInfo PhoneAuthProvider.provider().verifyPhoneNumber( with: hint, uiDelegate: nil, multiFactorSession: resolver.session ) { (verificationId, error) in // verificationId will be needed for sign-in completion. }
C objetivo
// Send SMS verification code [FIRPhoneAuthProvider.provider verifyPhoneNumberWithMultiFactorInfo:hint UIDelegate:nil multiFactorSession:resolver.session completion:^(NSString * _Nullable verificationID, NSError * _Nullable error) { if (error != nil) { // Failed to verify phone number. } }];
Una vez que se envía el código SMS, pídale al usuario que verifique el código y utilícelo para crear una
PhoneAuthCredential
:Rápido
// Ask user for the verification code. Then: let credential = PhoneAuthProvider.provider().credential( withVerificationID: verificationId!, verificationCode: verificationCodeFromUser)
C objetivo
// Ask user for the SMS verification code. Then: FIRPhoneAuthCredential *credential = [FIRPhoneAuthProvider.provider credentialWithVerificationID:verificationID verificationCode:verificationCodeFromUser];
Inicialice un objeto de aserción con la credencial:
Rápido
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
C objetivo
FIRMultiFactorAssertion *assertion = [FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
Resolver el inicio de sesión. A continuación, puede acceder al resultado de inicio de sesión original, que incluye los datos estándar específicos del proveedor y las credenciales de autenticación:
Rápido
// Complete sign-in. This will also trigger the Auth state listeners. resolver.resolveSignIn(with: assertion) { (authResult, error) in // authResult 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, // authResult.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. }
C objetivo
// Complete sign-in. [resolver resolveSignInWithAssertion:assertion completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (error != nil) { // User successfully signed in with the second factor phone number. } }];
El siguiente código muestra un ejemplo completo del inicio de sesión de un usuario de múltiples factores:
Rápido
Auth.auth().signIn(
withEmail: email,
password: password
) { (result, error) in
let authError = error as NSError?
if authError?.code == AuthErrorCode.secondFactorRequired.rawValue {
let resolver =
authError!.userInfo[AuthErrorUserInfoMultiFactorResolverKey] as! MultiFactorResolver
// Ask user which second factor to use.
// ...
// Then:
let hint = resolver.hints[selectedIndex] as! PhoneMultiFactorInfo
// Send SMS verification code
PhoneAuthProvider.provider().verifyPhoneNumber(
with: hint,
uiDelegate: nil,
multiFactorSession: resolver.session
) { (verificationId, error) in
if error != nil {
// Failed to verify phone number.
}
// Ask user for the SMS verification code.
// ...
// Then:
let credential = PhoneAuthProvider.provider().credential(
withVerificationID: verificationId!,
verificationCode: verificationCodeFromUser)
let assertion = PhoneMultiFactorGenerator.assertion(with: credential)
// Complete sign-in.
resolver.resolveSignIn(with: assertion) { (authResult, error) in
if error != nil {
// User successfully signed in with the second factor phone number.
}
}
}
}
}
C objetivo
[FIRAuth.auth signInWithEmail:email
password:password
completion:^(FIRAuthDataResult * _Nullable authResult,
NSError * _Nullable error) {
if (error == nil || error.code != FIRAuthErrorCodeSecondFactorRequired) {
// User is not enrolled with a second factor and is successfully signed in.
// ...
} else {
FIRMultiFactorResolver *resolver =
(FIRMultiFactorResolver *) error.userInfo[FIRAuthErrorUserInfoMultiFactorResolverKey];
// Ask user which second factor to use.
// ...
// Then:
FIRPhoneMultiFactorInfo *hint = (FIRPhoneMultiFactorInfo *) resolver.hints[selectedIndex];
// Send SMS verification code
[FIRPhoneAuthProvider.provider
verifyPhoneNumberWithMultiFactorInfo:hint
UIDelegate:nil
multiFactorSession:resolver.session
completion:^(NSString * _Nullable verificationID,
NSError * _Nullable error) {
if (error != nil) {
// Failed to verify phone number.
}
// Ask user for the SMS verification code.
// ...
// Then:
FIRPhoneAuthCredential *credential =
[FIRPhoneAuthProvider.provider
credentialWithVerificationID:verificationID
verificationCode:kPhoneSecondFactorVerificationCode];
FIRMultiFactorAssertion *assertion =
[FIRPhoneMultiFactorGenerator assertionWithCredential:credential];
// Complete sign-in.
[resolver resolveSignInWithAssertion:assertion
completion:^(FIRAuthDataResult * _Nullable authResult,
NSError * _Nullable error) {
if (error != nil) {
// User successfully signed in with the second factor phone number.
}
}];
}];
}
}];
¡Felicidades! Has iniciado sesión con éxito en un usuario mediante la autenticación multifactor.
Que sigue
- Administre usuarios multifactor mediante programación con Admin SDK.