Keycloak y Gateway con Seguridad - nelsonortfan/MicroDockerSpringBoot GitHub Wiki

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:

Docker keycloak Inicio

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:

imagen

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:

Cliente 0

Autorizamos la autenticación del cliente y dejamos que el flujo sea basado por cuentas de servicio de Roles:

cliente 1

Dejamos vacías las urls siguientes y damos click en Save:

cliente 2

Veremos que el cliente fue creado satisfactoriamente:

cliente 3

Si damos click en la pestaña de Credenciales veremos el secret del cliente el cual usaremos posteriormente para solicitar el token:

cliente 4

En la opcion de Realm settings del Realm Master, podemos ver la url de los endpoints que usaremos desde nuestro microservicio Gateway para comunicarnos:

endpoint 5

endpoint 6

Si damos click veremos todas las urls necesarias:

endpoint 7

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:

endpoint 8

Esta sera la respuesta:

endpoint 9

endpoint 10

Si quitamos en la petición en el scope la opción openId, veremos esta respuesta:

endpoint 11

endpoint 12

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:

Gateway 13

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:

Gateway 14

En el archivo de properties, copiamos la url de Keycloak para poderse conectar y validar:

Gateway 15

Iniciamos todos los servicios, dejando de ultimas el Gateway:

Gateway 16

Vemos que las peticiones GET no requieren autenticación:

Gateway 17

Si hacemos una peticion POST fallara porque no esta autorizado:

Gateway 18

Vamos a la pestaña Authorization y vemos la configuración usando OAUTH 2.0, copiamos la clave secreta del cliente:

Gateway 19

Bajamos y le damos la opción de crear un nuevo token, el cual usaremos:

Gateway 20

Gateway 20b

Gateway 22

Volvemos a enviar la petición POST y sera satisfactoria:

Gateway 23

Para los otros servicios (Cards y Loans) repetimos el proceso y debe ser exitoso:

Gateway 24

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:

Role 25

Role 26

Luego vamos al cliente que creamos y seleccionamos la pestaña Service accounts roles:

Role 28

Y le asignamos los roles que creamos:

Role 30

Role 31

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:

Role 32

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.

imagen

Comenzamos creando un nuevo cliente:

Authortization Code 33

Habilitamos la autenticación del cliente y el flujo de autenticación es el estándar:

Authortization Code 34

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:

Authortization Code 35

Vemos la confirmación de la creación:

Authortization Code 36

En la opción de Credentials veremos el secreto del cliente:

Authortization Code 37

Ahora procedemos a crear un usuario en la opción Users:

Authortization Code 38

Authortization Code 39

Veremos que el usuario es creado:

Authortization Code 40

En la opción de Credentials procedemos a crear un password, le quitamos la opción de temporal para que no tenga que modificarla:

Authortization Code 41

Authortization Code 42

Authortization Code 43

Luego sobre el usuario escogemos la pestaña Role mappping y le asignamos los roles que creamos con anterioridad:

Authortization Code 44

Authortization Code 45

Authortization Code 46

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:

Authortization Code 47

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):

Authortization Code 48

Authortization Code 49

Authortization Code 50

Authortization Code 51

Authortization Code 52

Volvemos a hacer la petición POST con el token y ahora sera satisfactoria:

Authortization Code 53

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:

Docker 57a

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:

Docker 57b

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:

Docker 57c

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

Docker 57

Veremos que se crea en Docker:

Docker 58

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

Docker 59

La versión de este código esta en el repositorio con la versión V.7.3