Las contraseñas han sido, por décadas, el método de autenticación estándar, demostrando su eficacia. Sin embargo, este modelo, que depende de que una persona memorice y mantenga en secreto una clave, presenta limitaciones significativas. Tanto para los usuarios como para los proveedores de servicios, las contraseñas son una fuente constante de problemas, desde la dificultad para recordarlas hasta el alto riesgo de ataques de phishing y la reutilización en múltiples sitios.
Para los desarrolladores, la gestión de contraseñas implica tareas complejas como el hashing, la adición de salts, la limitación de intentos de inicio de sesión y la creación de flujos de recuperación que rara vez son agradables. Afortunadamente, las passkeys o claves de acceso, surgen como una solución robusta a muchos de estos inconvenientes. En lugar de una contraseña, los usuarios pueden confirmar su identidad con un autenticador diferente, como huellas dactilares, reconocimiento facial o un PIN, utilizando una clave criptográfica almacenada en su dispositivo que nunca se comparte.
Los Desafíos de la Autenticación Basada en Contraseñas
Antes de implementar nuevas soluciones, es crucial entender los problemas que las contraseñas tradicionales presentan:
Ataques de Phishing
Una contraseña funciona en cualquier lugar donde se ingrese. Si un atacante crea una página idéntica a la de un banco, la contraseña funcionará igual de bien en esa página falsa. El único impedimento para el compromiso del usuario es su capacidad para notar una URL ligeramente diferente, lo cual es mucho pedir. Las páginas de phishing suelen ser casi perfectas y vienen en forma de correos electrónicos o mensajes de texto urgentes diseñados para inducir una acción inmediata. Incluso usuarios muy cuidadosos y técnicos pueden ser engañados. Las contraseñas de un solo uso, enviadas por SMS o desde una aplicación de autenticación, son útiles, pero aún así las personas pueden ser engañadas para que las escriban en una página falsa.
Reutilización de Contraseñas
La mayoría de las personas tienen docenas, si no cientos, de cuentas en línea. Es imposible recordar una contraseña única y fuerte para cada una, lo que lleva a la reutilización de las mismas pocas contraseñas. Los atacantes lo saben y, si un sitio es comprometido, tomarán los pares de correo electrónico y contraseña filtrados para probarlos automáticamente en otros sitios, un ataque conocido como ‘relleno de credenciales’. Una brecha en un foro olvidado puede resultar en el acceso a su correo electrónico o cuenta bancaria.
Violaciones de Datos
Todo sitio que utiliza contraseñas debe almacenar algo que pueda usarse para verificarlas. La situación ideal es que el sitio almacene hashes salados en lugar de las contraseñas en sí. Sin embargo, no todos los sitios lo hacen bien, y los hashes de contraseñas débiles aún pueden ser descifrados sin conexión una vez que un atacante tiene una copia de la base de datos. Esta carga recae en los desarrolladores, quienes deben elegir el algoritmo de hashing correcto, ajustarlo, proteger la base de datos y aún así tratar una fuga como un desastre para sus usuarios.
Falta de Privacidad
Con las contraseñas, los usuarios comparten un secreto con cada sitio en el que se registran. Deben confiar en que ese sitio lo protegerá y no tienen control sobre lo que sucede una vez que se produce una brecha. A medida que las personas reutilizan las mismas combinaciones de correo electrónico y contraseña, es posible que las credenciales filtradas se asocien entre diferentes brechas. Esto, a su vez, facilita la vinculación de cuentas entre servicios y la construcción de un perfil del comportamiento en línea de una persona.
Fatiga de Credenciales
A esto se suma la frustración diaria. Los usuarios constantemente deben lidiar con políticas de contraseñas (al menos un símbolo, no más de 16 caracteres, etc.), restablecimientos forzados cada pocos meses, preguntas de seguridad, códigos de verificación, y la lista continúa. Cada nueva cuenta que se crea solo aumenta esta carga. Esta fatiga lleva a comportamientos que hacen que las contraseñas sean inseguras: contraseñas cortas, pequeñas variaciones de la misma contraseña y contraseñas escritas en notas adhesivas. También genera costos para las empresas, ya que los usuarios abandonan el proceso de registro, se bloquean y luego contactan al soporte para restablecer contraseñas olvidadas.
Cómo las Passkeys Transforman la Seguridad
Las passkeys eliminan por completo el secreto compartido. Son intuitivas, automáticamente únicas, resistentes a las brechas y resistentes al phishing. Así es como abordan los problemas mencionados:
- Ataques de Phishing: El navegador y el sistema operativo solo usan una passkey en el sitio que la creó. Un dominio falso no funciona, por muy convincente que parezca.
- Reutilización de Contraseñas: Cada passkey es un nuevo par de claves creado para un solo sitio, por lo que no hay nada que reutilizar.
- Violaciones de Datos: El servidor solo almacena una clave pública. Una base de datos filtrada no proporciona a los atacantes nada con lo que puedan iniciar sesión.
- Falta de Privacidad: No se comparte nada secreto con el sitio, y las claves son diferentes para cada sitio. Los datos de huellas dactilares y faciales no abandonan el dispositivo.
- Fatiga de Credenciales: No hay nada que crear o recordar. Los usuarios confirman con la misma huella dactilar, rostro o bloqueo de pantalla que usan varias veces al día.
El cambio fundamental radica en dónde reside la confianza. Con las contraseñas, la seguridad depende de la capacidad de los usuarios para detectar sitios fraudulentos y elegir credenciales fuertes. Con las passkeys, son el navegador y el sistema operativo quienes aplican las reglas, mientras que el usuario simplemente confirma su identidad.
Implementación de Passkeys: Backend con NestJS y Frontend con Next.js
Para construir una aplicación sin contraseñas tradicionales, se puede utilizar una API de NestJS en el backend para almacenar usuarios y sus passkeys en PostgreSQL, mientras que el frontend sería una aplicación Next.js donde los usuarios se registran e inician sesión solo con una dirección de correo electrónico y una passkey.
Se recomienda el uso de SimpleWebAuthn, una biblioteca TypeScript bien mantenida que simplifica las tareas relacionadas con la criptografía y el análisis de datos de WebAuthn. Al finalizar la implementación, se tendrá lo necesario para registrar y autenticar passkeys en un sitio web y validarlas de forma segura en el servidor.
¿Qué son las Passkeys?
Una passkey es una credencial basada en criptografía de clave pública. Al crearla, el dispositivo genera un par de claves: la clave privada permanece en el dispositivo, protegida por la huella dactilar, el rostro o el bloqueo de pantalla, mientras que la clave pública se envía al sitio web, que la almacena junto a la cuenta del usuario.
Las passkeys se basan en la API de autenticación web (WebAuthn), un estándar del W3C compatible con todos los navegadores principales. El término ‘passkey‘ es el nombre amigable que la industria adoptó para las credenciales de WebAuthn que pueden sincronizarse entre dispositivos. Es importante destacar que la aplicación no puede elegir entre huella dactilar, reconocimiento facial o un código PIN; es el sistema operativo quien decide, basándose en las capacidades del dispositivo y la configuración del usuario.
Los usuarios suelen ver los siguientes métodos de verificación:
- Mac: Touch ID o la contraseña de Mac.
- iPhone o iPad: Face ID, Touch ID o el código de acceso.
- Android: Huella dactilar, desbloqueo facial o PIN, patrón o contraseña.
- Windows: Windows Hello facial, huella dactilar o PIN.
- Cualquier otra computadora: Escanear un código QR y confirmar en el teléfono.
Lo que el servidor puede hacer es exigir que se haya realizado alguna verificación local.
Estructura del Proyecto
La construcción de un sistema de autenticación con passkeys implica varios pasos clave tanto en el backend como en el frontend.
- Configuración del Backend con NestJS: Esto incluye la creación de la base de datos, la adición de variables de entorno, la conexión a PostgreSQL, la definición de las entidades de la base de datos y la exposición de los endpoints de autenticación.
- Registro de una Passkey en el Servidor: Se generan opciones de registro y se verifica la respuesta de registro.
- Inicio de Sesión con una Passkey en el Servidor: Se generan opciones de autenticación y se verifica la respuesta de autenticación.
- Protección de Rutas con JWT: Implementar seguridad en las rutas del backend.
- Configuración del Frontend con Next.js: Construir las páginas de registro e inicio de sesión, y mostrar mensajes de error útiles.
Errores de Seguridad a Evitar
Al implementar passkeys, es crucial evitar ciertos errores de seguridad comunes:
- Codificar el ID de la credencial dos veces: Asegurarse de que el ID de la credencial no se codifique de forma redundante.
- Borrar el desafío con un valor indefinido: El desafío criptográfico debe manejarse correctamente y no ser borrado prematuramente.
- Buscar una credencial sin verificar su propietario: Siempre se debe verificar que la credencial pertenece al usuario que intenta autenticarse.
- Permitir que el registro añada passkeys a cuentas existentes: El proceso de registro debe ser claro y no permitir la adición no intencionada de passkeys a cuentas ya creadas.
- Solicitar verificación sin requerirla: Si se solicita una verificación, esta debe ser un paso obligatorio en el proceso.
Conclusión
Las passkeys representan un avance significativo en la autenticación web, ofreciendo una alternativa más segura y fácil de usar que las contraseñas tradicionales. Al adoptar estándares como WebAuthn y herramientas como NestJS y Next.js, los desarrolladores pueden construir sistemas de autenticación robustos que protegen a los usuarios de amenazas comunes como el phishing y la reutilización de contraseñas, mejorando la experiencia general de seguridad en línea.
📝 Basado en información de freecodecamp.org
