Keycloak: Autenticación con Java Quarkus
Implementación de servicio de autenticación Keycloak con api rest en Java Quarkus
Las últimas versiones de Keycloak ya no utilizan WildFly como servidor y motor de distribución, ahora implementan un servidor de aplicaciones basado en Java Quarkus. Por tanto, hay algunos cambios en la instalación y configuración del servicio.
El siguiente archivo manifiesto contiene la especificación básica de servicio Keycloak. Define usuario administrador, un volumen en directorio local para persistencia (base de datos H2), puerto tcp y un comando de modo de operación. El modo de operación de desarrollo (comando 'start-dev') es útil en entornos de prueba y desarrollo porque permite http y es menos exigente en cuanto a requisitos de seguridad y resolución de nombres de hosts. Para entornos de produción se debe utilizar el modo de operación 'start'.
docker-compose.yml
version: '3'
services:
keycloak:
image: quay.io/keycloak/keycloak:18.0.2
container_name: keycloak
restart: unless-stopped
environment:
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: admin123
volumes:
- ./data:/opt/keycloak/data/
ports:
- 8080:8080
command:
- start-dev
Vamos a crear un realm de ejemplo ('corp'), junto a un cliente ('service'), usuarios ('lab', 'dev') y roles ('user', 'admin'). Esto lo haremos en el terminal, utilizando el servicio admin-cli disponible en el directorio /opt/keycloak/bin/ del contenedor.
Iniciar servicio Keycloak e ingresar a contenedor:
docker-compose run -d
docker exec -it keycloak bash
Acceder a directorio de binarios de administración de Keycloak y autenticarse con usuario 'admin' definido en docker compose:
cd opt/keycloak/bin/
./kcadm.sh config credentials --server http://localhost:8080 --realm master --user admin
Crear realm:
./kcadm.sh create realms -s realm=corp -s enabled=true -o
Crear cliente, asociarlo al nuevo realm, definir parámetros de acceso y url de servicio rest:
./kcadm.sh create clients -r corp -s clientId=service -s enabled=true
-s clientAuthenticatorType=client-secret -s secret=qwe1234.
-s publicClient=false -s bearerOnly=false -s standardFlowEnabled=true
-s directAccessGrantsEnabled=true -s serviceAccountsEnabled=true
-s "redirectUris=[\"http://localhost:8000/api/*\"]"
Crear usuarios y asociarlos al nuevo realm
./kcadm.sh create users -r corp -s username=lab -s enabled=true
./kcadm.sh set-password -r corp --username lab --new-password lab123
./kcadm.sh create users -r corp -s username=dev -s enabled=true
./kcadm.sh set-password -r corp --username dev --new-password dev123
Crear roles y asociarlos al realm y a los nuevos usuarios
./kcadm.sh create roles -r corp -s name=user
./kcadm.sh create roles -r corp -s name=admin
./kcadm.sh add-roles --uusername lab --rolename user -r corp
./kcadm.sh add-roles --uusername dev --rolename admin -r corp
Servicio Rest Java Quarkus
Dependencias en archivo pom.xml de proyecto Java Quarkus de ejemplo:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-keycloak-authorization</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-oidc</artifactId>
</dependency>
Archivo de propiedades de proyecto java, se define la url de servicio keycloak con el realm de ejemplo 'corp' y cliente 'service':
quarkus.http.port=8000
quarkus.oidc.auth-server-url=http://localhost:8080/realms/corp
quarkus.oidc.client-id=service
Clases con métodos para pruebas básicas de acceso a recursos protegidos utilizando la anotación @RolesAllowed:
AdminResource.java:
@Path("/api/admin")
public class AdminResource {
@GET
@Path("/info")
@RolesAllowed("admin")
@Produces(MediaType.TEXT_PLAIN)
public String user() {
return "admin resource granted..";
}
}
UserResouce.java, tiene un recurso público de ejemplo ('/api/users/open'):
@Path("/api/users")
public class UserResource {
@GET
@Path("/info")
@RolesAllowed("user")
@Produces(MediaType.TEXT_PLAIN)
public String user() {
return "user resource granted..";
}
@GET
@Path("/open")
@PermitAll
@Produces(MediaType.TEXT_PLAIN)
public String open() {
return "public resource..";
}
}
Pruebas con curl: autenticarse y obtener access token:
curl -X POST http://localhost:8080/realms/corp/protocol/openid-connect/token \
--user service:qwe1234. \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'username=lab&password=lab123&grant_type=password'
curl -X POST http://localhost:8080/realms/corp/protocol/openid-connect/token \
--user service:qwe1234. \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'username=dev&password=dev123&grant_type=password'
Probar servicio java quarkus con curl, utilizando access token:
curl -v -X GET \
http://localhost:8000/api/users/info \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia.."
curl -v -X GET \
http://localhost:8000/api/admin/info \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2l.."
Puedes descargar el código fuente completo de este ejemplo en el siguiente enlace.
¿Tienes alguna consulta?
Puedes contactarme enviándome un mensaje desde aquí.
![](assets/img/posts/2022/post-java-virtual-threads-1.webp)
diciembre 16, 2022 Backend
![](assets/img/posts/2022/raspberry-pi-router-1.jpg)
septiembre 19, 2022 Redes/Networking, Embedded Systems
![](assets/img/posts/2022/keycloak-1.jpg)
julio 20, 2022 Cloud
- Backend(4)
- Redes/Networking(4)
- Embedded Systems(2)
- Cloud(2)
- Frontend(3)
- Microservicios(4)