Keycloak
Since Camel 4.15
Both producer and consumer are supported
The Keycloak component supports running operations on Keycloak instance and policy enforcements.
Component Features
The Keycloak component provides three main functionalities:
-
Producer Operations - Manage Keycloak instances via the Admin API (realms, users, roles, clients, groups, sessions, tokens, and more)
-
Consumer Operations - Poll and consume user events and admin events from Keycloak for monitoring, auditing, and event-driven workflows
-
Security Policies - Route-level authorization using Keycloak authentication and authorization services, including role-based access, permission-based access, and OAuth 2.0 token introspection
URI Format
keycloak://label[?options]
You can append query options to the URI in the following format:
?options=value&option2=value&…
Configuring Options
Camel components are configured on two separate levels:
-
component level
-
endpoint level
Configuring Component Options
At the component level, you set general and shared configurations that are, then, inherited by the endpoints. It is the highest configuration level.
For example, a component may have security settings, credentials for authentication, urls for network connection and so forth.
Some components only have a few options, and others may have many. Because components typically have pre-configured defaults that are commonly used, then you may often only need to configure a few options on a component; or none at all.
You can configure components using:
-
the Component DSL.
-
in a configuration file (
application.properties,*.yamlfiles, etc). -
directly in the Java code.
Configuring Endpoint Options
You usually spend more time setting up endpoints because they have many options. These options help you customize what you want the endpoint to do. The options are also categorized into whether the endpoint is used as a consumer (from), as a producer (to), or both.
Configuring endpoints is most often done directly in the endpoint URI as path and query parameters. You can also use the Endpoint DSL and DataFormat DSL as a type safe way of configuring endpoints and data formats in Java.
A good practice when configuring options is to use Property Placeholders.
Property placeholders provide a few benefits:
-
They help prevent using hardcoded urls, port numbers, sensitive information, and other settings.
-
They allow externalizing the configuration from the code.
-
They help the code to become more flexible and reusable.
The following two sections list all the options, firstly for the component followed by the endpoint.
Component Options
The Keycloak component supports 33 options, which are listed below.
| Name | Description | Default | Type |
|---|---|---|---|
Pre-obtained access token for authentication. When provided, this token will be used directly instead of obtaining one through username/password or client credentials flow. | String | ||
Filter admin events by authentication client ID. | String | ||
Filter admin events by authentication IP address. | String | ||
Keycloak realm to authenticate against. If not specified, the realm parameter is used for authentication. This is useful when you want to authenticate against one realm (e.g., master) but perform operations on another realm. | master | String | |
Filter admin events by authentication realm. | String | ||
Filter admin events by authentication user ID. | String | ||
Filter events by client ID. | String | ||
Keycloak client ID. | String | ||
Keycloak client secret. | String | ||
Component configuration. | KeycloakConfiguration | ||
Filter events by start date/time in milliseconds since epoch. | String | ||
Filter events by end date/time in milliseconds since epoch. | String | ||
Type of events to consume: events or admin-events. | events | String | |
Offset for pagination (first result index). | 0 | int | |
Enable caching of token introspection results to reduce API calls to Keycloak. | true | boolean | |
Time-to-live for cached introspection results in seconds. | 60 | long | |
Filter events by IP address. | String | ||
Autowired To use an existing configured Keycloak admin client. | Keycloak | ||
Maximum number of events to retrieve per poll. | 100 | int | |
The operation to perform. Enum values:
| KeycloakOperations | ||
Filter admin events by operation types (comma-separated list, e.g., CREATE,UPDATE,DELETE). | String | ||
Keycloak password. | String | ||
If we want to use a POJO request as body or not. | false | boolean | |
Keycloak realm, the default is master because usually all the operations are done starting from the master realm. | master | String | |
Filter admin events by resource path. | String | ||
Keycloak server URL. | String | ||
Filter events by event types (comma-separated list, e.g., LOGIN,LOGOUT). | String | ||
Filter events by user ID. | String | ||
Keycloak username. | String | ||
Enable OAuth 2.0 token introspection for real-time token validation. When enabled, tokens are validated by calling Keycloak’s introspection endpoint instead of local JWT parsing. This allows detecting revoked tokens before expiration. | false | boolean | |
Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean | |
Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel’s routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing. | false | boolean | |
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 type, which then gets configured on the component. This can be used for automatic configuring JDBC data sources, JMS connection factories, AWS Clients, etc. | true | boolean |
Endpoint Options
The Keycloak endpoint is configured using URI syntax:
keycloak:label
With the following path and query parameters:
Query Parameters (49 parameters)
| Name | Description | Default | Type |
|---|---|---|---|
Pre-obtained access token for authentication. When provided, this token will be used directly instead of obtaining one through username/password or client credentials flow. | String | ||
Filter admin events by authentication client ID. | String | ||
Filter admin events by authentication IP address. | String | ||
Keycloak realm to authenticate against. If not specified, the realm parameter is used for authentication. This is useful when you want to authenticate against one realm (e.g., master) but perform operations on another realm. | master | String | |
Filter admin events by authentication realm. | String | ||
Filter admin events by authentication user ID. | String | ||
Filter events by client ID. | String | ||
Keycloak client ID. | String | ||
Keycloak client secret. | String | ||
Filter events by start date/time in milliseconds since epoch. | String | ||
Filter events by end date/time in milliseconds since epoch. | String | ||
Type of events to consume: events or admin-events. | events | String | |
Offset for pagination (first result index). | 0 | int | |
Enable caching of token introspection results to reduce API calls to Keycloak. | true | boolean | |
Time-to-live for cached introspection results in seconds. | 60 | long | |
Filter events by IP address. | String | ||
Autowired To use an existing configured Keycloak admin client. | Keycloak | ||
Maximum number of events to retrieve per poll. | 100 | int | |
The operation to perform. Enum values:
| KeycloakOperations | ||
Filter admin events by operation types (comma-separated list, e.g., CREATE,UPDATE,DELETE). | String | ||
Keycloak password. | String | ||
If we want to use a POJO request as body or not. | false | boolean | |
Keycloak realm, the default is master because usually all the operations are done starting from the master realm. | master | String | |
Filter admin events by resource path. | String | ||
Keycloak server URL. | String | ||
Filter events by event types (comma-separated list, e.g., LOGIN,LOGOUT). | String | ||
Filter events by user ID. | String | ||
Keycloak username. | String | ||
Enable OAuth 2.0 token introspection for real-time token validation. When enabled, tokens are validated by calling Keycloak’s introspection endpoint instead of local JWT parsing. This allows detecting revoked tokens before expiration. | false | boolean | |
If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead. | false | boolean | |
Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions (if possible) occurred while the Camel consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. Important: This is only possible if the 3rd party component allows Camel to be alerted if an exception was thrown. Some components handle this internally only, and therefore bridgeErrorHandler is not possible. In other situations we may improve the Camel component to hook into the 3rd party component and make this possible for future releases. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean | |
To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored. | ExceptionHandler | ||
Sets the exchange pattern when the consumer creates an exchange. Enum values:
| ExchangePattern | ||
A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel. | PollingConsumerPollStrategy | ||
Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel’s routing error handlers. Beware that when the first message is processed then creating and starting the producer may take a little time and prolong the total processing time of the processing. | false | boolean | |
The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in. | int | ||
The number of subsequent idle polls that should happen before the backoffMultipler should kick-in. | int | ||
To let the scheduled polling consumer backoff if there has been a number of subsequent idles/errors in a row. The multiplier is then the number of polls that will be skipped before the next actual attempt is happening again. When this option is in use then backoffIdleThreshold and/or backoffErrorThreshold must also be configured. | int | ||
Milliseconds before the next poll. | 500 | long | |
If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the previous run polled 1 or more messages. | false | boolean | |
Milliseconds before the first poll starts. | 1000 | long | |
Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only fire once. If you set it to 5, it will only fire five times. A value of zero or negative means fire forever. | 0 | long | |
The consumer logs a start/complete log line when it polls. This option allows you to configure the logging level for that. Enum values:
| TRACE | LoggingLevel | |
Allows for configuring a custom/shared thread pool to use for the consumer. By default each consumer has its own single threaded thread pool. | ScheduledExecutorService | ||
To use a cron scheduler from either camel-spring or camel-quartz component. Use value spring or quartz for built in scheduler. | none | Object | |
To configure additional properties when using a custom scheduler or any of the Quartz, Spring based scheduler. This is a multi-value option with prefix: scheduler. | Map | ||
Whether the scheduler should be auto started. | true | boolean | |
Time unit for initialDelay and delay options. Enum values:
| MILLISECONDS | TimeUnit | |
Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details. | true | boolean |
Message Headers
The Keycloak component supports 64 message header(s), which is/are listed below:
| Name | Description | Default | Type |
|---|---|---|---|
CamelKeycloakOperation (common) Constant: | The operation to perform. Enum values:
| KeycloakOperations | |
CamelKeycloakRealmName (common) Constant: | The realm name. | String | |
| Constant: | The user ID. | String | |
CamelKeycloakUsername (common) Constant: | The username. | String | |
CamelKeycloakUserEmail (common) Constant: | The user email. | String | |
CamelKeycloakUserFirstName (common) Constant: | The user first name. | String | |
CamelKeycloakUserLastName (common) Constant: | The user last name. | String | |
| Constant: | The role ID. | String | |
CamelKeycloakRoleName (common) Constant: | The role name. | String | |
CamelKeycloakRoleDescription (common) Constant: | The role description. | String | |
| Constant: | The group ID. | String | |
CamelKeycloakGroupName (common) Constant: | The group name. | String | |
CamelKeycloakClientId (common) Constant: | The client ID. | String | |
CamelKeycloakClientUuid (common) Constant: | The client UUID. | String | |
CamelKeycloakUserPassword (common) Constant: | The user password. | String | |
CamelKeycloakPasswordTemporary (common) Constant: | Whether the password is temporary. | Boolean | |
CamelKeycloakSearchQuery (common) Constant: | Search query string. | String | |
CamelKeycloakMaxResults (common) Constant: | Maximum number of results. | Integer | |
CamelKeycloakFirstResult (common) Constant: | First result index. | Integer | |
CamelKeycloakClientScopeId (common) Constant: | The client scope ID. | String | |
CamelKeycloakClientScopeName (common) Constant: | The client scope name. | String | |
CamelKeycloakEventType (common) Constant: | The event type (event or admin-event). | String | |
| Constant: | The event ID or timestamp. | Long | |
CamelKeycloakIdpAlias (common) Constant: | The identity provider alias. | String | |
| Constant: | The identity provider ID. | String | |
CamelKeycloakResourceId (common) Constant: | The resource ID. | String | |
CamelKeycloakResourceName (common) Constant: | The resource name. | String | |
CamelKeycloakResourceType (common) Constant: | The resource type. | String | |
CamelKeycloakResourceUri (common) Constant: | The resource URI. | String | |
CamelKeycloakPolicyId (common) Constant: | The policy ID. | String | |
CamelKeycloakPolicyName (common) Constant: | The policy name. | String | |
CamelKeycloakPolicyType (common) Constant: | The policy type. | String | |
CamelKeycloakPermissionId (common) Constant: | The permission ID. | String | |
CamelKeycloakPermissionName (common) Constant: | The permission name. | String | |
CamelKeycloakScopeName (common) Constant: | The scope name. | String | |
CamelKeycloakAttributeName (common) Constant: | The user attribute name. | String | |
CamelKeycloakAttributeValue (common) Constant: | The user attribute value. | String | |
CamelKeycloakCredentialId (common) Constant: | The credential ID. | String | |
CamelKeycloakCredentialType (common) Constant: | The credential type. | String | |
CamelKeycloakRequiredAction (common) Constant: | The required action type. | String | |
| Constant: | The list of actions to execute. | List | |
CamelKeycloakRedirectUri (common) Constant: | The redirect URI. | String | |
CamelKeycloakLifespan (common) Constant: | The lifespan in seconds. | Integer | |
| Constant: | The list of users for bulk operations. | List | |
| Constant: | The list of user IDs for bulk operations. | List | |
CamelKeycloakUsernames (common) Constant: | The list of usernames for bulk operations. | List | |
CamelKeycloakRoleNames (common) Constant: | The list of role names for bulk operations. | List | |
CamelKeycloakContinueOnError (common) Constant: | Continue on error during bulk operations. | Boolean | |
CamelKeycloakBatchSize (common) Constant: | Batch size for bulk operations. | Integer | |
CamelKeycloakAccessToken (common) Constant: | The access token for permission evaluation. | String | |
| Constant: | The token for revocation or introspection. | String | |
CamelKeycloakTokenTypeHint (common) Constant: | The token type hint for revocation. | String | |
CamelKeycloakPermissionResourceNames (common) Constant: | Comma-separated list of resource names or IDs to evaluate permissions for. | String | |
CamelKeycloakPermissionScopes (common) Constant: | Comma-separated list of scopes to evaluate permissions for. | String | |
CamelKeycloakSubjectToken (common) Constant: | Subject token for permission evaluation on behalf of a user. | String | |
CamelKeycloakPermissionAudience (common) Constant: | Audience for permission evaluation. | String | |
CamelKeycloakPermissionsOnly (common) Constant: | Whether to only return the list of permissions without obtaining an RPT. | Boolean | |
CamelKeycloakOrganizationId (common) Constant: | The organization ID. | String | |
CamelKeycloakOrganizationName (common) Constant: | The organization name. | String | |
CamelKeycloakOrganizationAlias (common) Constant: | The organization alias. | String | |
CamelKeycloakOrganizationDescription (common) Constant: | The organization description. | String | |
CamelKeycloakOrganizationRedirectUrl (common) Constant: | The organization redirect URL. | String | |
CamelKeycloakOrganizationDomain (common) Constant: | The organization domain name. | String | |
CamelKeycloakOrganizationSearch (common) Constant: | Search query for organizations. | String |
Overview
Producer
The producer supports a comprehensive set of administrative operations on Keycloak via the Admin API, including user management, role management, client management, group management, session management, token management, identity providers, organizations, authorization services, and bulk operations.
See Keycloak Producer Operations for the full list of supported operations, configuration details, and examples.
Consumer
The consumer allows you to poll Keycloak for user events (logins, logouts, registrations) and admin events (resource creates, updates, deletes). It supports filtering by event type, operation type, date range, user, client, and IP address, with built-in fingerprint-based deduplication.
See Keycloak Consumer Operations for configuration, event processing patterns, and examples.
Security Policies
The security policy provides route-level authorization by validating Keycloak access tokens. It supports role-based and permission-based authorization, local JWT parsing and OAuth 2.0 token introspection (RFC 7662) with pluggable cache implementations.
See Keycloak Security Policies for configuration, token introspection setup, and examples.
Usage
Providing Access Tokens
The security policy expects access tokens to be provided in one of the following ways:
-
Header:
CamelKeycloakAccessToken -
Authorization Header:
Authorization: Bearer <token> -
Exchange Property:
CamelKeycloakAccessToken
// Using header
template.sendBodyAndHeader("direct:protected", "message",
"CamelKeycloakAccessToken", accessToken);
// Using Authorization header
template.sendBodyAndHeader("direct:protected", "message",
"Authorization", "Bearer " + accessToken); Route Examples
-
Java
-
YAML
from("direct:admin-only")
.policy(adminPolicy)
.transform().constant("Admin access granted")
.to("mock:admin");
from("direct:user-or-admin")
.policy(userPolicy)
.transform().constant("User access granted")
.to("mock:user");
from("rest:get:/api/documents")
.policy(documentsPolicy)
.to("direct:list-documents"); - route:
from:
uri: direct:admin-only
steps:
- policy:
ref: adminPolicy
- transform:
constant: "Admin access granted"
- to:
uri: mock:admin
- route:
from:
uri: direct:user-or-admin
steps:
- policy:
ref: userPolicy
- transform:
constant: "User access granted"
- to:
uri: mock:user
- rest:
get:
- uri: /api/documents
to: direct:list-documents
route:
policy:
ref: documentsPolicy Configuration Options
| Name | Default | Description |
|---|---|---|
serverUrl | Keycloak server URL (e.g., http://localhost:8080) | |
realm | Keycloak realm name | |
clientId | Keycloak client ID | |
clientSecret | Keycloak client secret (for client credentials flow) | |
username | Username (for resource owner password flow) | |
password | Password (for resource owner password flow) | |
requiredRoles | "" | Comma-separated list of required roles (e.g., "admin,user,manager") |
requiredPermissions | "" | Comma-separated list of required permissions (e.g., "read:documents,write:documents") |
allRolesRequired | true | Whether ALL roles are required (true) or ANY role (false) |
allPermissionsRequired | true | Whether ALL permissions are required (true) or ANY permission (false) |
useResourceOwnerPasswordCredentials | false | Whether to use resource owner password flow |
Security Considerations
-
Always use HTTPS in production environments
-
Store client secrets securely (environment variables, secret management systems)
-
Regularly rotate client secrets and user passwords
-
Use the principle of least privilege when assigning roles and permissions
-
Consider token expiration and refresh strategies
Error Handling
The component throws CamelAuthorizationException when:
-
Access token is missing or invalid
-
User doesn’t have required roles
-
User doesn’t have required permissions
-
Keycloak server is unreachable
-
Token verification fails
-
Java
-
YAML
onException(CamelAuthorizationException.class)
.handled(true)
.setHeader(Exchange.HTTP_RESPONSE_CODE, constant(403))
.transform().constant("Access denied"); - onException:
exception:
- "org.apache.camel.CamelAuthorizationException"
handled: true
steps:
- setHeader:
name: "CamelHttpResponseCode"
constant: 403
- transform:
constant: "Access denied" Running Integration Tests
The component includes integration tests that require a running Keycloak instance. These tests are disabled by default and only run when specific system properties are provided.
The integration tests include comprehensive testing for: * Role-based authorization with different role requirements * Permission-based authorization using custom claims and scopes * Public key verification with JWKS endpoint integration * Combined roles and permissions validation * Token parsing with and without public key verification * Different authorization header formats (Bearer token, custom header) * Token expiration and validity checks * Error handling for invalid tokens and insufficient privileges
Starting Keycloak with Docker
1. Start Keycloak Container
# Start Keycloak in development mode
docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak:latest start-dev 2. Access Keycloak Admin Console
Open your browser to http://localhost:8080/admin and login with: - Username: admin - Password: admin
Keycloak Configuration for Integration Tests
3. Create Test Realm
-
In the Keycloak Admin Console, click "Add realm"
-
Set realm name to:
test-realm -
Click "Create"
4. Create Test Client
-
In the
test-realm, go to Clients → "Create client" -
Set the following:
-
Client type:
OpenID Connect -
Client ID:
test-client -
Next → Client authentication:
ON -
Authorization:
ON(optional, for advanced features) -
Next → Valid redirect URIs:
* -
Click "Save"
-
-
Go to Credentials tab and copy the Client Secret
5. Create Test Roles
-
Go to Realm roles → "Create role"
-
Create the following roles:
-
admin-role -
user -
reader
-
6. Create Test Users
Create three test users with the following configuration:
User 1: myuser 1. Go to Users → "Add user" 2. Set: - Username: myuser - Email: myuser@test.com - First name: My - Last name: User - Click "Create" 3. Go to Credentials tab → "Set password" - Password: pippo123 - Temporary: OFF 4. Go to Role mapping tab → "Assign role" - Assign role: admin-role
User 2: test-user 1. Create user with: - Username: test-user - Password: user123 (temporary: OFF) - Assign role: user
User 3: reader-user 1. Create user with: - Username: reader-user - Password: reader123 (temporary: OFF) - Assign role: reader
Running the Integration Tests
7. Execute Tests with Maven
Run All Integration Tests:
# Run integration tests with required properties
mvn test -Dtest=KeycloakSecurityIT \
-Dkeycloak.server.url=http://localhost:8080 \
-Dkeycloak.realm=test-realm \
-Dkeycloak.client.id=test-client \
-Dkeycloak.client.secret=YOUR_CLIENT_SECRET Run Specific Test Categories:
# Test only role-based authorization
mvn test -Dtest=KeycloakSecurityIT#testKeycloakSecurityPolicyWithValidAdminToken,testKeycloakSecurityPolicyWithValidUserToken,testKeycloakSecurityPolicyUserCannotAccessAdminRoute \
-Dkeycloak.server.url=http://localhost:8080 \
-Dkeycloak.realm=test-realm \
-Dkeycloak.client.id=test-client \
-Dkeycloak.client.secret=YOUR_CLIENT_SECRET
# Test only permissions-based authorization
mvn test -Dtest=KeycloakSecurityIT#testKeycloakSecurityPolicyWithPermissions,testKeycloakSecurityPolicyWithScopeBasedPermissions,testKeycloakSecurityPolicyWithCombinedRolesAndPermissions \
-Dkeycloak.server.url=http://localhost:8080 \
-Dkeycloak.realm=test-realm \
-Dkeycloak.client.id=test-client \
-Dkeycloak.client.secret=YOUR_CLIENT_SECRET
# Test only public key verification
mvn test -Dtest=KeycloakSecurityIT#testKeycloakSecurityPolicyWithPublicKeyVerification,testParseTokenDirectlyWithPublicKey \
-Dkeycloak.server.url=http://localhost:8080 \
-Dkeycloak.realm=test-realm \
-Dkeycloak.client.id=test-client \
-Dkeycloak.client.secret=YOUR_CLIENT_SECRET Replace YOUR_CLIENT_SECRET with the actual client secret from step 4.
Run Manual Producer Tests:
The KeycloakProducerIT test contains manual integration tests for producer operations. These tests are disabled by default and require explicit activation:
# Run manual producer integration tests
mvn test -Dtest=KeycloakProducerIT \
-Dmanual.keycloak.test=true \
-Dkeycloak.server.url=http://localhost:8080 \
-Dkeycloak.realm=master \
-Dkeycloak.username=admin \
-Dkeycloak.password=admin The -Dmanual.keycloak.test=true flag is required to run KeycloakProducerIT tests. Without this flag, the tests will be skipped even if other Keycloak properties are provided. This prevents the tests from accidentally running in automated CI environments. |
8. Alternative: Set Environment Variables
# For KeycloakSecurityIT tests
export KEYCLOAK_SERVER_URL=http://localhost:8080
export KEYCLOAK_REALM=test-realm
export KEYCLOAK_CLIENT_ID=test-client
export KEYCLOAK_CLIENT_SECRET=YOUR_CLIENT_SECRET
# Run security tests
mvn test -Dtest=KeycloakSecurityIT \
-Dkeycloak.server.url=$KEYCLOAK_SERVER_URL \
-Dkeycloak.realm=$KEYCLOAK_REALM \
-Dkeycloak.client.id=$KEYCLOAK_CLIENT_ID \
-Dkeycloak.client.secret=$KEYCLOAK_CLIENT_SECRET
# For manual producer tests (KeycloakProducerIT)
export KEYCLOAK_SERVER_URL=http://localhost:8080
export KEYCLOAK_REALM=master
export KEYCLOAK_USERNAME=admin
export KEYCLOAK_PASSWORD=admin
# Run manual producer tests (requires explicit flag)
mvn test -Dtest=KeycloakProducerIT \
-Dmanual.keycloak.test=true \
-Dkeycloak.server.url=$KEYCLOAK_SERVER_URL \
-Dkeycloak.realm=$KEYCLOAK_REALM \
-Dkeycloak.username=$KEYCLOAK_USERNAME \
-Dkeycloak.password=$KEYCLOAK_PASSWORD Troubleshooting
Tests are skipped: - For KeycloakSecurityIT: Verify all four required properties are provided and Keycloak is running on the specified URL. - For KeycloakProducerIT: Ensure -Dmanual.keycloak.test=true is set along with the required Keycloak properties.
401 Unauthorized: Check that: - Users exist with correct passwords - Users have the required roles assigned - Client credentials are correct
Connection refused: Ensure Keycloak is running and accessible at the specified URL.
Token validation errors: Verify the realm name and client configuration match exactly.
Setting up Permissions in Keycloak
For permissions-based authorization, you have several options to include permissions in tokens:
Option 1: Custom Claims Mapper
-
In your realm, go to Client Scopes → roles → Mappers → Create mapper
-
Set the following:
-
Mapper Type:
User Attribute -
Name:
permissions-mapper -
User Attribute:
permissions -
Token Claim Name:
permissions -
Claim JSON Type:
JSON -
Add to ID token:
ON -
Add to access token:
ON
-
-
Add the
permissionsattribute to users:-
Go to Users → Select user → Attributes tab
-
Add attribute:
permissionswith value like["read:documents", "write:documents"]
-
Option 2: Scope-based Permissions
-
Configure client scopes:
-
Go to Client Scopes → Create client scope
-
Scope Name:
documents -
Protocol:
openid-connect
-
-
Add scope to client:
-
Go to Clients → Your client → Client Scopes tab
-
Add the scope as Default or Optional
-
-
In your application code, you can then use scopes as permissions:
KeycloakSecurityPolicy policy = new KeycloakSecurityPolicy();
policy.setRequiredPermissions("documents,users,admin");
policy.setAllPermissionsRequired(false); // ANY permission Option 3: Authorization Services (Advanced)
For complex permission models, enable Keycloak Authorization Services:
-
Go to Clients → Your client → Settings → Authorization Enabled:
ON -
Configure Resources, Scopes, and Policies in the Authorization tab
-
Enable Authorization on the client
Note: Full Authorization Services integration requires additional setup and is more complex than the simple approaches above.