Serie de Autenticación (Parte 1): Prácticas de Ingeniería de Aplicaciones
March 8, 2024
Introducción
La autenticación de identidad juega un papel crucial en la protección del acceso a los datos y la privacidad del usuario en las aplicaciones de internet, especialmente en las aplicaciones internas de las empresas. En esta serie de artículos, exploraremos la autenticación de identidad desde diferentes perspectivas, con un enfoque específico en las prácticas de autenticación de identidad en la ingeniería de aplicaciones en este artículo.
En diversas aplicaciones, la autenticación de identidad comúnmente emplea las siguientes dos técnicas:
-
Cookie & Session: Este mecanismo de autenticación tradicional es ampliamente utilizado en aplicaciones web, principalmente dentro de los navegadores. Verifica la identidad del usuario y mantiene el estado de la sesión utilizando cookies y sesiones.
-
Bearer Token: Este es un mecanismo de autenticación más moderno que elimina la dependencia de las cookies del navegador y, en su lugar, utiliza el protocolo HTTP para la autenticación. Es particularmente adecuado para escenarios de API y puede ser utilizado en aplicaciones móviles.
Independientemente del método elegido, los desarrolladores necesitan seleccionar el enfoque de autenticación adecuado para sus productos para garantizar la seguridad de los datos, la privacidad del usuario y una experiencia de usuario fluida.
Aplicaciones Web Tradicionales
En el pasado, utilizábamos Java JSP para construir aplicaciones web directamente, identificando a los usuarios mediante JSESSIONID, un ID de sesión almacenado en una cookie en el navegador del cliente y enviado con cada solicitud.
Sin embargo, este enfoque tenía ciertos problemas. Dado que las cookies son gestionadas y almacenadas en el dispositivo del cliente por el navegador, los atacantes maliciosos podían robar el ID de sesión almacenado y suplantar al usuario, lo que representaba un riesgo de seguridad. Además, los desarrolladores a veces tenían dificultades para establecer períodos de expiración y requisitos de seguridad razonables para las cookies y las sesiones.
Al desarrollar estas aplicaciones, los desarrolladores a menudo tenían que implementar la autenticación por separado para cada sistema, lo cual era independiente y utilizaba diferentes sistemas de identidad. Esto requería trabajo repetitivo. En tales casos, el Inicio de Sesión Único (SSO) podía abordar estos desafíos utilizando un sistema de autenticación unificado, requiriendo un trabajo mínimo de integración en cada aplicación web individual para lograr la funcionalidad de autenticación.
En los últimos años, tanto las tecnologías de front-end como de back-end han avanzado rápidamente. Los desarrolladores han comenzado a migrar a pilas tecnológicas más modernas, dejando las aplicaciones impulsadas por tecnologías obsoletas como plataformas heredadas. Sin embargo, hay casos en los que surgen nuevos requisitos de seguridad de identidad, pero modificar el código antiguo no es factible. En tales casos, un enfoque alternativo es utilizar middleware que funcione como un proxy inverso para realizar la autenticación. Antes de que el cliente llegue a la aplicación, el middleware redirige al usuario a una interfaz de autenticación externa, donde el usuario inicia sesión. El middleware luego obtiene la información de identidad del usuario y la adjunta a la solicitud antes de pasarla a la aplicación antigua. Esto permite a los desarrolladores agregar nuevos mecanismos de autenticación a aplicaciones antiguas sin modificar el código existente.
Evolución de las Aplicaciones Web: Separación del Front-End del Back-End
Con la aparición de nuevas tecnologías de front-end como Vue y React, las interacciones web han sido revolucionadas. En el pasado, los usuarios tenían que llenar y enviar formularios en las páginas web, interactuando con el back-end utilizando formularios HTML y botones, lo que no proporcionaba una experiencia de usuario fluida. Ahora, las interacciones en la página son en tiempo real, y los desarrolladores utilizan scripts de JavaScript para interactuar con las API del back-end, ofreciendo una experiencia más consistente y continua. Las interacciones del usuario han pasado de ser solicitudes HTTP directas a invocar diversas API.
Existen algunas diferencias en los mecanismos de autenticación de identidad entre las aplicaciones orientadas a páginas web y las aplicaciones orientadas a API. Aunque las cookies antiguas aún pueden utilizarse, no son adecuadas para las tecnologías modernas de front-end. Las nuevas tecnologías empoderan a los desarrolladores con código más expresivo, permitiéndoles realizar más operaciones, incluyendo escenarios donde podríamos necesitar cambiar cuentas de usuario en el front-end. Sin embargo, implementar esto directamente en el front-end a través de cookies es desafiante (por razones de seguridad, las cookies relacionadas con la identidad del usuario a menudo se configuran como httpOnly, evitando que los scripts de JavaScript las lean y manipulen).
Normalmente, las aplicaciones modernas de front-end gestionan las sesiones de usuario por sí mismas. Una vez que un usuario inicia sesión correctamente, el front-end gestiona el token generado por el back-end y lo agrega al encabezado de la solicitud al realizar llamadas API para que el back-end identifique la identidad del usuario. Las API utilizan tokens para identificar la información del usuario. Hay varios medios técnicos disponibles, como implementar manualmente mecanismos de token utilizando JSON Web Tokens (JWT). El payload del JWT almacena información de identificación como el ID del usuario, que luego se firma para permitir que el back-end verifique el token y recupere la información de identidad del usuario.
Sin embargo, JWT también tiene algunos inconvenientes, como:
-
El tiempo de expiración del JWT es fijo y no se puede modificar una vez que se completa la firma. Dado que normalmente no se almacena en el back-end y solo se somete a verificación de firma, no es posible revocar el token, lo que representa un riesgo de robo de token.
-
Los datos del payload se almacenan en texto plano y pueden ser analizados por el cliente, lo que los hace inadecuados para almacenar información confidencial.
Afortunadamente, ahora existen nuevas especificaciones de JWT para abordar estas deficiencias. El payload del JWT puede incluir un campo llamado "jti" para almacenar un identificador único del JWT, que puede almacenarse en la caché del back-end para controlar el ciclo de vida del JWT. Además, la especificación JSON Web Encryption (JWE) define una extensión de JWT cifrado que combina las ventajas del cifrado asimétrico y simétrico, asegurando que el payload se transmita en forma de texto cifrado para evitar fugas.
Además, existen otras tecnologías basadas en JWT que ofrecen soluciones más maduras, como OpenID Connect. Es importante destacar que OpenID Connect no depende de JWT, pero pueden utilizarse juntos. OpenID Connect estandariza los mecanismos para tokens de acceso y tokens de actualización, permitiendo a los desarrolladores utilizar tokens de corta duración para mitigar el riesgo de robo de tokens. El ecosistema de OpenID Connect también está prosperando, con muchas implementaciones de servidor y cliente disponibles para ayudar a los desarrolladores a construir sistemas de autenticación de identidad basados en el protocolo OpenID Connect. Además, soluciones de autenticación de identidad de código abierto como Keycloak pueden ayudar a los desarrolladores a implementar servicios de autenticación de identidad seguros.
Las nuevas prácticas de tecnología de front-end, como Next.js, están introduciendo gradualmente técnicas de renderizado del lado del servidor en el ámbito del front-end. Esto representa una nueva evolución del antiguo paradigma de desarrollo web, combinando React con programas de back-end para mejorar aún más la experiencia del usuario. Ahora existen más bibliotecas, como NextAuth, que pueden ayudar a los desarrolladores a implementar la autenticación de identidad utilizando este mecanismo, haciendo que el proceso de autenticación sea más amigable para los desarrolladores.
Puertas de Enlace API y Autenticación de Identidad
Consideremos cómo nuestras aplicaciones móviles interactúan con los datos. ¿También utilizan API? En las aplicaciones móviles, no existe un mecanismo de cookies como en los navegadores para almacenar sesiones de usuario, por lo que principalmente utilizan tokens para pasar información a través de los encabezados de las solicitudes HTTP.
¿Qué pasa con los servicios API? Un back-end de aplicación exitoso generalmente consiste en muchos sistemas API complejos que requieren un mecanismo de autenticación de identidad unificado. De lo contrario, los desarrolladores tendrían que implementar el mismo mecanismo de autenticación para cada servicio, lo que sería engorroso.
Las puertas de enlace API pueden ayudarnos a resolver este problema manejando tareas de autenticación y análisis similares a las cookies o tokens, y pasando directamente la información de identidad analizada a los servicios de back-end, reduciendo la duplicación de trabajo. Apache APISIX y API7 Enterprise también admiten funcionalidad de autenticación OpenID Connect lista para usar, ayudando a los usuarios a integrar servicios de autenticación de identidad directamente. Además, las puertas de enlace API admiten la implementación de cualquier mecanismo de autenticación a través de scripts, por lo que incluso con mecanismos de autenticación de identidad personalizados, pueden integrarse en la puerta de enlace API, simplificando el desarrollo de aplicaciones.
Resumen
El desarrollo de los métodos de interacción del usuario ha impulsado avances en la autenticación de identidad. El enfoque centrado en API se está convirtiendo en una tendencia principal, y las API pueden ser proporcionadas por arquitecturas de microservicios, lo que requiere un mecanismo de autenticación de identidad unificado para reducir el desarrollo redundante. Por lo tanto, deberíamos elegir mecanismos más modernos como OpenID Connect y JWT, y utilizar una puerta de enlace API puede proporcionar funcionalidad adicional para el desarrollo de API.