Aprende a integrar Passkeys en iOS usando autenticación por claves criptográficas públicas y privadas, una alternativa moderna al Face ID que combina seguridad y experiencia de usuario fluida. Esta guía te muestra cómo conectar tu app con Authentication Services y manejar el flujo completo de login.
¿Qué son las Passkeys y por qué importan en iOS?
Las Passkeys son un sistema de autenticación que reemplaza contraseñas tradicionales por un par de claves criptográficas: una pública que vive en el servidor y una privada que se guarda en tu dispositivo. Apple las integra a través del framework Authentication Services, y muchas veces las combina con Face ID para sumar una capa extra de seguridad.
¿Qué diferencia hay entre Passkeys y Face ID? Face ID valida tu identidad biométrica localmente. Passkeys usan criptografía de clave pública/privada y suelen apoyarse en Face ID para confirmar al usuario antes de firmar el reto del servidor.
La idea central: tu teléfono guarda la clave privada, el servidor guarda la pública, y la autenticación ocurre cuando ambas firman un challenge sin enviar contraseñas por la red.
¿Cómo se configura el AuthDelegate para manejar la autenticación?
El delegado es la pieza que recibe los callbacks de éxito o error desde Authentication Services. Todo arranca creando una clase que herede de NSObject y conforme ASAuthorizationControllerDelegate [02:00].
Dentro de esa clase necesitas una variable privada completion del tipo Result<Void, Error> que se inicializa en el constructor del delegado. Esa variable es la que va a propagar el resultado hacia tu vista.
¿Qué funciones del delegado debes implementar?
Son dos funciones clave del protocolo:
authorizationController(controller:didCompleteWithAuthorization:): se dispara cuando la autenticación es exitosa.
authorizationController(controller:didCompleteWithError:): se dispara cuando algo falla.
En la función de éxito, valida que la credencial sea del tipo ASAuthorizationPlatformPublicKeyCredentialAssertion [03:30]. Si lo es, llamas a completion(.success(())). Si no, devuelves un NSError con dominio "Passkeys", un código y un userInfo que incluya NSLocalizedDescriptionKey con el mensaje, por ejemplo "Credenciales incorrectas" o "Autenticación exitosa".
En la función de error, imprimes el localizedDescription y llamas a completion(.failure(error)) para que la vista reaccione.
¿Cómo conectar la vista DemoPasskeysAuthView con el delegado?
La vista en SwiftUI necesita dos @State privados: uno para authenticationStatus que muestra el texto en pantalla, y otro authDelegate que mantiene una referencia fuerte al delegado para evitar que se libere de memoria [07:00].
El primer paso obligatorio es importar AuthenticationServices. Después, el botón ejecuta una función authenticateUser() que arma el flujo completo.
¿Qué pasos sigue la función authenticateUser?
El flujo se compone de cinco pasos secuenciales:
- Crear el proveedor con
ASAuthorizationPlatformPublicKeyCredentialProvider(relyingPartyIdentifier:) usando el Bundle Identifier de tu app.
- Generar la solicitud con
createCredentialAssertionRequest(challenge:), pasando un Data codificado en UTF-8 (por ejemplo "demo challenge").
- Configurar el controlador con
ASAuthorizationController(authorizationRequests: [request]).
- Instanciar el
AuthDelegate con un closure que use switch sobre el Result para actualizar authenticationStatus a "Autenticado correctamente" o "Error al autenticar".
- Asignar
authController.delegate = delegate y llamar a authController.performRequests() para iniciar el flujo.
¿Dónde encuentro el Relying Party Identifier? Es el Bundle Identifier de tu proyecto. Lo copias desde la pestaña Signing & Capabilities en la configuración del target en Xcode.
Un detalle importante: la referencia fuerte al delegado se logra asignándolo a la propiedad @State authDelegate. Sin eso, ARC liberaría el objeto antes de recibir el callback.
¿Por qué Passkeys no funciona en el simulador de iOS?
El simulador no tiene acceso al Secure Enclave ni a Face ID real, así que la autenticación por Passkeys siempre devuelve error en ese entorno. Cuando pruebas en un dispositivo físico, al pulsar Iniciar sesión con Passkey se dispara el prompt nativo del sistema, se combina con Face ID, y al confirmar tu identidad la variable cambia a "Autenticado exitosamente" [14:30].
¿Por qué se combina Passkeys con Face ID? Face ID actúa como verificación local del usuario antes de que la clave privada firme el challenge. Sumar ambos métodos eleva el nivel de seguridad sin agregar fricción.
Esta combinación es la base del estándar FIDO2/WebAuthn que Apple adoptó: criptografía asimétrica respaldada por biometría del dispositivo.
¿Ya probaste integrar Passkeys en tu app? Cuéntame en los comentarios qué retos encontraste con el Relying Party o el manejo del delegado.