OTRS uses Keycloak for identity and access management. This tutorial explains setup, configuration and maintenance guidelines for using Keycloak as 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 versions: 26.2.0 to 26.4.0
Setup Keycloak
OTRS uses two-realms solution, separate realm for agents and 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.
-
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 the users managing operations. -
Select the client from the Clients list, then in Service accounts roles tab add the following roles with Assign role button:
- realm-management: manage-clients - realm-management: manage-users - realm-management: view-clients - realm-management: view-users - realm-management: query-users
-
Create the customer users realm
otrs-customer-users. -
Configure it in the exact same way as the agents realm.
Setup OTRS for Keycloak
Note
If you plan to migrate an existing OTRS installation to Keycloak, please read the Migration section below before you setup 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 Keycloak and OTRS are setup:
-
Create the user
root@localhostin the agents realm. -
Create the necessary roles in client
otrs-appand assign them to the users.
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 setup correctly. See section Setup Keycloak above.
-
Synchronize agent roles by running the following scripts in OTRS:
bin/otrs.Console.pl Admin::OIDC::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::OIDC::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::OIDC::SyncCustomerUsers \ --realmĀ otrs-customer-users \ --client-id otrs-app \ --backend-authority {Keycloak host} \ --api-credentials-client-id otrs-api \ --api-credentials-client-secret {secret}
-
Setup OTRS. See section Setup OTRS for Keycloak above.
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.
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.
