Implementar Face ID es una excelente manera de proteger secciones sensibles de tu aplicación y ofrecer una experiencia de usuario moderna y segura. En este artículo, te enseñaremos cómo integrar Face ID en tu proyecto SwiftUI con un ejemplo básico, ideal para comenzar a experimentar con la autenticación biométrica.
Configurar el Proyecto para Usar Face ID
Para poder utilizar Face ID, es necesario configurar un permiso en el archivo Info.plist de tu proyecto. Este permiso es requerido por Apple para que la aplicación pueda acceder a datos sensibles.
Dentro del archivo Info.plist, agrega la siguiente clave y valor:
<key>NSFaceIDUsageDescription</key>
<string>Esta aplicación utiliza Face ID para desbloquear secciones seguras de la aplicación.</string>
Asegúrate de que las líneas estén dentro del <dict> para mantener una estructura xml correcta. Tu archivo Info.plist debería quedar algo similar a esto:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSFaceIDUsageDescription</key>
<string>Esta aplicación utiliza Face ID para desbloquear secciones seguras de la aplicación.</string>
</dict>
</plist>
De esta forma aseguramos que la aplicación solicite al usuario permiso para usar Face ID y explique el propósito de su uso.
Implementar Face ID en SwiftUI
Con el permiso configurado, es hora de implementar Face ID en tu aplicación. Vamos a proteger una sección específica de la app que solo se desbloqueará con Face ID.
En el archivo ContentView.swift, comienza importando LocalAuthentication:
import SwiftUI
import LocalAuthentication
¿Qué es LocalAuthentication?
LocalAuthentication es un framework de Apple que proporciona una forma sencilla de autenticar a los usuarios mediante métodos biométricos, como Face ID y Touch ID, o mediante la autenticación tradicional basada en contraseña. Este framework permite a las aplicaciones mejorar la seguridad al requerir que los usuarios se identifiquen de manera segura antes de acceder a ciertas funcionalidades o datos sensibles.
Crear la Interfaz de Usuario
Primero, vamos a crear la interfaz de usuario (UI) que permita al usuario interactuar con la autenticación mediante Face ID. La idea es tener un botón que, al presionarlo, active el proceso de autenticación.
struct ContentView: View {
@State private var isUnlocked = false
var body: some View {
VStack {
if isUnlocked {
Text("¡Bienvenido! Has desbloqueado la sección segura.")
.padding()
} else {
Button("Desbloquear con Face ID") {
authenticate() // Llamada a la función de autenticación que vamos a trabajar más adelante
}
.padding()
.background(Color.blue)
.foregroundColor(.white)
.clipShape(Capsule())
}
}
}
}
La propiedad isUnlocked controla si la sección protegida de la app está desbloqueada o no. Usamos @State para que el valor pueda cambiar dinámicamente y actualizar la interfaz cuando cambie.
Implementar la Función de Autenticación
Ahora que tenemos la interfaz, es momento de crear la función que manejará la autenticación biométrica mediante Face ID.
func authenticate() {
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "Necesitamos autenticarte para acceder a la sección segura."
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, authenticationError in
DispatchQueue.main.async {
if success {
self.isUnlocked = true
} else {
// Manejar la autenticación fallida
}
}
}
} else {
// Manejar el caso donde Face ID no esté disponible
}
}
canEvaluatePolicy verifica si el dispositivo puede usar Face ID (o Touch ID) para autenticación. Si es posible, procede a la autenticación; de lo contrario, maneja el caso donde Face ID no esté disponible.
Si canEvaluatePolicy retorna true, evaluatePolicy solicita al usuario que se autentique utilizando Face ID. Recibe dos parámetros importantes:
- localizedReason: Un mensaje que explica al usuario por qué se le pide que se autentique. Es crucial que este mensaje sea claro y relevante para la acción que está realizando.
- success: Un valor booleano que indica si la autenticación fue exitosa.
- authenticationError: Un error opcional que detalla por qué la autenticación falló.
Finalmente, debido a que evaluatePolicy se ejecuta en un hilo de fondo, usamos DispatchQueue.main.async para asegurarnos de que cualquier actualización de la interfaz de usuario (UI) ocurra en el hilo principal.
Resultado Test App