Autenticación con OAuth y Keycloak en un servicio REST con JAX-RS y Spring Boot

Publicado por pico.dev el , actualizado el .
blog-stack java planeta-codigo programacion
Comentarios

Keycloak es un proveedor de OAuth que podemos usar en nuestras aplicaciones y servicios para proporcionar autenticación, autorización, SSO y también añadir seguridad a los servicios REST que desarrollemos como muestro en este artículo. OAuth tiene varias ventajas sobre usar autenticación Basic.

Keycloak
Java

Una forma de autenticar a los clientes de un servicio REST es usar autenticación Basic que se basa en añadir una cabecera en la petición en la que se incluye un usuario y contraseña. La autenticación Basic es sencilla pero para que sea segura ha de usar el protocolo seguro HTTPS.

Sin embargo, presenta otros inconvenientes y es que si al servicio van a acceder varios clientes y a uno queremos impedirle el acceso no podremos hacerlo sin cambiar el usuario y contraseña lo que obligará al resto de clientes actualizarse para usar las nuevas credenciales si las comparten, que no siempre es posible sobre todo si esos clientes están fuera de nuestro control. Para solventar el segundo problema tenemos la posibilidad de segurizar el servicio REST con el protocolo OAuth.

Teniendo un servicio web REST implementado con JAX-RS y Spring Boot añadirle seguridad con OAuth mediante el proveedor Keycloak es lo que muestro en este artículo. En el servicio REST bastará que usemos el adaptador para Spring Boot de Keycloak y añadamos en Keycloak cierta configuración que consistirá en un realm y el registro de un cliente. Para acceder al servicio REST usaremos el flujo client_credentials que nos permitirá obtener un token usando las credenciales del cliente.

Iniciado Keycloak con Docker y Docker Compose accedemos al panel de administración con el navegador, en mi caso en http://localhost:9080 con el usuario admin y contraseña admin según lo indicado en el archivo docker-compose.yml.

Creamos un realm, en el ejemplo llamado springbootjaxrs y un cliente con id client, además crearemos un rol api y se lo asignaremos al cliente.

Una vez realizada la configuración en el servidor de OAuth/Keycloak obtendremos la configuración para el adaptador de Keycloak para el servicio REST desde la pestaña Installation que añadiremos en el fichero de configuración de Spring Boot application.yml. Además, indicaremos que el cliente solo aceptará access tokens mediante la opción bearer-only de modo que no hará redirecciones para autenticar.

Indicaremos también el rol que deberá poseer el cliente para acceder al servicio REST junto que URLs del servicio estarán autenticadas por OAuth. Añadida la configuración al archivo application.yml el servicio REST es totalmente inconsciente de la autenticación que se realizará con OAuth y Keycloak.

Iniciado Keycloak y el servicio REST con el comando gradlew run podemos iniciar el proceso de obtención de un access token y llamar al servicio proporcionando el access token obtenido y ver que pasa si no proporcionamos token o uno modificado o inválido. Para obtener el access token podemos emplear curl accediendo al endpoint de Keycloak para obtenerlos.

Obtenido el access token si no lo proporcionamos en la llamada al servicio REST observaremos que la respuesta que obtenemos es un código de estado HTTP 401 indicando que se necesitan proporcionar las credenciales que con OAuth es un token.

Proporcionando el token mediante una cabecera de la petición el servicio nos devolverá los datos que proporciona. Si el token no es válido obtendremos un error HTTP 401.

Para usar Keycloak en una aplicación Java con Spring Boot deberemos añadir algunas dependencias al proyecto que usando Gradle como herramienta de construcción serían las siguientes.

Un buen libro sobre OAuth que he leído es Mastering OAuth 2.0 que explica detalladamente el protocolo OAuth junto con el resto de formas de obtener un token además del mostrado en este artículo usando las credenciales del cliente.

En el siguiente artículo mostraré un cliente del servicio REST autenticado con OAuth en Java que haga las mismas llamadas que con curl pero usando código Java mediante la librería HttpComponents.

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando el comando ./gradle run.