Cabinee Connector: Keycloak (unibpm-external-task-keycloak)
Purpose
The unibpm-external-task-keycloak module provides a Cabinee
connector for BPMN processes to interact with the Keycloak
identity management system through the External Task mechanism.
The connector allows processes to:
- retrieve user data
- look up a user by username
- retrieve a user’s groups
- retrieve group information
- retrieve group members
The module runs in the Integration Runtime service, which receives jobs from Cabinee Kafka topics.
Architecture
BPMN Service Task
→ Cabinee Engine
→ Kafka Topic (external-task.jobs.*)
→ Integration Runtime
→ Keycloak connector handler
→ Keycloak Admin REST API
Component Purpose
Cabinee Engine publishes External Task jobs Integration Runtime executes connector handlers KeycloakClient HTTP client for Keycloak Handlers implement specific connector actions
Supported actions
Action Description
user.get Get a user by ID
user.getByUsername Find a user by username
user.groups Get a user’s groups
group.get Get a group by ID
group.members Get group members
group.getByName Find a group by name
Common extension properties
Every BPMN Service Task must define the following properties:
Property Required Description
uni.connector ✔ connector name (keycloak)
uni.action ✔ action to execute
uni.version ✔ connector version
kc.result ✖ process variable name for the result
kc.select ✖ result attribute filtering
Result filtering (kc.select)
The kc.select property returns only the selected fields
from the Keycloak response.
Filtering works as a whitelist projection of attributes.
Example
Keycloak response:
{
"id": "123",
"username": "ivanov",
"email": "ivanov@reunico.com"
}
BPMN configuration:
kc.select = id,email
Result:
{
"id": "123",
"email": "info@reunico.com"
}
Nested attributes
Selecting nested fields is supported:
kc.select = id,attributes.signerFullName
Result:
{
"id": "123",
"attributes": {
"signerFullName": "Seva Ivanov"
}
}
Working with lists
If the response contains an array of objects, filtering is applied to each element.
Example:
kc.select = id,email
Result:
[
{
"id": "1",
"email": "a@company.com"
},
{
"id": "2",
"email": "b@company.com"
}
]
Actions
user.get
Get a user by ID.
Extension properties
Property Required Description
kc.userId ✔ Keycloak user ID
kc.result ✖ result variable name
kc.select ✖ result filtering
Example
uni.connector = keycloak
uni.action = user.get
uni.version = v1
kc.userId = ${userId}
kc.result = userData
user.getByUsername
Get a user by username.
Extension properties
Property Required Description
kc.username ✔ user username
kc.result ✖ result variable
kc.select ✖ result filtering
Example:
uni.connector = keycloak
uni.action = user.getByUsername
uni.version = v1
kc.username = ${initiator}
user.groups
Get a user’s groups.
Extension properties
Property Required Description
kc.userId ✔ user ID
kc.result ✖ result variable
kc.select ✖ result filtering
Result:
kc.groups = List<KeycloakGroup>
group.get
Get a group by ID.
Extension properties
Property Required Description
kc.groupId ✔ group ID
kc.result ✖ result variable
kc.select ✖ result filtering
group.getByName
Get a group by name.
Extension properties
Property Required Description
kc.groupName ✔ group name
kc.result ✖ result variable
kc.select ✖ result filtering
group.members
Get group members.
Extension properties
Property Required Description
kc.groupId ✔ group ID
kc.first ✖ offset
kc.max ✖ limit
kc.result ✖ result variable
kc.select ✖ result filtering
BPMN errors
Some connector errors are converted into a BPMN Error.
Code Description
KC_USER_NOT_FOUND user not found
KC_GROUP_NOT_FOUND group not found
BPMN Service Task example
uni.connector = keycloak
uni.action = user.groups
uni.version = v1
kc.userId = ${initiator}
kc.result = groups
kc.select = id,name
Result:
[
{ "id": "...", "name": "Managers" },
{ "id": "...", "name": "HR" }
]
Requirements
The Keycloak service account must have the following roles:
realm-management
manage-users
view-users
query-groups
Technologies
- Java 17
- Spring Boot
- OpenFeign
- Kafka
- Jackson
- Keycloak Admin REST API