This is an automated email from the ASF dual-hosted git repository.
oscerd pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 85110f566255 CAMEL-23454: camel-keycloak: Add token revocation and
session logout operations
85110f566255 is described below
commit 85110f56625507b8d05855c0b8addd221652ea14
Author: Andrea Cosentino <[email protected]>
AuthorDate: Mon Jun 8 18:13:49 2026 +0200
CAMEL-23454: camel-keycloak: Add token revocation and session logout
operations
Adds 5 new operations to the camel-keycloak component to improve token and
session management:
- revokeAccessToken
- revokeRefreshToken
- logoutAllUsers
- pushNotBefore
- introspectToken
Closes #23848
---
.../apache/camel/catalog/components/keycloak.json | 32 +--
.../apache/camel/component/keycloak/keycloak.json | 32 +--
.../src/main/docs/keycloak-component.adoc | 103 +++++++-
.../component/keycloak/KeycloakConstants.java | 6 +
.../component/keycloak/KeycloakOperations.java | 6 +
.../camel/component/keycloak/KeycloakProducer.java | 141 +++++++++++
.../keycloak/KeycloakProducerRevocationIT.java | 279 +++++++++++++++++++++
.../dsl/KeycloakEndpointBuilderFactory.java | 24 ++
8 files changed, 592 insertions(+), 31 deletions(-)
diff --git
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/keycloak.json
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/keycloak.json
index 692f286998c7..34d0c275362f 100644
---
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/keycloak.json
+++
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/keycloak.json
@@ -43,7 +43,7 @@
"ipAddress": { "index": 16, "kind": "property", "displayName": "Ip
Address", "group": "common", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Filter events by IP
address" },
"keycloakClient": { "index": 17, "kind": "property", "displayName":
"Keycloak Client", "group": "common", "label": "", "required": false, "type":
"object", "javaType": "org.keycloak.admin.client.Keycloak", "deprecated":
false, "deprecationNote": "", "autowired": true, "secret": false,
"configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "To use an existing
configured Keycloak admin client" },
"maxResults": { "index": 18, "kind": "property", "displayName": "Max
Results", "group": "common", "label": "", "required": false, "type": "integer",
"javaType": "int", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": 100, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Maximum number of events
to retrieve per poll" },
- "operation": { "index": 19, "kind": "property", "displayName":
"Operation", "group": "common", "label": "", "required": false, "type": "enum",
"javaType": "org.apache.camel.component.keycloak.KeycloakOperations", "enum": [
"createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser",
"deleteUser", "getUser", "updateUser", "listUsers", "searchUsers",
"createRole", "deleteRole", "getRole", "updateRole", "listRoles",
"assignRoleToUser", "removeRoleFromUser", "getUserRoles", "cr [...]
+ "operation": { "index": 19, "kind": "property", "displayName":
"Operation", "group": "common", "label": "", "required": false, "type": "enum",
"javaType": "org.apache.camel.component.keycloak.KeycloakOperations", "enum": [
"createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser",
"deleteUser", "getUser", "updateUser", "listUsers", "searchUsers",
"createRole", "deleteRole", "getRole", "updateRole", "listRoles",
"assignRoleToUser", "removeRoleFromUser", "getUserRoles", "cr [...]
"operationTypes": { "index": 20, "kind": "property", "displayName":
"Operation Types", "group": "common", "label": "", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": false, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Filter admin events by
operation types (comma-separated list, e.g., CREATE,UPDATE,DELETE)" },
"password": { "index": 21, "kind": "property", "displayName": "Password",
"group": "common", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": true, "security": "secret", "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Keycloak password" },
"pojoRequest": { "index": 22, "kind": "property", "displayName": "Pojo
Request", "group": "common", "label": "", "required": false, "type": "boolean",
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "If we want to use a POJO
request as body or not" },
@@ -59,7 +59,7 @@
"autowiredEnabled": { "index": 32, "kind": "property", "displayName":
"Autowired Enabled", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": true, "description":
"Whether autowiring is enabled. This is used for automatic autowiring options
(the option must be marked as autowired) by looking up in the registry to find
if there is a single instance of matching [...]
},
"headers": {
- "CamelKeycloakOperation": { "index": 0, "kind": "header", "displayName":
"", "group": "common", "label": "", "required": false, "javaType":
"org.apache.camel.component.keycloak.KeycloakOperations", "enum": [
"createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser",
"deleteUser", "getUser", "updateUser", "listUsers", "searchUsers",
"createRole", "deleteRole", "getRole", "updateRole", "listRoles",
"assignRoleToUser", "removeRoleFromUser", "getUserRoles", "createGroup", "de
[...]
+ "CamelKeycloakOperation": { "index": 0, "kind": "header", "displayName":
"", "group": "common", "label": "", "required": false, "javaType":
"org.apache.camel.component.keycloak.KeycloakOperations", "enum": [
"createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser",
"deleteUser", "getUser", "updateUser", "listUsers", "searchUsers",
"createRole", "deleteRole", "getRole", "updateRole", "listRoles",
"assignRoleToUser", "removeRoleFromUser", "getUserRoles", "createGroup", "de
[...]
"CamelKeycloakRealmName": { "index": 1, "kind": "header", "displayName":
"", "group": "common", "label": "", "required": false, "javaType": "String",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The realm name", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#REALM_NAME" },
"CamelKeycloakUserId": { "index": 2, "kind": "header", "displayName": "",
"group": "common", "label": "", "required": false, "javaType": "String",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The user ID", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#USER_ID" },
"CamelKeycloakUsername": { "index": 3, "kind": "header", "displayName":
"", "group": "common", "label": "", "required": false, "javaType": "String",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The username", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#USERNAME" },
@@ -109,18 +109,20 @@
"CamelKeycloakContinueOnError": { "index": 47, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Continue on error during bulk
operations", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#CONTINUE_ON_ERROR" },
"CamelKeycloakBatchSize": { "index": 48, "kind": "header", "displayName":
"", "group": "common", "label": "", "required": false, "javaType": "Integer",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "Batch size for bulk operations", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#BATCH_SIZE" },
"CamelKeycloakAccessToken": { "index": 49, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The access token for permission
evaluation", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ACCESS_TOKEN" },
- "CamelKeycloakPermissionResourceNames": { "index": 50, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Comma-separated list of resource names
or IDs to evaluate permissions for", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#PERMISSION_RESOURCE_NAMES"
},
- "CamelKeycloakPermissionScopes": { "index": 51, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Comma-separated list of scopes to
evaluate permissions for", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#PERMISSION_SCOPES" },
- "CamelKeycloakSubjectToken": { "index": 52, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Subject token for permission evaluation
on behalf of a user", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#SUBJECT_TOKEN" },
- "CamelKeycloakPermissionAudience": { "index": 53, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Audience for permission evaluation",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#PERMISSION_AUDIENCE" },
- "CamelKeycloakPermissionsOnly": { "index": 54, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Whether to only return the list of
permissions without obtaining an RPT", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#PERMISSIONS_ONLY" },
- "CamelKeycloakOrganizationId": { "index": 55, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization ID", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_ID" },
- "CamelKeycloakOrganizationName": { "index": 56, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization name", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_NAME" },
- "CamelKeycloakOrganizationAlias": { "index": 57, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization alias",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_ALIAS" },
- "CamelKeycloakOrganizationDescription": { "index": 58, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization description",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_DESCRIPTION"
},
- "CamelKeycloakOrganizationRedirectUrl": { "index": 59, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization redirect URL",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_REDIRECT_URL"
},
- "CamelKeycloakOrganizationDomain": { "index": 60, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization domain name",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_DOMAIN" },
- "CamelKeycloakOrganizationSearch": { "index": 61, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Search query for organizations",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_SEARCH" }
+ "CamelKeycloakToken": { "index": 50, "kind": "header", "displayName": "",
"group": "common", "label": "", "required": false, "javaType": "String",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The token for revocation or introspection",
"constantName": "org.apache.camel.component.keycloak.KeycloakConstants#TOKEN" },
+ "CamelKeycloakTokenTypeHint": { "index": 51, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The token type hint for revocation",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#TOKEN_TYPE_HINT" },
+ "CamelKeycloakPermissionResourceNames": { "index": 52, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Comma-separated list of resource names
or IDs to evaluate permissions for", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#PERMISSION_RESOURCE_NAMES"
},
+ "CamelKeycloakPermissionScopes": { "index": 53, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Comma-separated list of scopes to
evaluate permissions for", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#PERMISSION_SCOPES" },
+ "CamelKeycloakSubjectToken": { "index": 54, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Subject token for permission evaluation
on behalf of a user", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#SUBJECT_TOKEN" },
+ "CamelKeycloakPermissionAudience": { "index": 55, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Audience for permission evaluation",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#PERMISSION_AUDIENCE" },
+ "CamelKeycloakPermissionsOnly": { "index": 56, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Whether to only return the list of
permissions without obtaining an RPT", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#PERMISSIONS_ONLY" },
+ "CamelKeycloakOrganizationId": { "index": 57, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization ID", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_ID" },
+ "CamelKeycloakOrganizationName": { "index": 58, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization name", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_NAME" },
+ "CamelKeycloakOrganizationAlias": { "index": 59, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization alias",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_ALIAS" },
+ "CamelKeycloakOrganizationDescription": { "index": 60, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization description",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_DESCRIPTION"
},
+ "CamelKeycloakOrganizationRedirectUrl": { "index": 61, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization redirect URL",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_REDIRECT_URL"
},
+ "CamelKeycloakOrganizationDomain": { "index": 62, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization domain name",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_DOMAIN" },
+ "CamelKeycloakOrganizationSearch": { "index": 63, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Search query for organizations",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_SEARCH" }
},
"properties": {
"label": { "index": 0, "kind": "path", "displayName": "Label", "group":
"common", "label": "", "required": true, "type": "string", "javaType":
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Logical name" },
@@ -142,7 +144,7 @@
"ipAddress": { "index": 16, "kind": "parameter", "displayName": "Ip
Address", "group": "common", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Filter events by IP
address" },
"keycloakClient": { "index": 17, "kind": "parameter", "displayName":
"Keycloak Client", "group": "common", "label": "", "required": false, "type":
"object", "javaType": "org.keycloak.admin.client.Keycloak", "deprecated":
false, "deprecationNote": "", "autowired": true, "secret": false,
"configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "To use an existing
configured Keycloak admin client" },
"maxResults": { "index": 18, "kind": "parameter", "displayName": "Max
Results", "group": "common", "label": "", "required": false, "type": "integer",
"javaType": "int", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": 100, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Maximum number of events
to retrieve per poll" },
- "operation": { "index": 19, "kind": "parameter", "displayName":
"Operation", "group": "common", "label": "", "required": false, "type": "enum",
"javaType": "org.apache.camel.component.keycloak.KeycloakOperations", "enum": [
"createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser",
"deleteUser", "getUser", "updateUser", "listUsers", "searchUsers",
"createRole", "deleteRole", "getRole", "updateRole", "listRoles",
"assignRoleToUser", "removeRoleFromUser", "getUserRoles", "c [...]
+ "operation": { "index": 19, "kind": "parameter", "displayName":
"Operation", "group": "common", "label": "", "required": false, "type": "enum",
"javaType": "org.apache.camel.component.keycloak.KeycloakOperations", "enum": [
"createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser",
"deleteUser", "getUser", "updateUser", "listUsers", "searchUsers",
"createRole", "deleteRole", "getRole", "updateRole", "listRoles",
"assignRoleToUser", "removeRoleFromUser", "getUserRoles", "c [...]
"operationTypes": { "index": 20, "kind": "parameter", "displayName":
"Operation Types", "group": "common", "label": "", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": false, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Filter admin events by
operation types (comma-separated list, e.g., CREATE,UPDATE,DELETE)" },
"password": { "index": 21, "kind": "parameter", "displayName": "Password",
"group": "common", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": true, "security": "secret", "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Keycloak password" },
"pojoRequest": { "index": 22, "kind": "parameter", "displayName": "Pojo
Request", "group": "common", "label": "", "required": false, "type": "boolean",
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "If we want to use a POJO
request as body or not" },
diff --git
a/components/camel-keycloak/src/generated/resources/META-INF/org/apache/camel/component/keycloak/keycloak.json
b/components/camel-keycloak/src/generated/resources/META-INF/org/apache/camel/component/keycloak/keycloak.json
index 692f286998c7..34d0c275362f 100644
---
a/components/camel-keycloak/src/generated/resources/META-INF/org/apache/camel/component/keycloak/keycloak.json
+++
b/components/camel-keycloak/src/generated/resources/META-INF/org/apache/camel/component/keycloak/keycloak.json
@@ -43,7 +43,7 @@
"ipAddress": { "index": 16, "kind": "property", "displayName": "Ip
Address", "group": "common", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Filter events by IP
address" },
"keycloakClient": { "index": 17, "kind": "property", "displayName":
"Keycloak Client", "group": "common", "label": "", "required": false, "type":
"object", "javaType": "org.keycloak.admin.client.Keycloak", "deprecated":
false, "deprecationNote": "", "autowired": true, "secret": false,
"configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "To use an existing
configured Keycloak admin client" },
"maxResults": { "index": 18, "kind": "property", "displayName": "Max
Results", "group": "common", "label": "", "required": false, "type": "integer",
"javaType": "int", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": 100, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Maximum number of events
to retrieve per poll" },
- "operation": { "index": 19, "kind": "property", "displayName":
"Operation", "group": "common", "label": "", "required": false, "type": "enum",
"javaType": "org.apache.camel.component.keycloak.KeycloakOperations", "enum": [
"createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser",
"deleteUser", "getUser", "updateUser", "listUsers", "searchUsers",
"createRole", "deleteRole", "getRole", "updateRole", "listRoles",
"assignRoleToUser", "removeRoleFromUser", "getUserRoles", "cr [...]
+ "operation": { "index": 19, "kind": "property", "displayName":
"Operation", "group": "common", "label": "", "required": false, "type": "enum",
"javaType": "org.apache.camel.component.keycloak.KeycloakOperations", "enum": [
"createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser",
"deleteUser", "getUser", "updateUser", "listUsers", "searchUsers",
"createRole", "deleteRole", "getRole", "updateRole", "listRoles",
"assignRoleToUser", "removeRoleFromUser", "getUserRoles", "cr [...]
"operationTypes": { "index": 20, "kind": "property", "displayName":
"Operation Types", "group": "common", "label": "", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": false, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Filter admin events by
operation types (comma-separated list, e.g., CREATE,UPDATE,DELETE)" },
"password": { "index": 21, "kind": "property", "displayName": "Password",
"group": "common", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": true, "security": "secret", "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Keycloak password" },
"pojoRequest": { "index": 22, "kind": "property", "displayName": "Pojo
Request", "group": "common", "label": "", "required": false, "type": "boolean",
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "If we want to use a POJO
request as body or not" },
@@ -59,7 +59,7 @@
"autowiredEnabled": { "index": 32, "kind": "property", "displayName":
"Autowired Enabled", "group": "advanced", "label": "advanced", "required":
false, "type": "boolean", "javaType": "boolean", "deprecated": false,
"autowired": false, "secret": false, "defaultValue": true, "description":
"Whether autowiring is enabled. This is used for automatic autowiring options
(the option must be marked as autowired) by looking up in the registry to find
if there is a single instance of matching [...]
},
"headers": {
- "CamelKeycloakOperation": { "index": 0, "kind": "header", "displayName":
"", "group": "common", "label": "", "required": false, "javaType":
"org.apache.camel.component.keycloak.KeycloakOperations", "enum": [
"createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser",
"deleteUser", "getUser", "updateUser", "listUsers", "searchUsers",
"createRole", "deleteRole", "getRole", "updateRole", "listRoles",
"assignRoleToUser", "removeRoleFromUser", "getUserRoles", "createGroup", "de
[...]
+ "CamelKeycloakOperation": { "index": 0, "kind": "header", "displayName":
"", "group": "common", "label": "", "required": false, "javaType":
"org.apache.camel.component.keycloak.KeycloakOperations", "enum": [
"createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser",
"deleteUser", "getUser", "updateUser", "listUsers", "searchUsers",
"createRole", "deleteRole", "getRole", "updateRole", "listRoles",
"assignRoleToUser", "removeRoleFromUser", "getUserRoles", "createGroup", "de
[...]
"CamelKeycloakRealmName": { "index": 1, "kind": "header", "displayName":
"", "group": "common", "label": "", "required": false, "javaType": "String",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The realm name", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#REALM_NAME" },
"CamelKeycloakUserId": { "index": 2, "kind": "header", "displayName": "",
"group": "common", "label": "", "required": false, "javaType": "String",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The user ID", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#USER_ID" },
"CamelKeycloakUsername": { "index": 3, "kind": "header", "displayName":
"", "group": "common", "label": "", "required": false, "javaType": "String",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The username", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#USERNAME" },
@@ -109,18 +109,20 @@
"CamelKeycloakContinueOnError": { "index": 47, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Continue on error during bulk
operations", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#CONTINUE_ON_ERROR" },
"CamelKeycloakBatchSize": { "index": 48, "kind": "header", "displayName":
"", "group": "common", "label": "", "required": false, "javaType": "Integer",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "Batch size for bulk operations", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#BATCH_SIZE" },
"CamelKeycloakAccessToken": { "index": 49, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The access token for permission
evaluation", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ACCESS_TOKEN" },
- "CamelKeycloakPermissionResourceNames": { "index": 50, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Comma-separated list of resource names
or IDs to evaluate permissions for", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#PERMISSION_RESOURCE_NAMES"
},
- "CamelKeycloakPermissionScopes": { "index": 51, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Comma-separated list of scopes to
evaluate permissions for", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#PERMISSION_SCOPES" },
- "CamelKeycloakSubjectToken": { "index": 52, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Subject token for permission evaluation
on behalf of a user", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#SUBJECT_TOKEN" },
- "CamelKeycloakPermissionAudience": { "index": 53, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Audience for permission evaluation",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#PERMISSION_AUDIENCE" },
- "CamelKeycloakPermissionsOnly": { "index": 54, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Whether to only return the list of
permissions without obtaining an RPT", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#PERMISSIONS_ONLY" },
- "CamelKeycloakOrganizationId": { "index": 55, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization ID", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_ID" },
- "CamelKeycloakOrganizationName": { "index": 56, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization name", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_NAME" },
- "CamelKeycloakOrganizationAlias": { "index": 57, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization alias",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_ALIAS" },
- "CamelKeycloakOrganizationDescription": { "index": 58, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization description",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_DESCRIPTION"
},
- "CamelKeycloakOrganizationRedirectUrl": { "index": 59, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization redirect URL",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_REDIRECT_URL"
},
- "CamelKeycloakOrganizationDomain": { "index": 60, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization domain name",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_DOMAIN" },
- "CamelKeycloakOrganizationSearch": { "index": 61, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Search query for organizations",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_SEARCH" }
+ "CamelKeycloakToken": { "index": 50, "kind": "header", "displayName": "",
"group": "common", "label": "", "required": false, "javaType": "String",
"deprecated": false, "deprecationNote": "", "autowired": false, "secret":
false, "description": "The token for revocation or introspection",
"constantName": "org.apache.camel.component.keycloak.KeycloakConstants#TOKEN" },
+ "CamelKeycloakTokenTypeHint": { "index": 51, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The token type hint for revocation",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#TOKEN_TYPE_HINT" },
+ "CamelKeycloakPermissionResourceNames": { "index": 52, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Comma-separated list of resource names
or IDs to evaluate permissions for", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#PERMISSION_RESOURCE_NAMES"
},
+ "CamelKeycloakPermissionScopes": { "index": 53, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Comma-separated list of scopes to
evaluate permissions for", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#PERMISSION_SCOPES" },
+ "CamelKeycloakSubjectToken": { "index": 54, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Subject token for permission evaluation
on behalf of a user", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#SUBJECT_TOKEN" },
+ "CamelKeycloakPermissionAudience": { "index": 55, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Audience for permission evaluation",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#PERMISSION_AUDIENCE" },
+ "CamelKeycloakPermissionsOnly": { "index": 56, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "Boolean", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Whether to only return the list of
permissions without obtaining an RPT", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#PERMISSIONS_ONLY" },
+ "CamelKeycloakOrganizationId": { "index": 57, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization ID", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_ID" },
+ "CamelKeycloakOrganizationName": { "index": 58, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization name", "constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_NAME" },
+ "CamelKeycloakOrganizationAlias": { "index": 59, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization alias",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_ALIAS" },
+ "CamelKeycloakOrganizationDescription": { "index": 60, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization description",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_DESCRIPTION"
},
+ "CamelKeycloakOrganizationRedirectUrl": { "index": 61, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization redirect URL",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_REDIRECT_URL"
},
+ "CamelKeycloakOrganizationDomain": { "index": 62, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "The organization domain name",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_DOMAIN" },
+ "CamelKeycloakOrganizationSearch": { "index": 63, "kind": "header",
"displayName": "", "group": "common", "label": "", "required": false,
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "description": "Search query for organizations",
"constantName":
"org.apache.camel.component.keycloak.KeycloakConstants#ORGANIZATION_SEARCH" }
},
"properties": {
"label": { "index": 0, "kind": "path", "displayName": "Label", "group":
"common", "label": "", "required": true, "type": "string", "javaType":
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired":
false, "secret": false, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Logical name" },
@@ -142,7 +144,7 @@
"ipAddress": { "index": 16, "kind": "parameter", "displayName": "Ip
Address", "group": "common", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": false, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Filter events by IP
address" },
"keycloakClient": { "index": 17, "kind": "parameter", "displayName":
"Keycloak Client", "group": "common", "label": "", "required": false, "type":
"object", "javaType": "org.keycloak.admin.client.Keycloak", "deprecated":
false, "deprecationNote": "", "autowired": true, "secret": false,
"configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "To use an existing
configured Keycloak admin client" },
"maxResults": { "index": 18, "kind": "parameter", "displayName": "Max
Results", "group": "common", "label": "", "required": false, "type": "integer",
"javaType": "int", "deprecated": false, "autowired": false, "secret": false,
"defaultValue": 100, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Maximum number of events
to retrieve per poll" },
- "operation": { "index": 19, "kind": "parameter", "displayName":
"Operation", "group": "common", "label": "", "required": false, "type": "enum",
"javaType": "org.apache.camel.component.keycloak.KeycloakOperations", "enum": [
"createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser",
"deleteUser", "getUser", "updateUser", "listUsers", "searchUsers",
"createRole", "deleteRole", "getRole", "updateRole", "listRoles",
"assignRoleToUser", "removeRoleFromUser", "getUserRoles", "c [...]
+ "operation": { "index": 19, "kind": "parameter", "displayName":
"Operation", "group": "common", "label": "", "required": false, "type": "enum",
"javaType": "org.apache.camel.component.keycloak.KeycloakOperations", "enum": [
"createRealm", "deleteRealm", "getRealm", "updateRealm", "createUser",
"deleteUser", "getUser", "updateUser", "listUsers", "searchUsers",
"createRole", "deleteRole", "getRole", "updateRole", "listRoles",
"assignRoleToUser", "removeRoleFromUser", "getUserRoles", "c [...]
"operationTypes": { "index": 20, "kind": "parameter", "displayName":
"Operation Types", "group": "common", "label": "", "required": false, "type":
"string", "javaType": "java.lang.String", "deprecated": false, "autowired":
false, "secret": false, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Filter admin events by
operation types (comma-separated list, e.g., CREATE,UPDATE,DELETE)" },
"password": { "index": 21, "kind": "parameter", "displayName": "Password",
"group": "common", "label": "", "required": false, "type": "string",
"javaType": "java.lang.String", "deprecated": false, "autowired": false,
"secret": true, "security": "secret", "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "Keycloak password" },
"pojoRequest": { "index": 22, "kind": "parameter", "displayName": "Pojo
Request", "group": "common", "label": "", "required": false, "type": "boolean",
"javaType": "boolean", "deprecated": false, "autowired": false, "secret":
false, "defaultValue": false, "configurationClass":
"org.apache.camel.component.keycloak.KeycloakConfiguration",
"configurationField": "configuration", "description": "If we want to use a POJO
request as body or not" },
diff --git a/components/camel-keycloak/src/main/docs/keycloak-component.adoc
b/components/camel-keycloak/src/main/docs/keycloak-component.adoc
index 72de959a747d..3bba59b931de 100644
--- a/components/camel-keycloak/src/main/docs/keycloak-component.adoc
+++ b/components/camel-keycloak/src/main/docs/keycloak-component.adoc
@@ -156,7 +156,8 @@ The component supports the following operations:
* **Client Secret Management**: `getClientSecret`, `regenerateClientSecret`
* **Client Role Management**: `createClientRole`, `getClientRole`,
`updateClientRole`, `listClientRoles`, `deleteClientRole`,
`assignClientRoleToUser`, `removeClientRoleFromUser`
* **Password Management**: `resetUserPassword`
-* **Session Management**: `listUserSessions`, `logoutUser`
+* **Session Management**: `listUserSessions`, `logoutUser`, `logoutAllUsers`
+* **Token Management**: `revokeAccessToken`, `revokeRefreshToken`,
`introspectToken`, `pushNotBefore`
* **Client Scope Management**: `createClientScope`, `getClientScope`,
`updateClientScope`, `listClientScopes`, `deleteClientScope`
* **Identity Provider Management**: `createIdentityProvider`,
`getIdentityProvider`, `updateIdentityProvider`, `listIdentityProviders`,
`deleteIdentityProvider`
* **Authorization Services**: `createResource`, `getResource`,
`updateResource`, `listResources`, `deleteResource`, `createResourcePolicy`,
`getResourcePolicy`, `updateResourcePolicy`, `listResourcePolicies`,
`deleteResourcePolicy`, `createResourcePermission`, `getResourcePermission`,
`updateResourcePermission`, `listResourcePermissions`,
`deleteResourcePermission`, `evaluatePermission`
@@ -970,6 +971,10 @@ logoutHeaders.put(KeycloakConstants.REALM_NAME,
"my-realm");
logoutHeaders.put(KeycloakConstants.USER_ID, "user-id-123");
template.sendBodyAndHeaders("keycloak:admin?operation=logoutUser", null,
logoutHeaders);
+
+// Logout all users in realm
+template.sendBodyAndHeader("keycloak:admin?operation=logoutAllUsers", null,
+ KeycloakConstants.REALM_NAME, "my-realm");
----
YAML::
@@ -1015,6 +1020,102 @@ YAML::
operation: logoutUser
- log:
message: "User logged out: ${header.CamelKeycloakUserId}"
+
+# Logout all users route
+- route:
+ from:
+ uri: direct:logout-all
+ steps:
+ - setHeader:
+ name: CamelKeycloakRealmName
+ constant: "my-realm"
+ - to:
+ uri: keycloak:admin
+ parameters:
+ operation: logoutAllUsers
+----
+====
+
+=== Token Management Operations
+
+Token management operations allow you to revoke specific tokens or introspect
them for real-time validation.
+
+[tabs]
+====
+Java::
++
+[source,java]
+----
+// Revoke an access token
+Map<String, Object> revokeHeaders = new HashMap<>();
+revokeHeaders.put(KeycloakConstants.REALM_NAME, "my-realm");
+revokeHeaders.put(KeycloakConstants.TOKEN, accessToken);
+
+template.sendBodyAndHeaders("keycloak:admin?operation=revokeAccessToken",
null, revokeHeaders);
+
+// Introspect a token
+Map<String, Object> introspectHeaders = new HashMap<>();
+introspectHeaders.put(KeycloakConstants.REALM_NAME, "my-realm");
+introspectHeaders.put(KeycloakConstants.TOKEN, tokenToVerify);
+
+Map<String, Object> claims =
template.requestBodyAndHeaders("keycloak:admin?operation=introspectToken",
+ null, introspectHeaders, Map.class);
+
+// Push not-before policy (invalidates all tokens issued before now)
+template.sendBodyAndHeader("keycloak:admin?operation=pushNotBefore", null,
+ KeycloakConstants.REALM_NAME, "my-realm");
+----
+
+YAML::
++
+[source,yaml]
+----
+# Revoke token route
+- route:
+ from:
+ uri: direct:revoke-token
+ steps:
+ - setHeader:
+ name: CamelKeycloakRealmName
+ constant: "my-realm"
+ - setHeader:
+ name: CamelKeycloakToken
+ simple: "${body}"
+ - to:
+ uri: keycloak:admin
+ parameters:
+ operation: revokeAccessToken
+
+# Introspect token route
+- route:
+ from:
+ uri: direct:introspect
+ steps:
+ - setHeader:
+ name: CamelKeycloakRealmName
+ constant: "my-realm"
+ - setHeader:
+ name: CamelKeycloakToken
+ simple: "${body}"
+ - to:
+ uri: keycloak:admin
+ parameters:
+ operation: introspectToken
+ - log:
+ message: "Token claims: ${body}"
+
+# Push not-before route
+- route:
+ from:
+ uri: direct:push-not-before
+ steps:
+ - setHeader:
+ name: CamelKeycloakRealmName
+ constant: "my-realm"
+ - to:
+ uri: keycloak:admin
+ parameters:
+ operation: pushNotBefore
----
====
diff --git
a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakConstants.java
b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakConstants.java
index 1f5399780fa8..34814ac14915 100644
---
a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakConstants.java
+++
b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakConstants.java
@@ -178,6 +178,12 @@ public final class KeycloakConstants {
@Metadata(description = "The access token for permission evaluation",
javaType = "String")
public static final String ACCESS_TOKEN = "CamelKeycloakAccessToken";
+ @Metadata(description = "The token for revocation or introspection",
javaType = "String")
+ public static final String TOKEN = "CamelKeycloakToken";
+
+ @Metadata(description = "The token type hint for revocation", javaType =
"String")
+ public static final String TOKEN_TYPE_HINT = "CamelKeycloakTokenTypeHint";
+
@Metadata(description = "Comma-separated list of resource names or IDs to
evaluate permissions for", javaType = "String")
public static final String PERMISSION_RESOURCE_NAMES =
"CamelKeycloakPermissionResourceNames";
diff --git
a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakOperations.java
b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakOperations.java
index 7bddf4a57569..1c5317c5d345 100644
---
a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakOperations.java
+++
b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakOperations.java
@@ -64,6 +64,12 @@ public enum KeycloakOperations {
// User session operations
listUserSessions,
logoutUser,
+ logoutAllUsers,
+ // Token operations
+ revokeAccessToken,
+ revokeRefreshToken,
+ introspectToken,
+ pushNotBefore,
// Client scope operations
createClientScope,
deleteClientScope,
diff --git
a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakProducer.java
b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakProducer.java
index 50ab83d3617b..88dfc5251094 100644
---
a/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakProducer.java
+++
b/components/camel-keycloak/src/main/java/org/apache/camel/component/keycloak/KeycloakProducer.java
@@ -18,6 +18,7 @@ package org.apache.camel.component.keycloak;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -28,10 +29,17 @@ import org.apache.camel.Endpoint;
import org.apache.camel.Exchange;
import org.apache.camel.InvalidPayloadException;
import org.apache.camel.Message;
+import org.apache.camel.component.keycloak.security.KeycloakTokenIntrospector;
import org.apache.camel.support.DefaultProducer;
import org.apache.camel.util.CastUtils;
import org.apache.camel.util.ObjectHelper;
import org.apache.camel.util.URISupport;
+import org.apache.hc.client5.http.classic.methods.HttpPost;
+import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.HttpClients;
+import org.apache.hc.core5.http.NameValuePair;
+import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.authorization.client.AuthzClient;
import org.keycloak.authorization.client.Configuration;
@@ -212,6 +220,21 @@ public class KeycloakProducer extends DefaultProducer {
case logoutUser:
logoutUser(getEndpoint().getKeycloakClient(), exchange);
break;
+ case logoutAllUsers:
+ logoutAllUsers(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case revokeAccessToken:
+ revokeAccessToken(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case revokeRefreshToken:
+ revokeRefreshToken(getEndpoint().getKeycloakClient(),
exchange);
+ break;
+ case introspectToken:
+ introspectToken(getEndpoint().getKeycloakClient(), exchange);
+ break;
+ case pushNotBefore:
+ pushNotBefore(getEndpoint().getKeycloakClient(), exchange);
+ break;
case createClientScope:
createClientScope(getEndpoint().getKeycloakClient(), exchange);
break;
@@ -1247,6 +1270,124 @@ public class KeycloakProducer extends DefaultProducer {
message.setBody("User logged out successfully");
}
+ private void logoutAllUsers(Keycloak keycloakClient, Exchange exchange) {
+ String realmName =
exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ keycloakClient.realm(realmName).logoutAll();
+ Message message = getMessageForResponse(exchange);
+ message.setBody("All users logged out successfully");
+ }
+
+ private void revokeAccessToken(Keycloak keycloakClient, Exchange exchange)
throws Exception {
+ revokeToken(exchange, "access_token");
+ }
+
+ private void revokeRefreshToken(Keycloak keycloakClient, Exchange
exchange) throws Exception {
+ revokeToken(exchange, "refresh_token");
+ }
+
+ private void revokeToken(Exchange exchange, String defaultTypeHint) throws
Exception {
+ String realmName =
exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ realmName = getConfiguration().getRealm();
+ }
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ String token = exchange.getIn().getHeader(KeycloakConstants.TOKEN,
String.class);
+ if (ObjectHelper.isEmpty(token)) {
+ token = exchange.getIn().getBody(String.class);
+ }
+ if (ObjectHelper.isEmpty(token)) {
+ throw new IllegalArgumentException("Token must be specified for
revocation");
+ }
+
+ String typeHint =
exchange.getIn().getHeader(KeycloakConstants.TOKEN_TYPE_HINT, String.class);
+ if (ObjectHelper.isEmpty(typeHint)) {
+ typeHint = defaultTypeHint;
+ }
+
+ String serverUrl = getConfiguration().getServerUrl();
+ String clientId = getConfiguration().getClientId();
+ String clientSecret = getConfiguration().getClientSecret();
+
+ String revocationUrl =
String.format("%s/realms/%s/protocol/openid-connect/revoke", serverUrl,
realmName);
+
+ try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+ HttpPost request = new HttpPost(revocationUrl);
+
+ // Add Basic authentication header
+ String auth = clientId + ":" + clientSecret;
+ String encodedAuth =
Base64.getEncoder().encodeToString(auth.getBytes());
+ request.setHeader("Authorization", "Basic " + encodedAuth);
+ request.setHeader("Content-Type",
"application/x-www-form-urlencoded");
+
+ List<NameValuePair> params = new ArrayList<>();
+ params.add(new BasicNameValuePair("token", token));
+ params.add(new BasicNameValuePair("token_type_hint", typeHint));
+ request.setEntity(new UrlEncodedFormEntity(params));
+
+ httpClient.execute(request, response -> {
+ int statusCode = response.getCode();
+ if (statusCode != 200) {
+ throw new RuntimeException("Token revocation failed with
status " + statusCode);
+ }
+ return null;
+ });
+ }
+
+ Message message = getMessageForResponse(exchange);
+ message.setBody("Token revoked successfully");
+ }
+
+ private void introspectToken(Keycloak keycloakClient, Exchange exchange)
throws Exception {
+ String realmName =
exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ realmName = getConfiguration().getRealm();
+ }
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ String token = exchange.getIn().getHeader(KeycloakConstants.TOKEN,
String.class);
+ if (ObjectHelper.isEmpty(token)) {
+ token = exchange.getIn().getBody(String.class);
+ }
+ if (ObjectHelper.isEmpty(token)) {
+ throw new IllegalArgumentException("Token must be specified for
introspection");
+ }
+
+ KeycloakTokenIntrospector introspector = new KeycloakTokenIntrospector(
+ getConfiguration().getServerUrl(),
+ realmName,
+ getConfiguration().getClientId(),
+ getConfiguration().getClientSecret(),
+ false, 0);
+
+ try {
+ KeycloakTokenIntrospector.IntrospectionResult result =
introspector.introspect(token);
+ Message message = getMessageForResponse(exchange);
+ message.setBody(result.getAllClaims());
+ } finally {
+ introspector.close();
+ }
+ }
+
+ private void pushNotBefore(Keycloak keycloakClient, Exchange exchange) {
+ String realmName =
exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
+ if (ObjectHelper.isEmpty(realmName)) {
+ throw new IllegalArgumentException(MISSING_REALM_NAME);
+ }
+
+ keycloakClient.realm(realmName).pushRevocation();
+ Message message = getMessageForResponse(exchange);
+ message.setBody("Not-before policy pushed successfully");
+ }
+
private void createClientScope(Keycloak keycloakClient, Exchange exchange)
throws InvalidPayloadException {
String realmName =
exchange.getIn().getHeader(KeycloakConstants.REALM_NAME, String.class);
if (ObjectHelper.isEmpty(realmName)) {
diff --git
a/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakProducerRevocationIT.java
b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakProducerRevocationIT.java
new file mode 100644
index 000000000000..a495d37b7816
--- /dev/null
+++
b/components/camel-keycloak/src/test/java/org/apache/camel/component/keycloak/KeycloakProducerRevocationIT.java
@@ -0,0 +1,279 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.keycloak;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.infra.keycloak.services.KeycloakService;
+import org.apache.camel.test.infra.keycloak.services.KeycloakServiceFactory;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.keycloak.admin.client.Keycloak;
+import org.keycloak.admin.client.KeycloakBuilder;
+import org.keycloak.admin.client.resource.ClientResource;
+import org.keycloak.admin.client.resource.RealmResource;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.idm.CredentialRepresentation;
+import org.keycloak.representations.idm.ProtocolMapperRepresentation;
+import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.representations.idm.UserRepresentation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class KeycloakProducerRevocationIT extends CamelTestSupport {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(KeycloakProducerRevocationIT.class);
+
+ @RegisterExtension
+ static KeycloakService keycloakService =
KeycloakServiceFactory.createService();
+
+ private static final String TEST_REALM_NAME = "revocation-realm-" +
UUID.randomUUID().toString().substring(0, 8);
+ private static final String TEST_CLIENT_ID = "revocation-client-" +
UUID.randomUUID().toString().substring(0, 8);
+ private static String TEST_CLIENT_SECRET;
+
+ private static final String TEST_USER = "test-user-" +
UUID.randomUUID().toString().substring(0, 8);
+ private static final String TEST_PASSWORD = "password123";
+
+ private static Keycloak keycloakAdminClient;
+ private static RealmResource realmResource;
+
+ @BeforeAll
+ static void setupKeycloak() {
+ keycloakAdminClient = KeycloakBuilder.builder()
+ .serverUrl(keycloakService.getKeycloakServerUrl())
+ .realm(keycloakService.getKeycloakRealm())
+ .username(keycloakService.getKeycloakUsername())
+ .password(keycloakService.getKeycloakPassword())
+ .clientId("admin-cli")
+ .build();
+
+ // Create realm
+ RealmRepresentation realm = new RealmRepresentation();
+ realm.setId(TEST_REALM_NAME);
+ realm.setRealm(TEST_REALM_NAME);
+ realm.setDisplayName("Revocation Test Realm");
+ realm.setEnabled(true);
+ realm.setAccessTokenLifespan(3600);
+ keycloakAdminClient.realms().create(realm);
+ realmResource = keycloakAdminClient.realm(TEST_REALM_NAME);
+
+ // Create client
+ ClientRepresentation client = new ClientRepresentation();
+ client.setClientId(TEST_CLIENT_ID);
+ client.setPublicClient(false);
+ client.setDirectAccessGrantsEnabled(true);
+ client.setEnabled(true);
+ client.setServiceAccountsEnabled(true);
+ try (Response response = realmResource.clients().create(client)) {
+ assertEquals(201, response.getStatus(), "Failed to create client");
+ String location = response.getHeaderString("Location");
+ String clientUuid = location.substring(location.lastIndexOf('/') +
1);
+ ClientResource clientResource =
realmResource.clients().get(clientUuid);
+ TEST_CLIENT_SECRET = clientResource.getSecret().getValue();
+
+ // Add audience mapper to include this client in the token audience
+ // This is required for Keycloak token introspection
+ ProtocolMapperRepresentation audienceMapper = new
ProtocolMapperRepresentation();
+ audienceMapper.setName("audience-mapper");
+ audienceMapper.setProtocol("openid-connect");
+ audienceMapper.setProtocolMapper("oidc-audience-mapper");
+ Map<String, String> config = new HashMap<>();
+ config.put("included.client.audience", TEST_CLIENT_ID);
+ config.put("access.token.claim", "true");
+ config.put("id.token.claim", "false");
+ audienceMapper.setConfig(config);
+ clientResource.getProtocolMappers().createMapper(audienceMapper);
+
+ // Assign realm-management roles to the client service account
+ UserRepresentation serviceAccount =
clientResource.getServiceAccountUser();
+ String realmManagementId =
realmResource.clients().findByClientId("realm-management").get(0).getId();
+
+
realmResource.users().get(serviceAccount.getId()).roles().clientLevel(realmManagementId)
+
.add(realmResource.clients().get(realmManagementId).roles().list().stream()
+ .filter(r -> r.getName().equals("manage-realm") ||
r.getName().equals("manage-users"))
+ .collect(java.util.stream.Collectors.toList()));
+ }
+ // Create user
+ UserRepresentation user = new UserRepresentation();
+ user.setUsername(TEST_USER);
+ user.setFirstName("Test");
+ user.setLastName("User");
+ user.setEmail(TEST_USER + "@test.com");
+ user.setEnabled(true);
+ user.setEmailVerified(true);
+ user.setRequiredActions(java.util.Collections.emptyList());
+ CredentialRepresentation cred = new CredentialRepresentation();
+ cred.setType(CredentialRepresentation.PASSWORD);
+ cred.setValue(TEST_PASSWORD);
+ cred.setTemporary(false);
+ user.setCredentials(Arrays.asList(cred));
+ try (Response response = realmResource.users().create(user)) {
+ assertEquals(201, response.getStatus(), "Failed to create user");
+ }
+ }
+
+ @AfterAll
+ static void cleanup() {
+ if (keycloakAdminClient != null) {
+ try {
+ keycloakAdminClient.realm(TEST_REALM_NAME).remove();
+ } catch (Exception e) {
+ // ignore
+ } finally {
+ keycloakAdminClient.close();
+ }
+ }
+ }
+
+ @Override
+ protected RoutesBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ String endpoint =
String.format("keycloak:admin?serverUrl=%s&realm=%s&clientId=%s&clientSecret=%s",
+ keycloakService.getKeycloakServerUrl(),
TEST_REALM_NAME, TEST_CLIENT_ID, TEST_CLIENT_SECRET);
+
+ from("direct:introspect")
+ .to(endpoint + "&operation=introspectToken");
+
+ from("direct:revoke")
+ .to(endpoint + "&operation=revokeAccessToken");
+
+ from("direct:logoutAll")
+ .to(endpoint + "&operation=logoutAllUsers");
+
+ from("direct:pushNotBefore")
+ .to(endpoint + "&operation=pushNotBefore");
+ }
+ };
+ }
+
+ @Test
+ @Order(1)
+ void testIntrospectToken() {
+ String token = getAccessToken();
+ assertNotNull(token);
+
+ Map<String, Object> headers = new HashMap<>();
+ headers.put(KeycloakConstants.TOKEN, token);
+
+ Map<String, Object> claims =
template.requestBodyAndHeaders("direct:introspect", null, headers, Map.class);
+ assertNotNull(claims);
+ assertEquals(Boolean.TRUE, claims.get("active"));
+ assertEquals(TEST_USER, claims.get("preferred_username"));
+ }
+
+ @Test
+ @Order(2)
+ void testRevokeToken() {
+ String token = getAccessToken();
+
+ // 1. Verify token is active
+ Map<String, Object> headers = new HashMap<>();
+ headers.put(KeycloakConstants.TOKEN, token);
+ Map<String, Object> claims =
template.requestBodyAndHeaders("direct:introspect", null, headers, Map.class);
+ assertEquals(Boolean.TRUE, claims.get("active"));
+
+ // 2. Revoke token
+ template.sendBodyAndHeaders("direct:revoke", null, headers);
+
+ // 3. Verify token is NO LONGER active
+ claims = template.requestBodyAndHeaders("direct:introspect", null,
headers, Map.class);
+ assertEquals(Boolean.FALSE, claims.get("active"));
+ }
+
+ @Test
+ @Order(3)
+ void testLogoutAllUsers() {
+ String token = getAccessToken();
+
+ // 1. Verify token is active
+ Map<String, Object> headers = new HashMap<>();
+ headers.put(KeycloakConstants.TOKEN, token);
+ Map<String, Object> claims =
template.requestBodyAndHeaders("direct:introspect", null, headers, Map.class);
+ assertEquals(Boolean.TRUE, claims.get("active"));
+
+ // 2. Logout all users
+ template.sendBodyAndHeader("direct:logoutAll", null,
KeycloakConstants.REALM_NAME, TEST_REALM_NAME);
+
+ // 3. Verify token is NO LONGER active
+ claims = template.requestBodyAndHeaders("direct:introspect", null,
headers, Map.class);
+ assertEquals(Boolean.FALSE, claims.get("active"));
+ }
+
+ @Test
+ @Order(4)
+ void testPushNotBefore() throws Exception {
+ int initialNotBefore = realmResource.toRepresentation().getNotBefore();
+
+ // 1. Push not-before
+ template.sendBodyAndHeader("direct:pushNotBefore", null,
KeycloakConstants.REALM_NAME, TEST_REALM_NAME);
+
+ // 2. Verify notBefore has increased
+ int updatedNotBefore = realmResource.toRepresentation().getNotBefore();
+ assertTrue(updatedNotBefore >= initialNotBefore);
+ }
+
+ private String getAccessToken() {
+ try (Client client = ClientBuilder.newClient()) {
+ String tokenUrl = keycloakService.getKeycloakServerUrl() +
"/realms/" + TEST_REALM_NAME
+ + "/protocol/openid-connect/token";
+
+ Form form = new Form()
+ .param("grant_type", "password")
+ .param("client_id", TEST_CLIENT_ID)
+ .param("client_secret", TEST_CLIENT_SECRET)
+ .param("username", TEST_USER)
+ .param("password", TEST_PASSWORD);
+
+ try (Response response = client.target(tokenUrl)
+ .request(MediaType.APPLICATION_JSON)
+ .post(Entity.entity(form,
MediaType.APPLICATION_FORM_URLENCODED))) {
+
+ if (response.getStatus() == 200) {
+ Map<String, Object> tokenResponse =
response.readEntity(Map.class);
+ return (String) tokenResponse.get("access_token");
+ } else {
+ LOG.error("Failed to obtain access token. Status: {},
Body: {}",
+ response.getStatus(),
response.readEntity(String.class));
+ return null;
+ }
+ }
+ }
+ }
+}
diff --git
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/KeycloakEndpointBuilderFactory.java
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/KeycloakEndpointBuilderFactory.java
index 025c71d27aaf..96ce4e7d20ed 100644
---
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/KeycloakEndpointBuilderFactory.java
+++
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/KeycloakEndpointBuilderFactory.java
@@ -3126,6 +3126,30 @@ public interface KeycloakEndpointBuilderFactory {
public String keycloakAccessToken() {
return "CamelKeycloakAccessToken";
}
+ /**
+ * The token for revocation or introspection.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: common
+ *
+ * @return the name of the header {@code KeycloakToken}.
+ */
+ public String keycloakToken() {
+ return "CamelKeycloakToken";
+ }
+ /**
+ * The token type hint for revocation.
+ *
+ * The option is a: {@code String} type.
+ *
+ * Group: common
+ *
+ * @return the name of the header {@code KeycloakTokenTypeHint}.
+ */
+ public String keycloakTokenTypeHint() {
+ return "CamelKeycloakTokenTypeHint";
+ }
/**
* Comma-separated list of resource names or IDs to evaluate
permissions
* for.