En cualquier empresa grande, y X5 Retail Group no es una excepción, a medida que se desarrolla, aumenta el número de proyectos donde se requiere la autorización de usuarios. Con el tiempo, se necesita una transición fluida de los usuarios de una aplicación a otra y surge la necesidad de utilizar un servidor único de Single-Sign-On (SSO). Pero, ¿qué hacer cuando ya se utilizan proveedores de identidad como AD u otros que no tienen atributos adicionales en varios proyectos? Los sistemas llamados 'correos de identidad' vienen al rescate. Sus representantes más funcionales son productos como Keycloak, Gravitee Access Management, entre otros. Los escenarios de uso suelen ser diversos: interacción máquina a máquina, participación de usuarios, etc. La solución debe soportar funcionalidades flexibles y escalables que puedan unir todos los requisitos en una sola, y esa solución en nuestra empresa actualmente es el bróker de identidad: Keycloak.

Keycloak es un producto de código abierto destinado a la identificación y control de acceso, respaldado por la empresa RedHat. Es la base para los productos de la empresa que utilizan SSO: RH-SSO.
Conceptos básicos
Antes de comenzar a revisar soluciones y enfoques, es necesario aclarar los términos y la secuencia de procesos:

Identificación — es el procedimiento para reconocer a un sujeto por su identificador (en otras palabras, es determinar el nombre, inicio de sesión o número).
Autenticación — es el procedimiento de autenticación (se verifica al usuario mediante una contraseña, un correo se valida mediante firma electrónica, etc.).
Autorización — es la concesión de acceso a algún recurso (por ejemplo, al correo electrónico).
Bróker de identidad Keycloak
Keycloak — es una solución para la gestión de identidades y accesos de código abierto, diseñada para ser utilizada en sistemas donde se pueden emplear patrones de arquitectura de microservicios.
Keycloak ofrece funciones como inicio único (SSO), identificación de bróker y acceso social, federación de usuarios, adaptadores de clientes, consola de administración y consola de gestión de cuentas.
Funcionalidades básicas soportadas en Keycloak:
- Single-Sign On y Single-Sign Out para aplicaciones web.
- Soporte para OpenID/OAuth 2.0/SAML.
- Identificación de Agentes – autenticación mediante proveedores de identidad externos OpenID Connect o SAML.
- Inicio de Sesión Social – soporte para Google, GitHub, Facebook, Twitter para la identificación de usuarios.
- Federación de Usuarios – sincronización de usuarios desde servidores LDAP y Active Directory y otros proveedores de identidad.
- Puente Kerberos – uso del servidor Kerberos para la autenticación automática de usuarios.
- Consola Administrativa — para la gestión unificada de configuraciones y parámetros de la solución a través de la Web.
- Consola de Gestión de Cuentas – para la autogestión del perfil de usuarios.
- Personalización de la solución basada en la identidad corporativa.
- Autenticación 2FA – soporte para TOTP/HOTP mediante Google Authenticator o FreeOTP.
- Flujos de Inicio de Sesión – posibilidad de auto registro de usuarios, recuperación y restablecimiento de contraseñas, y más.
- Gestión de Sesiones – los administradores pueden gestionar las sesiones de los usuarios desde un único punto.
- Mapeadores de Tokens – vinculación de atributos de usuarios, roles y otros atributos necesarios en los tokens.
- Gestión flexible de políticas a través de realm, aplicación y usuarios.
- Soporte CORS – adaptadores de cliente tienen soporte incorporado para CORS.
- Interfaces de Proveedor de Servicios (SPI) – gran cantidad de SPI que permiten configurar varios aspectos del funcionamiento del servidor: flujos de autenticación, proveedores de identidad, mapeo de protocolos y mucho más.
- Adaptadores de cliente para aplicaciones JavaScript, WildFly, JBoss EAP, Fuse, Tomcat, Jetty, Spring.
- Soporte para trabajar con diversas aplicaciones que utilizan la biblioteca OpenID Connect Relying Party o la biblioteca SAML 2.0 Service Provider.
- Posibilidad de expansión mediante plugins.
Para procesos CI/CD y también la automatización de procesos de gestión en Keycloak, se puede utilizar REST API/JAVA API. La documentación está disponible en formato electrónico:
REST API
JAVA API
Proveedores de identidad a nivel empresarial (On-Premise)
Posibilidad de autenticación de usuarios a través de servicios de Federación de Usuarios.

También se puede utilizar la autenticación única: si los usuarios se autentican en estaciones de trabajo con Kerberos (LDAP o AD), pueden ser autenticados automáticamente en Keycloak sin necesidad de volver a ingresar su nombre de usuario y contraseña.
Para la autenticación y autorización de los usuarios, es posible utilizar una base de datos relacional, lo cual es más aplicable para entornos de desarrollo, ya que no implica configuraciones e integraciones prolongadas en las primeras etapas de los proyectos. Por defecto, Keycloak utiliza una base de datos incorporada para almacenar la configuración y los datos de los usuarios.
La lista de bases de datos soportadas es amplia e incluye: MS SQL, Oracle, PostgreSQL, MariaDB, Oracle y otras. Las que han sido más probadas hasta el momento son Oracle 12C Release1 RAC y Galera 3.12 cluster para MariaDB 10.1.19.
Proveedores de identidad — inicio de sesión social
Es posible utilizar el inicio de sesión desde redes sociales. Para activar la posibilidad de autenticar a los usuarios, se utiliza la consola de administración de Keycloak. No se requieren cambios en el código de las aplicaciones y esta funcionalidad está disponible 'de fábrica' y puede ser activada en cualquier etapa de la implementación del proyecto.

Para la autenticación de usuarios, es posible utilizar proveedores de identidad OpenID/SAML.
Escenarios típicos de autorización utilizando OAuth2 en Keycloak
Flujo de Código de Autorización — se utiliza con aplicaciones del lado del servidor (server-side applications). Uno de los tipos más comunes de autorización, ya que es muy adecuado para aplicaciones del lado del servidor, donde el código fuente de la aplicación y los datos del cliente no son accesibles para terceros. En este caso, el proceso se basa en la redirección. La aplicación debe poder interactuar con el agente del usuario (user-agent), como un navegador web, para recibir códigos de autorización de API redirigidos a través del agente del usuario.
Flujo Implícito — se utiliza por aplicaciones móviles o web (aplicaciones que funcionan en el dispositivo del usuario).
El tipo implícito de autorización se utiliza en aplicaciones móviles y web, donde no se puede garantizar la privacidad del cliente. Este tipo de autorización también utiliza la redirección del agente de usuario, pasando el token de acceso al agente de usuario para su uso posterior en la aplicación. Esto hace que el token esté disponible para el usuario y otras aplicaciones en el dispositivo del usuario. Con este tipo de autorización, no se lleva a cabo la autenticación de la aplicación y el proceso se basa en la URL de redirección (registrada previamente en el servicio).
El flujo implícito no admite tokens de actualización (refresh tokens).
Flujo de concesión de credenciales del cliente — se utiliza cuando una aplicación accede a una API. Este tipo de autorización se utiliza normalmente para interacciones «servidor-servidor» que deben ejecutarse en segundo plano sin interacción inmediata del usuario. El flujo de otorgación de credenciales del cliente permite que un servicio web (cliente confidencial) utilice sus propias credenciales en lugar de representar al usuario para la autenticación al llamar a otro servicio web. Para un mayor nivel de seguridad, el servicio que realiza la llamada puede utilizar un certificado (en lugar de un secreto compartido) como credenciales.
La especificación OAuth2 está descrita en
Token JWT y sus ventajas
JWT (JSON Web Token) es un estándar abierto (), que define un método compacto y autónomo para la transmisión segura de información entre partes en forma de objeto JSON.
Según el estándar, el token consta de tres partes en formato base-64, separadas por puntos. La primera parte se llama encabezado (header), que contiene el tipo de token y el nombre del algoritmo de hash utilizado para obtener la firma digital. La segunda parte almacena la información principal (usuario, atributos, etc.). La tercera parte es la firma digital.
..
Nunca almacenes el token en tu base de datos. Porque un token válido es equivalente a una contraseña; almacenar el token es lo mismo que almacenar una contraseña en texto claro.
Token de acceso — es un token que proporciona a su propietario acceso a recursos protegidos en el servidor. Normalmente, tiene una vida útil corta y puede contener información adicional, como la dirección IP de la parte que solicita este token.
Token de actualización — es un token que permite a los clientes solicitar nuevos tokens de acceso una vez que hayan expirado. Estos tokens generalmente se emiten por un período prolongado.
Principales ventajas de su uso en arquitectura de microservicios:
- Posibilidad de acceder a varias aplicaciones y servicios a través de una única autenticación.
- Si faltan ciertos atributos requeridos en el perfil de usuario, es posible enriquecer los datos que se pueden agregar a la carga útil, incluso de manera automatizada y "en tiempo real".
- No es necesario almacenar información sobre sesiones activas; la aplicación del servidor solo necesita verificar la firma.
- Gestión de acceso más flexible gracias a atributos adicionales en la carga útil.
- El uso de la firma del token para el encabezado y la carga útil aumenta la seguridad de la solución en general.
Token JWT — composición
Encabezado — por defecto, el encabezado contiene solo el tipo de token y el algoritmo utilizado para la encriptación.
El tipo de token se almacena en la clave "typ". La clave "typ" es ignorada en JWT. Si la clave "typ" está presente, su valor debe ser JWT, para indicar que este objeto es un JSON Web Token.
La segunda clave "alg" define el algoritmo utilizado para la encriptación del token. Por defecto, debe establecerse en HS256. El encabezado se codifica en base64.
{ "alg": "HS256", "typ": "JWT"}
Carga útil (contenido) — en la carga útil se almacena cualquier información que necesite ser verificada. Cada clave en la carga útil se conoce como "declaración". Por ejemplo, se puede acceder a la aplicación solo por invitación (promoción cerrada). Cuando queremos invitar a alguien a participar, le enviamos un correo electrónico con la invitación. Es importante verificar que la dirección de correo electrónico pertenece a la persona que acepta la invitación, por lo que incluiremos esta dirección en la carga útil, guardándola en la clave "e-mail".
{ "email": "example@x5.ru" }
Las claves en la carga útil pueden ser arbitrarias. Sin embargo, hay algunas reservas:
- iss (Emisor) — define la aplicación desde la cual se envía el token.
- sub (Subject) — define el tema del token.
- aud (Audience) – un array de cadenas sensibles a mayúsculas o URI, que es una lista de destinatarios de este token. Cuando la parte receptora recibe un JWT con esta clave, debe verificar su presencia en los destinatarios; de lo contrario, ignorar el token.
- exp (Expiration Time) — indica cuándo expira el token. El estándar JWT requiere que en todas sus implementaciones, los tokens con tiempo de expiración hayan sido rechazados. La clave exp debe ser una marca de tiempo en formato unix.
- nbf (Not Before) — es el tiempo en formato unix que define el momento en que el token será válido.
- iat (Issued At) — esta clave representa el tiempo en que se emitió el token y puede ser utilizada para determinar la edad del JWT. La clave iat debe ser una marca de tiempo en formato unix.
- jti (JWT ID) — una cadena que define el identificador único de este token, siendo sensible a mayúsculas.
Es importante entender que la carga útil no se transmite de forma encriptada (aunque, los tokens pueden estar anidados, permitiendo así transmitir datos encriptados). Por tanto, no se puede almacenar información secreta en ella. Al igual que el encabezado, la carga útil se codifica en base64.
Firma — una vez que tenemos el encabezado y la carga útil, se puede calcular la firma.
Se toman el encabezado y la carga útil codificados en base64, se combinan en una cadena a través de un punto. Luego, esta cadena y la clave secreta se pasan al algoritmo de cifrado especificado en el encabezado (clave "alg"). La clave puede ser cualquier cadena. Las cadenas más largas serán preferibles, ya que tomarán más tiempo para ser descifradas.
{"alg":"RSA1_5","payload":"A128CBC-HS256"}
Construcción de la arquitectura de un clúster de Keycloak resistente a fallos
Al utilizar un único clúster para todos los proyectos, se generan mayores requisitos para la solución de SSO. Cuando el número de proyectos no es grande, estos requisitos no son tan perceptibles para todos los proyectos; sin embargo, a medida que aumenta la cantidad de usuarios e integraciones, también lo hacen los requerimientos de disponibilidad y rendimiento.
El aumento de los riesgos de fallo del SSO unificado incrementa los requisitos para la arquitectura de la solución y los métodos de respaldo de los componentes, lo que resulta en un SLA muy estricto. Por ello, en las fases de desarrollo o implementación temprana de las soluciones, los proyectos suelen tener su propia infraestructura que no es tolerante a fallos. A medida que avanza el desarrollo, es necesario incorporar capacidades de crecimiento y escalado. La forma más flexible de construir un clúster tolerante a fallos es mediante la virtualización de contenedores o un enfoque híbrido.
Para operar en modo Active/Active y Active/Passive, el clúster debe garantizar la consistencia de los datos en la base de datos relacional: ambos nodos de la base de datos deben replicarse de manera sincrónica entre diferentes centros de datos geográficamente distribuidos.
El ejemplo más sencillo de una instalación tolerante a fallos.

¿Cuáles son las ventajas de utilizar un clúster unificado?
- Alta disponibilidad y rendimiento.
- Soporte para los modos de operación: Active/Active, Active/Passive.
- Capacidad de escalado dinámico — al utilizar virtualización de contenedores.
- Posibilidad de gestión y monitoreo centralizado.
- Un enfoque único para la identificación/autenticación/autorización de usuarios en los proyectos.
- Interacción más transparente entre diversos proyectos sin la participación de los usuarios.
- Posibilidad de reutilizar el token JWT en diferentes proyectos.
- Un solo punto de confianza.
- Lanzamiento más rápido de proyectos utilizando microservicios/virtualización de contenedores (no se requiere levantar y configurar componentes adicionales).
- Es posible adquirir soporte comercial del proveedor.
Aspectos a tener en cuenta al planificar un clúster
SGBD
Keycloak utiliza un sistema de gestión de bases de datos para almacenar: realms, clients, users, etc.
Se admite una amplia gama de bases de datos: MS SQL, Oracle, MySQL, PostgreSQL. Keycloak se entrega con su propia base de datos relacional integrada. Se recomienda su uso para entornos no cargados, como los entornos de desarrollo.
Para operar en modo Active/Active y Active/Passive, el clúster debe garantizar la consistencia de los datos en la base de datos relacional y ambos nodos del clúster de base de datos se replican de forma sincrónica entre los centros de datos.
Caché distribuido (Infinispan)
Para un funcionamiento correcto del clúster, se requiere la sincronización adicional de los siguientes tipos de caché utilizando JBoss Data Grid:
Sesiones de autenticación: se utilizan para mantener los datos durante la autenticación de un usuario específico. Las solicitudes de este caché generalmente incluyen solo el navegador y el servidor Keycloak, y no la aplicación.
Tokens de acción: se utilizan en escenarios donde el usuario necesita confirmar una acción de forma asíncrona (por correo electrónico). Por ejemplo, durante el flujo de olvido de contraseña, el caché actionTokens de Infinispan se utiliza para rastrear metadatos sobre los tokens de acción relacionados que ya se han utilizado, por lo que no se pueden reutilizar.
Caché e invalidación de datos persistentes: se utiliza para almacenar en caché datos persistentes para evitar consultas innecesarias a la base de datos. Cuando un servidor Keycloak actualiza datos, todos los demás servidores Keycloak en todos los centros de datos deben estar al tanto.
Trabajo: se utiliza únicamente para enviar mensajes de invalidación entre nodos del clúster y centros de datos.
Sesiones de usuario: se utilizan para almacenar datos sobre sesiones de usuario que son válidas durante la sesión del navegador del usuario. El caché debe manejar solicitudes HTTP del usuario final y de la aplicación.
Protección contra ataques de fuerza bruta: se utiliza para rastrear datos sobre intentos de inicio de sesión fallidos.
Balanceo de carga
El balanceador de carga es el único punto de entrada en Keycloak y debe admitir sesiones pegajosas.
Servidores de aplicaciones
Se utilizan para controlar la interacción entre componentes y pueden ser virtualizados o contenerizados utilizando herramientas de automatización existentes y escalado dinámico de infraestructura. Los escenarios de implementación más comunes en OpenShift, Kubernetes, Rancher.
Aquí finaliza la primera parte, la teórica. En los siguientes ciclos de artículos, se analizarán ejemplos de integraciones con varios proveedores de identidad y ejemplos de configuraciones.
Fuente: habr.com
