OTRS uses Keycloak for identity and access management. This tutorial explains the setup, configuration and maintenance guidelines for using Keycloak as a central authentication with OTRS.
When OTRS is configured to use Keycloak, and an agent or a customer user tries to access the OTRS login page, the browser will be automatically redirected to Keycloak where authentication actually happens. If authentication is successful, the browser is redirected to OTRS where normal usage takes place.
Note
Supported Keycloak version: 26.4.0
Keycloak Setup
OTRS uses two-realm solution, one realm for agents and one for customer users.
See also
Read the official Keycloak documentation to learn how to install and how does it work.
If Keycloak is up and running:
-
Create the agents realm
otrs-agents. -
Go to Realm settings, select General tab and enable Unmanaged Attributes.
-
Still in Realm settings, select User profile tab:
-
select
username, then scroll down to Validations section and delete the validator up-username-not-idn-homograph -
select
lastName, then scroll down to Validations section and delete the validator person-name-prohibited-characters -
select
firstName, then scroll down to Validations section and delete the validator person-name-prohibited-characters
-
-
Select the client
realm-managementfrom the Clients list, then in Roles tab create the roleview-system. -
Create the client
otrs-app. This will be the client used by the OTRS agent front end. -
Select the client from the Clients list, then in Settings tab scroll down to Capability config section and select the Standard flow checkbox in Authentication flow.
-
Create the client
otrs-api. This client is needed for user management operations. -
Select the client from the Clients list. In the Settings tab, scroll down to the Capability config section. Under Authentication flow, enable Client authentication, select the Standard Flow and Service accounts roles checkboxes.
-
Then in Service accounts roles tab add the following roles with Assign role button:
- realm-management: manage-clients - realm-management: manage-users - realm-management: query-users - realm-management: view-clients - realm-management: view-system - realm-management: view-users
-
Create the customer users realm
otrs-customer-users. -
Configure it in the exact same way as the agents realm.
Note
In the default configuration, Keycloak requires usernames with at least 3 characters. To change this behavior, select the appropriate realm and navigate to Realm Settings. Open the User Profile section and switch to the Attributes tab. Locate the username attribute, then add a Length validator. Configure the required minimum and maximum length values for the username and save the changes. The updated limits will apply to newly created users and when existing usernames are modified.
OTRS Setup for Keycloak
Note
If you plan to migrate an existing OTRS installation to Keycloak, please read the Migration section below before you set up OTRS for Keycloak.
To activate Keycloak for agents, you need to copy the following configuration snippet from Kernel/Config/Defaults.pm and paste it to Kernel/Config.pm. Uncomment the lines and add the proper values for the keys.
# -------------------------------------------------- #
# OIDC/Keycloak authentication of Agents #
# -------------------------------------------------- #
$Self->{'AuthModule'} = 'Kernel::System::Auth::OIDC';
$Self->{'AuthModule::OIDC::Authority'} = 'https://keycloak-host:8024';
# In Kubernetes environment, we need a different Authority URL, to comunicate directly to the Keycloak.
# $Self->{'AuthModule::OIDC::BackendAuthority'} = 'https://keycloak-host:8024';
$Self->{'AuthModule::OIDC::Realm'} = 'otrs-agents';
$Self->{'AuthModule::OIDC::ClientID'} = 'otrs-app';
$Self->{'AuthModule::OIDC::PostLogoutRedirectURL'} = 'http://localhost:3001';
$Self->{'Agent::AccessTokenStorageModule'} = 'Kernel::System::AccessToken::Storage::OIDC';
$Self->{'Keycloak::API::Credentials::User::ClientID'} = 'otrs-api';
$Self->{'Keycloak::API::Credentials::User::ClientSecret'} = 'secret';
# };
# Set to 1 to enable remote session checking, instead of using local checking
# $Self->{'AuthModule::OIDC::Token::EnableRemoteCheck'} = 1;
# Define role name which user must have in order to be able to login on Agent interface.
# $Self->{'AuthModule::OIDC::AgentRole'} = 'Agent'; # optional
# --------------------------------------------------------- #
# authentication sync settings - OpenID Connect #
# (enable agent data sync. after successful authentication) #
# --------------------------------------------------------- #
# This is an example configuration for an OIDC auth sync. backend.
$Self->{'AuthSyncModule'} = 'Kernel::System::Auth::Sync::OIDC';
# Map if agent should be created/synced from access token to DB after successful login.
# OTRS-User-FieldName => Access token key
$Self->{'AuthSyncModule::OIDC::UserSyncMap'} = {
# DB -> Header
UserFirstname => 'given_name',
UserLastname => 'family_name',
UserEmail => 'email',
};
# Sync roles based on access token values (must be an array reference of role names).
# - DisableUserRolesSync: set to 1 to disable role sync.
# $Self->{'AuthSyncModule::OIDC::DisableUserRolesSync'} = 1;
Alternatively, environment variables can be used for the same purpose. The following environment variables will provide identical configuration possibilities as if using Kernel/Config.pm code snippet. If yes is displayed in the last column, the environment variable is mandatory if Keycloak is enabled.
|
Environment Variables for Agents |
Description |
Default Value |
Mandatory |
|---|---|---|---|
|
|
Keycloak URL |
N/A |
yes |
|
|
URL which is used for back end to Keycloak |
N/A |
no |
|
|
Keycloak realm for Agents |
N/A |
yes |
|
|
Client ID which is used for token handling |
N/A |
yes |
|
|
Role that identifies the user as an agent |
N/A |
yes |
|
|
Client ID which has access to the endpoints |
N/A |
yes |
|
|
Client secret |
N/A |
yes |
|
|
URL to redirect after successful login |
FQDN |
no |
|
|
Enable token remote check for every request |
N/A |
no |
|
|
Do not sync Agents <=> Roles memberships on |
N/A |
no |
|
|
User map for first name |
given_name |
no |
|
|
User map for last name |
family_name |
no |
|
|
User map for email |
|
no |
To activate Keycloak for customer users, you need to copy the following configuration snippet from Kernel/Config/Defaults.pm and paste it to Kernel/Config.pm. Uncomment the lines and add the proper values for the keys.
# --------------------------------------------------- #
# OIDC/Keycloak authentication of CustomerUsers #
# --------------------------------------------------- #
$Self->{'Customer::AuthModule'} = 'Kernel::System::CustomerAuth::OIDC';
$Self->{'Customer::AuthModule::OIDC::Authority'} = 'https://keycloak-host:8024';
# In Kubernetes environment, we need to use different Authority URL, to comunicate directly to the Keycloak.
# $Self->{'Customer::AuthModule::OIDC::BackendAuthority'} = 'https://keycloak-host:8024';
$Self->{'Customer::AuthModule::OIDC::Realm'} = 'otrs-customer-users';
$Self->{'Customer::AuthModule::OIDC::ClientID'} = 'otrs-app';
$Self->{'Customer::AuthModule::OIDC::PostLogoutRedirectURL'} = 'http://localhost:3001';
$Self->{'Customer::AccessTokenStorageModule'} = 'Kernel::System::AccessToken::Storage::OIDC';
$Self->{'Keycloak::API::Credentials::CustomerUser::ClientID'} = 'otrs-api';
$Self->{'Keycloak::API::Credentials::CustomerUser::ClientSecret'} = 'secret';
# Set to 1 to enable remote session checking, instead of using local checking
# $Self->{'Customer::AuthModule::OIDC::Token::EnableRemoteCheck'} = 1;
# Define role name which user must have in order to be able to login on External interface.
# $Self->{'Customer::AuthModule::OIDC::CustomerUserRole'} = 'Customer User'; # optional
$Self->{CustomerUser} = {
Name => 'OIDC Backend',
Module => 'Kernel::System::CustomerUser::OIDC',
# customer unique id
CustomerKey => 'username',
CustomerID => 'email',
CustomerUserListFields => ['firstName', 'lastName', 'email'],
CustomerUserSearchFields => ['id', 'username', 'email'],
CustomerUserSearchListLimit => 250,
CustomerUserPostMasterSearchFields => ['customerid'],
CustomerUserNameFields => ['firstName', 'lastName'],
# Configures the character for joining customer user name parts. Join single space if it is not defined.
CustomerUserNameFieldsJoin => ' ',
# show customer user and customer tickets in the external interface
CustomerUserExcludePrimaryCustomerID => 0,
# cache time to live in sec. - cache any Keycloak queries
CacheTTL => 0,
# Consider this source read only.
ReadOnly => 1,
Map => [
[ 'UserTitle', Translatable('Title or salutation'), 'title', 1, 0, 'var', '', 1, undef, undef ],
[ 'UserFirstname', Translatable('Firstname'), 'firstName', 1, 1, 'var', '', 1, undef, undef ],
[ 'UserLastname', Translatable('Lastname'), 'lastName', 1, 1, 'var', '', 1, undef, undef ],
[ 'UserLogin', Translatable('Username'), 'username', 1, 1, 'var', '', 1, undef, undef ],
[ 'UserEmail', Translatable('Email'), 'email', 1, 1, 'var', '', 1, undef, undef ],
# Important: customerid attribute MUST BE DEFINED in the Keycloak.
[ 'UserCustomerID', Translatable('CustomerID'), 'customerid',0, 1, 'var', '', 1, undef, undef ],
#[ 'UserCustomerIDs',Translatable('CustomerIDs'),'second_customer_ids',1, 0, 'var', '', 1, undef, undef ],
[ 'UserPhone', Translatable('Phone'), 'phone', 1, 0, 'var', '', 1, undef, undef ],
[ 'UserFax', Translatable('Fax'), 'fax', 1, 0, 'var', '', 1, undef, undef ],
[ 'UserMobile', Translatable('Mobile'), 'mobile', 1, 0, 'var', '', 1, undef, undef ],
[ 'UserStreet', Translatable('Street'), 'street', 1, 0, 'var', '', 1, undef, undef ],
[ 'UserZip', Translatable('Zip'), 'zip', 1, 0, 'var', '', 1, undef, undef ],
[ 'UserCity', Translatable('City'), 'city', 1, 0, 'var', '', 1, undef, undef ],
[ 'UserCountry', Translatable('Country'), 'country', 1, 0, 'var', '', 1, undef, undef ],
[ 'UserComment', Translatable('Comment'), 'comment', 1, 0, 'var', '', 1, undef, undef ],
[ 'ValidID', Translatable('Valid'), 'enabled', 0, 0, 'int', '', 1, undef, undef ],
# this is needed, if "SMIME::FetchFromCustomer" is active
# [ 'UserSMIMECertificate','SMIMECertificate','userSMIMECertificate', 0, 1, 'var', '', 1, undef, undef ],
# Dynamic field example
# [ 'DynamicField_Name_X', undef, 'Name_X', 0, 0, 'dynamic_field', undef, 0, undef, undef ],
],
};
Alternatively, environment variables can be used for the same purpose. The following environment variables will provide identical configuration possibilities as if using Kernel/Config.pm code snippet. If yes is displayed in the last column, the environment variable is mandatory if Keycloak is enabled.
|
Environment Variables for Customer Users |
Description |
Default Value |
Mandatory |
|---|---|---|---|
|
|
Keycloak URL |
N/A |
yes |
|
|
URL which is used for back end to Keycloak |
N/A |
no |
|
|
Keycloak realm for customer users |
N/A |
yes |
|
|
Client ID which is used for token handling |
N/A |
yes |
|
|
Role that identifies the user as a customer |
N/A |
yes |
|
|
Client ID which has access to the endpoints |
N/A |
yes |
|
|
Client secret |
N/A |
yes |
|
|
URL to redirect after successful login |
FQDN |
no |
|
|
Enable token remote check for every request |
N/A |
no |
After the setup of Keycloak and OTRS:
-
Create the user
root@localhostin the agents realm. -
Create the necessary roles in client
otrs-appand assign them to the users.
Set Up connection between LDAP and Keycloak
-
Login as admin in Keycloak and select the desired realm.
-
On the left side, select User Federation and click Add LDAP provider.
-
Under General options:
-
UI Display Name – Set any name, serves as a descriptor (e.g.
Corporate LDAPorOTRS Directory). -
Vendor – Select
Otherfor standard OpenLDAP servers orActive Directoryif using Microsoft AD.
-
-
Under Connection and Authentication Settings:
-
Connection URL –
ldaps://ldap.example.com:636
(useldap://with port389if TLS is not available) -
Leave other configuration as default.
-
Click Test Connection and ensure the result is green.
-
Bind Type – Select
simple. -
Bind DN – DN of the administrative or service user, for example:
uid=ldap-admin,ou=system,dc=example,dc=com -
Bind Credentials – Password for the Bind DN user, for example:
secret123 -
Click Test Authentication and ensure the result is green.
Note
Replace all example values (
ldap.example.com,uid=ldap-admin,secret123)
with the actual configuration of your LDAP server.Tip
If you are using LDAPS with a self-signed certificate, make sure to configure a
Java truststore and reference it in the Keycloak startup parameters using:
-Djavax.net.ssl.trustStore=/opt/keycloak/conf/truststore.jks
and-Djavax.net.ssl.trustStorePassword=<password>.
Alternatively, enable “Use Truststore SPI → Only for LDAPS connection”
in the Keycloak UI.Tip
To improve performance in large environments, enable Connection Pooling.
-
-
Under LDAP Searching and Updating:
-
Edit Mode –
READ_ONLY(recommended when LDAP is the main source of truth) -
Users DN –
ou=users,dc=example,dc=com -
Username LDAP Attribute –
uid(orsAMAccountNamefor Active Directory) -
RDN LDAP Attribute –
uid -
UUID LDAP Attribute –
entryUUID(orobjectGUIDfor Active Directory) -
User Object Classes –
inetOrgPerson,organizationalPerson,person,posixAccount -
Leave other configuration as default.
Tip
By default, it is recommended to keep Edit Mode set to
READ_ONLYsince
LDAP is typically considered the single source of truth and should not be
modified by Keycloak.However, for certain use cases — such as OTRS system migration — it may
be necessary to temporarily switch Edit Mode toWRITABLEto allow
Keycloak to synchronize users with OTRS.In such cases:
-
Set Edit Mode to
WRITABLEbefore running the synchronization process. -
Once synchronization is completed, revert Edit Mode
back toREAD_ONLYto protect LDAP data integrity.
Important
Keep
WRITABLEenabled only for the duration of the required synchronization.
Leaving it permanently active may allow Keycloak to modify LDAP user data,
which can lead to unintended attribute changes or conflicts with external systems.Tip
If you have more than 1000 users, enable Pagination to allow Keycloak to
retrieve all entries without server-imposed limits.
This prevents partial synchronization results in larger directories,
especially with Active Directory environments where the default size limit is 1000 entries. -
-
Synchronization settings:
-
Go to User Federation → Settings → Action → Sync all users.
-
Go to the Users list. Since it may not show users automatically, type
*in the search box. -
Verify that all users are listed and visible in the realm.
Tip
To keep data in sync automatically, configure periodic synchronization:
– Periodic Full Sync: every 24 hours (86400seconds)
– Periodic Changed Users Sync: every 1 hour (3600seconds)Note
Make sure that Import Users is enabled. This allows Keycloak to import
LDAP users into its internal database for authentication and role mapping. -
-
Attribute mapping (Mappers):
When a new LDAP provider is created, Keycloak attempts to automatically detect
and create mappings between LDAP attributes and Keycloak user attributes.-
Default mappings usually include:
–firstName→givenName
–lastName→sn
–email→mail
–username→uid(orsAMAccountNamefor Active Directory)
–uuid→entryUUID(orobjectGUIDfor AD)
Note
In most environments, these mappings are created automatically when the LDAP
provider is added. However, they can also be reviewed and customized manually
under User Federation → [Your LDAP Provider] → Mappers.Tip
-
If the email or name fields are empty after synchronization,
verify that their LDAP attributes are correctly mapped in this section. -
For Active Directory, make sure
objectGUIDis mapped to the
User ID attribute in Keycloak to ensure consistent user identity. -
If groups or roles are managed in LDAP, you can add an additional mapper
of type group-ldap-mapper or role-ldap-mapper to synchronize them
into Keycloak automatically.
Important
Incorrect or missing mappers can cause login failures or duplicate users after
synchronization. Always verify that all critical attributes (username, email,
UUID) are mapped correctly before enabling automatic sync. -
Migrate System Authentication to Keycloak
Note
For this migration to work, OTRS should be configured to use Keycloak only after the migration is completed.
-
Make sure that Keycloak is set up correctly. See section Keycloak Setup above.
-
Synchronize agent roles by running the following scripts in OTRS:
bin/otrs.Console.pl Admin::IAM::SyncRoles \ --realm otrs-agents \ --client-id otrs-app \ --backend-authority {Keycloak host} \ --api-credentials-client-id otrs-api \ --api-credentials-client-secret {secret}
-
Synchronize agents by running the following scripts in OTRS:
bin/otrs.Console.pl Admin::IAM::SyncUsers \ --realm otrs-agents \ --client-id otrs-app \ --backend-authority {Keycloak host} \ --api-credentials-client-id otrs-api \ --api-credentials-client-secret {secret}
-
Synchronize customer users by running the following scripts in OTRS:
bin/otrs.Console.pl Admin::IAM::SyncCustomerUsers \ --realm otrs-customer-users \ --client-id otrs-app \ --backend-authority {Keycloak host} \ --api-credentials-client-id otrs-api \ --api-credentials-client-secret {secret}
-
Set up OTRS. See section OTRS Setup for Keycloak above.
Important
During migration, some OTRS user accounts may not be synchronized to Keycloak because their login names contain characters that are not permitted by Keycloak’s username validation rules. Usernames including characters such as ! % & * / , must be identified and corrected prior to migration to ensure a successful synchronization.
Setup and Maintenance Topics
OTRS must be able to access Keycloak through the network any time. A good low latency connectivity is recommended.
To check the connectivity:
curl -v -L http://my.keycloak.host:8024.
You can use a console command for the same purpose:
bin/otrs.Console.pl Maint::IAM::Check
Do not delete users in Keycloak. Instead, you should set them to disabled when they are not needed anymore. OTRS keeps references to users. For this reason they should not be deleted, only set to disabled.
When OTRS is using Keycloak for authentication, every agent needs to check his organizer items of type customer user. Note that old organizer items most likely will not work, because wildcard search (*) is not supported in Keycloak. It is suggested to drop those and create new organizer items again with available and supported filters.
Customer User Attributes
When transferring or creating customer users in Keycloak, the following attributes should be considered. Some attributes are mandatory.
-
firstName(required) -
lastName(required) -
username(required) -
email(required) -
customerid(required, must be exactly equal to the value in OTRS) -
enabled(required) -
title -
phone -
comment -
fax -
mobile -
street -
zip -
city -
country
To configure customer user attributes in Keycloak, open the customer user realm settings, then user profile.
Data Synchronization
- Customer Users
-
When Keycloak is being used, it is not possible to create customer users directly in OTRS and there is no synchronization of customer users from Keycloak to OTRS. Customer users should be created and updated in Keycloak but they will not be created nor updated in OTRS.
- Agents
-
When Keycloak is being used, it is not possible to create agents directly in OTRS. Synchronization of agents from Keycloak to OTRS will occur on successful agent login. The above mentioned configuration setting
AuthSyncModulecontrols how the agent synchronization process happens.The synchronization process covers agent basic attributes like name, address and phone for example. The synchronization process covers agent roles mappings like user and administrator for example. The synchronization process does not cover groups.
- Agent Roles
-
When an agent logs in, OTRS reads agent roles mappings from the corresponding, Keycloak provided, access token. The access token contains a specific field for such data and OTRS is able to read it.
Role names defined in Keycloak must match exactly the role names defined in OTRS.
The configuration setting
DisableUserRolesSynccan be set to 1 to disable this feature. To create roles in Keycloak without synchronizing, you should select the client you want from the Clients menu. There, you can create roles in the Roles tab and assign them to the Keycloak users as needed. - Client Secret
-
To obtain the
ClientSecretsetting you should access your Keycloak administration interface, select the client you want from the Clients menu and activate Client authentication in the Settings tab. After that, you can navigate to the Credentials tab. The value you need is in the Client secret text box.
