Si actualizó a Firebase Authentication con Identity Platform, puede agregar autenticación multifactor por SMS a su aplicación iOS.
La autenticación multifactor aumenta la seguridad de su aplicación. Si bien los atacantes suelen comprometer 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 verifique los correos electrónicos de los usuarios. MFA requiere verificación por correo electrónico. Esto evita que actores maliciosos se registren en un servicio con un correo electrónico que no les pertenece y luego bloqueen al propietario real agregando un segundo factor.
Habilitar 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 por SMS .
También debes ingresar los números de teléfono con los que probarás tu 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 ha autorizado 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 es necesario pedirle al usuario que permita las notificaciones automáticas para utilizar 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, reCAPTCHA se resolverá solo automáticamente sin interacción del usuario.
Usar notificaciones silenciosas
Para habilitar las notificaciones de APN para usar con Firebase:
En Xcode, habilite las notificaciones push para su proyecto.
Cargue su clave de autenticación de APN usando 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 saber cómo obtenerla.
Abra la consola de Firebase .
Vaya a Configuración del proyecto .
Seleccione la pestaña Mensajería en la nube .
En 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 desarrolladores de Apple .
Haga clic en Cargar .
Si ya tiene un certificado APN, puede cargar el certificado en su lugar.
Usando la verificación reCAPTCHA
Para permitir que el SDK del cliente utilice 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 invertido en el campo Esquemas de URL . Puede encontrar este valor en el archivo de configuración
GoogleService-Info.plist
comoREVERSED_CLIENT_ID
.
Cuando esté completa, su configuración debería verse similar a la siguiente:
Opcionalmente, puede personalizar la forma en que su aplicación presenta SFSafariViewController
o UIWebView
al mostrar reCAPTCHA. Para hacer esto, cree una clase personalizada que se ajuste al protocolo FIRAuthUIDelegate
y pásela a 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 que se pueda omitir para inscribir un segundo factor durante el registro. Las aplicaciones que quieran fomentar, pero no exigir, la autenticación multifactor pueden preferir este enfoque.
Brinde la posibilidad de agregar un segundo factor desde la cuenta del usuario o la página de administración de perfil, en lugar de la pantalla de registro. Esto minimiza la fricción durante el proceso de registro y al mismo tiempo hace que la autenticación multifactor esté disponible para los usuarios sensibles a la seguridad.
Requerir agregar un segundo factor de manera incremental cuando el usuario desee acceder a funciones con mayores requisitos de seguridad.
Inscribir un segundo factor
Para inscribir un nuevo factor secundario para un usuario:
Vuelva a autenticar al usuario.
Solicite al usuario que ingrese 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) { // ... }];
Enviar 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 otra puntuación o espacio 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 tarifas estándar.
El método
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, en su lugar se emite un desafío reCAPTCHA.Una vez enviado el código SMS, solicite al usuario que verifique el código. Luego, use 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 múltiples segundos factores, ya que el número de teléfono está enmascarado 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 registrar 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! Registró exitosamente un segundo factor de autenticación para un usuario.
Iniciar sesión de usuarios con un segundo factor
Para iniciar sesión como usuario con verificación por SMS de dos factores:
Inicie sesión como usuario con su primer factor y luego detecte un error que indica que se requiere autenticación multifactor. Este error contiene un solucionador, sugerencias sobre los segundos factores inscritos y una sesión subyacente que demuestra que el usuario se autenticó exitosamente 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
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 if resolver.hints[selectedIndex].factorID == TotpMultiFactorID { // User selected a TOTP second factor. // ... } else { // Unsupported second factor. }
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 if (hint.factorID == FIRTOTPMultiFactorID) { // User selected a TOTP second factor. // ... } else { // Unsupported second factor. }
Enviar 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 enviado 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];
Resuelva el inicio de sesión. Luego podrá acceder al resultado del 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 de cómo iniciar sesión como usuario multifactor:
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! Ingresó exitosamente a un usuario mediante la autenticación multifactor.
Que sigue
- Administre usuarios multifactor mediante programación con Admin SDK.