Keycloak y Gateway con Seguridad - nelsonortfan/MicroDockerSpringBoot GitHub Wiki
- Keycloak Server
- Client Credentials
- Configuración Gatewayserver
- Autenticación por Roles
- Registrar Cliente y Usuario Final
- Docker Compose
Keycloak Server
Comenzamos haciendo la instalacion de Keycloak, en este caso usaremos una imagen de Docker para lo cual ejecutamos el siguiente comando:
docker run -d -p 7080:8080 -e KC_BOOTSTRAP_ADMIN_USERNAME=admin -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:26.2.5 start-dev
Veremos que se crea correctamente:
Una vez iniciado, abrimos la consola en el puerto 7080 ya que el 8080 esta siendo usado por el microservicios ACCOUNTS.
Client Credentials
Usada para conectar APIs entre si. Es la más simple y se usa solo si no existen UI o usuarios finales en el proceso:
Empezaremos creando un cliente que use la opción Client Credentials. Con esta opción, el Gatewayserver se encarga de todo y no es necesario que el usuario final tenga que loguear en Keycloak para ser validado. Vamos a Keycloak y creamos un cliente con el nombre eazybank-callcenter-cc con la descripción y diciendo que es un cliente tipo OpenID Connect. Damos click en Next:
Autorizamos la autenticación del cliente y dejamos que el flujo sea basado por cuentas de servicio de Roles:
Dejamos vacías las urls siguientes y damos click en Save:
Veremos que el cliente fue creado satisfactoriamente:
Si damos click en la pestaña de Credenciales veremos el secret del cliente el cual usaremos posteriormente para solicitar el token:
En la opcion de Realm settings del Realm Master, podemos ver la url de los endpoints que usaremos desde nuestro microservicio Gateway para comunicarnos:
Si damos click veremos todas las urls necesarias:
Desde Postman haremos una petición POST hacia el endpoint token_endpoint con la siguiente configuración agregando el cliente ID y el secreto que vimos anteriormente. Incluimos también el Scope para que traiga un token adicional con mas información:
Esta sera la respuesta:
Si quitamos en la petición en el scope la opción openId, veremos esta respuesta:
Configuración Gatewayserver
En el proyecto de Gateway Server, se agregan las siguientes dependencias en el archivo pom.xml para que se pueda trabajar con Keycloak:
Modificamos la aplicación creando una clase que nos permita acceder a las peticiones POST estando autenticado mientras que los GET no tienen restricción:
En el archivo de properties, copiamos la url de Keycloak para poderse conectar y validar:
Iniciamos todos los servicios, dejando de ultimas el Gateway:
Vemos que las peticiones GET no requieren autenticación:
Si hacemos una peticion POST fallara porque no esta autorizado:
Vamos a la pestaña Authorization y vemos la configuración usando OAUTH 2.0, copiamos la clave secreta del cliente:
Bajamos y le damos la opción de crear un nuevo token, el cual usaremos:
Volvemos a enviar la petición POST y sera satisfactoria:
Para los otros servicios (Cards y Loans) repetimos el proceso y debe ser exitoso:
Esta version del codigo es la V.7.1. del repositorio V.7.1
Autenticación por Roles
Ahora vamos a hacer la autenticacion por Roles. Empezamos en Realm roles en Keycloak y creamos los roles de ACCOUNTS, CARDS y LOANS:
Luego vamos al cliente que creamos y seleccionamos la pestaña Service accounts roles:
Y le asignamos los roles que creamos:
Si tomáramos un token generado y lo pasáramos por una herramienta JWT veremos que los roles vienen en el Payload en la clave realm_access:
Se modifica la aplicación de Gatewayserver para que se haga el control por roles y para que del token obtenga el rol. Algo interesante es que Spring Boot usa por configuración los roles usando el prefijo "ROLE_" por eso se agrega en la lógica para concatenarlo con lo que obtiene del token y así pueda saber el rol. Las modificaciones de este cambio se ven en la versión V.7.2.
Registrar Cliente y Usuario Final
Este es el flujo comúnmente usando ya que existe el usuario final y una UI que hará que haga login para la creación del Token. Esto es Authorization Code. En este caso, al no tener una UI, usaremos POSTMAN para simularlo.
Comenzamos creando un nuevo cliente:
Habilitamos la autenticación del cliente y el flujo de autenticación es el estándar:
En las urls, por el momento dejaremos en valor * que significa cualquiera para las opciones Valid direct URIs y Web origins, en la vida real se controla colocando los dominios específicos que queramos controlar:
Vemos la confirmación de la creación:
En la opción de Credentials veremos el secreto del cliente:
Ahora procedemos a crear un usuario en la opción Users:
Veremos que el usuario es creado:
En la opción de Credentials procedemos a crear un password, le quitamos la opción de temporal para que no tenga que modificarla:
Luego sobre el usuario escogemos la pestaña Role mappping y le asignamos los roles que creamos con anterioridad:
Abrimos la Collection de Postman y esta vez usaremos las peticiones que dicen AuthCode. Copiamos el secret del cliente y vemos que hay una variable state, la cual tiene un valor random y se usa para manejar ataques CSRF:
Procedemos a generar el token y automáticamente se abrirá la pagina para autenticarnos con el usuario creado (antes de ello, cerrar todos los navegadores ya que lo estamos hacienndo desde POSTMAN simulando un cliente UI):
Volvemos a hacer la petición POST con el token y ahora sera satisfactoria:
En esta parte no hay modificación de código, se usa la misma versión anterior.
Docker Compose
Comenzamos actualizando los archivos pom.xml para dejar la versión S12 de las imágenes, las creamos localmente en Docker y las subimos al repositorio DockerHub. Luego sobre el archivo de Docker Compose agregamos un servicio para crear una imagen de Keycloak:
En los microservicios de Accounts, Loans y Cards, retiramos el mapeo de puertos para que no puedan estar expuestos al exterior y solo sea el Gateway el que puede acceder a el:
En el servicio de Gatewayserver, agregamos la variable de ambiente para que conecte con Keycloak. Dejamos el puerto 8080 ya que en la red interna ese es donde Keycloak inicializa:
Luego, ejecutamos el comando para inicializar el docker compose con la opción -d para que lo haga por debajo sin tanta información a mostrar:
docker compose up -d
Veremos que se crea en Docker:
Ya que el contenedor de Keycloak es uno nuevo, necesitamos hacer todas las configuraciones anteriores de crear clientes, roles y usuario para poder hacer las pruebas.
Una vez las pruebas sean finalizadas, se destruyen los contenedores:
docker compose down
La versión de este código esta en el repositorio con la versión V.7.3