Red Hat's single sign-on (SSO) technology, based on the Keycloak open source project, is Red Hat's solution for securing web applications and RESTful web services. The goal of Red Hat's single sign-on technology is to make security simple, so that it is easy for application developers to secure the apps and services they have deployed in their organization.
Out of the box, single sign-on uses its own Java-based embedded relational database, called H2, to store persistent data. However, this H2 database is not viable in high-concurrency situations and should not be used in a cluster. So, it is highly recommended to replace this H2 database with a more production-ready external database.
This article shows you how to install and configure Red Hat's single sign-on technology to connect to a more mature database. We'll use MariaDB for the example, but the instructions should also work for MySQL.
Note: This article is the first in a series about using SSO with external databases. My next article will cover deploying an SSO image in Red Hat OpenShift. You will learn how to connect the image to an external MariaDB or MySQL server running outside of OpenShift using a custom JDBC driver.
Setting up and configuring the MariaDB or MySQL database
To perform the steps in this section, you must first log in as root
on a Red Hat Enterprise Linux (RHEL) 7 system.
Step 1: Install and configure a MariaDB or MySQL database server
This step can be done through the following commands:
[root@testvm ~]# yum install mariadb-server mariadb mysql-connector-java [root@testvm ~]# systemctl enable mariadb [root@testvm ~]# systemctl start mariadb [root@testvm ~]# /usr/bin/mysql_secure_installation ... Set root password? [Y/n] Y New password: redhat Re-enter new password: redhat ... Remove anonymous users? [Y/n] Y ... Disallow root login remotely? [Y/n] Y ... Remove test database and access to it? [Y/n] Y ... Reload privilege tables now? [Y/n] Y ... All done! If you've completed all of the above steps, your MariaDB installation should now be secure. Thanks for using MariaDB! [root@testvm ~]# [root@testvm ~]# mysql -h localhost -uroot -predhat ... MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | +--------------------+ 3 rows in set (0.01 sec) MariaDB [(none)]> MariaDB [(none)]> quit Bye [root@testvm ~]#
Step 2: Create a new user and a database for SSO
Enter the following commands to create the new user:
[root@testvm ~]# cat mariadb_rhsso74_db_setup.sql CREATE USER 'rhsso74'@'%' IDENTIFIED BY 'redhat'; DROP DATABASE IF EXISTS `rhsso74`; CREATE DATABASE IF NOT EXISTS `rhsso74`; GRANT ALL PRIVILEGES ON rhsso74.* TO 'rhsso74'@'%' identified by 'redhat'; [root@testvm ~]# [root@testvm ~]# mysql -h localhost -uroot -predhat < mariadb_rhsso74_db_setup.sql [root@testvm ~]# [root@testvm ~]# mysql -h localhost -uroot -predhat MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | rhsso74 | +--------------------+ 4 rows in set (0.00 sec) MariaDB [rhsso74]> quit Bye [root@testvm ~]# [root@testvm ~]# mysql -h localhost -urhsso74 -predhat MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | rhsso74 | +--------------------+ 2 rows in set (0.00 sec) MariaDB [(none)]> use `rhsso74`; Database changed MariaDB [rhsso74]> show tables; Empty set (0.00 sec) MariaDB [rhsso74]> quit Bye [root@testvm ~]#
Installing and configuring SSO
To perform the steps in this section, log in as ssoadmin
on a RHEL 7 system.
Step 1: Download and install Red Hat's single sign-on 7.4 software
At the time of writing this article, SSO 7.4 is the latest available release. Download and install SSO under a directory path of your choice, for instance:
/home/ssoadmin/RH-SSO_SETUP/RH-SSO_7.x/7.4.x/LATEST/
After creating the directory, run the following commands to install the software:
[ssoadmin@testvm LATEST]$ id -a uid=1000(ssoadmin) gid=1000(ssoadmin) groups=1000(ssoadmin),10(wheel) context=system_u:system_r:unconfined_service_t:s0 [ssoadmin@testvm LATEST]$ [ssoadmin@testvm LATEST]$ pwd /home/ssoadmin/RH-SSO_SETUP/RH-SSO_7.x/7.4.x/LATEST/ [ssoadmin@testvm LATEST]$ [ssoadmin@testvm LATEST]$ unzip rh-sso-7.4.0.zip Archive: rh-sso-7.4.0.zip creating: rh-sso-7.4/ creating: rh-sso-7.4/modules/ ... ... inflating: rh-sso-7.4/docs/licenses-rh-sso/org.keycloak,keycloak-server-spi-private,9.0.3.redhat-00002,Apache Software License 2.0.txt [ssoadmin@testvm LATEST]$ [ssoadmin@testvm LATEST]$ cd rh-sso-7.4/ [ssoadmin@testvm rh-sso-7.4]$ [ssoadmin@testvm rh-sso-7.4]$ cat version.txt Red Hat Single Sign-On - Version 7.4.0.GA [ssoadmin@testvm rh-sso-7.4]$
Step 2: Add a new admin user and start the SSO server instance
This step can be done through the following commands:
[ssoadmin@testvm rh-sso-7.4]$ cd bin [ssoadmin@testvm bin]$ ./add-user.sh --user admin -p redhat Updated user 'admin' to file '/home/ssoadmin/RH-SSO_SETUP/RH-SSO_7.x/7.4.x/LATEST/rh-sso-7.4/standalone/configuration/mgmt-users.properties' Updated user 'admin' to file '/home/ssoadmin/RH-SSO_SETUP/RH-SSO_7.x/7.4.x/LATEST/rh-sso-7.4/domain/configuration/mgmt-users.properties' [ssoadmin@testvm bin]$ [ssoadmin@testvm bin]$ ./standalone.sh
Step 3: Change the SSO binding addresses to listen to all network interfaces
By default, Red Hat's single sign-on technology binds via Red Hat JBoss Enterprise Application Platform (JBoss EAP) to the localhost loopback address 127.0.0.1. However, that’s not a very useful default setting if you want the authentication server available on your network. So, you need to set up your network interfaces to bind to something other than localhost. You could also do this when starting the server instance by setting the -b
option to the IP bind address of your choice. But it is better to set it in the configuration just once, where it applies to all the network interfaces on the host.
Open a new terminal tab and run the following JBoss command-line interface (CLI) commands:
[ssoadmin@testvm bin]$ ./jboss-cli.sh --connect [standalone@localhost:9990 /] /interface=public:write-attribute(name=inet-address,value=0.0.0.0) [standalone@localhost:9990 /] /interface=management:write-attribute(name=inet-address,value=0.0.0.0) [standalone@localhost:9990 /] reload [standalone@localhost:9990 /] exit
Step 4: Add a new admin user for SSO
This user account is specific to the server runtime for SSO, and will allow you to log into the master
realm’s administration console to perform administrative tasks in SSO. These tasks include creating realms, creating users, registering clients for applications to be secured by single sign-on, and so on.
When adding the user account, the command parameters differ a little, depending on whether you are using standalone operation mode or domain operation mode. The following works for standalone mode:
[ssoadmin@testvm bin]$ ./add-user-keycloak.sh -r master -u admin -p redhat Added 'admin' to '/home/ssoadmin/RH-SSO_SETUP/RH-SSO_7.x/7.4.x/LATEST/rh-sso-7.4/standalone/configuration/keycloak-add-user.json', restart server to load user [ssoadmin@testvm bin]$
Note: If your server is running and accessible from localhost, you can also create this admin user by going to http://localhost:8080/auth
.
For domain mode, you have to point the script to one of your server hosts using the -sc
option. For example:
[ssoadmin@testvm bin]$ ./add-user-keycloak.sh --sc domain/servers/server-one/configuration -r master -u username -p password
Step 5: Restart the SSO server instance to load the new admin user
Restart the SSO server instance:
[ssoadmin@testvm bin]$ ./standalone.sh ... 22:20:04,239 INFO [org.jboss.as] (MSC service thread 1-1) WFLYSRV0049: Red Hat Single Sign-On 7.4.0.GA (WildFly Core 10.1.2.Final-redhat-00001) starting ... ... 22:20:22,469 INFO [org.keycloak.services] (ServerService Thread Pool -- 68) KC-SERVICES0006: Importing users from '/home/ssoadmin/RH-SSO_SETUP/RH-SSO_7.x/7.4.x/LATEST/rh-sso-7.4/standalone/configuration/keycloak-add-user.json' 22:20:23,322 INFO [org.keycloak.services] (ServerService Thread Pool -- 68) KC-SERVICES0009: Added user 'admin' to realm 'master' ... 22:20:23,948 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0060: Http management interface listening on http://0.0.0.0:9990/management 22:20:23,948 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0051: Admin console listening on http://0.0.0.0:9990 22:20:23,949 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: Red Hat Single Sign-On 7.4.0.GA (WildFly Core 10.1.2.Final-redhat-00001) started in 19857ms - Started 598 of 893 services (602 services are lazy, passive or on-demand) ...
Configuring SSO to use the MariaDB or MySQL database
These steps, like those in the preceding section, are performed as ssoadmin
on a RHEL 7 system.
Step 1: Add the MySQL JDBC driver module to SSO
Enter the following commands for this step:
[ssoadmin@testvm bin]$ pwd /home/ssoadmin/RH-SSO_SETUP/RH-SSO_7.x/7.4.x/LATEST/rh-sso-7.4/bin [ssoadmin@testvm bin]$ [ssoadmin@testvm bin]$ ./jboss-cli.sh You are disconnected at the moment. Type 'connect' to connect to the server or 'help' for the list of supported commands. [disconnected /] [disconnected /] module add --name=com.mysql --resources=/usr/share/java/mysql-connector-java.jar --dependencies=javax.api,javax.transaction.api [disconnected /] exit [ssoadmin@testvm bin]$ ls -alrt /home/ssoadmin/RH-SSO_SETUP/RH-SSO_7.x/7.4.x/LATEST/rh-sso-7.4/modules/com/mysql/main/ total 868 drwxrwxr-x. 3 ssoadmin ssoadmin 18 Oct 17 19:31 .. -rw-rw-r--. 1 ssoadmin ssoadmin 883899 Oct 17 19:31 mysql-connector-java.jar drwxrwxr-x. 2 ssoadmin ssoadmin 56 Oct 17 19:31 . -rw-rw-r--. 1 ssoadmin ssoadmin 317 Oct 17 19:31 module.xml [ssoadmin@testvm bin]$
Step 2: Register the database driver and add the DataSource
Register the MySQL or MariaDB driver:
[ssoadmin@testvm bin]$ ./jboss-cli.sh --connect [standalone@localhost:9990 /] [standalone@localhost:9990 /] /subsystem=datasources/jdbc-driver=mysql:add(driver-name=mysql,driver-module-name=com.mysql,driver-xa-datasource-class-name=com.mysql.jdbc.jdbc2.optional.MysqlXADataSource, driver-class-name=com.mysql.jdbc.Driver) {"outcome" => "success"} [standalone@localhost:9990 /] [standalone@localhost:9990 /] /subsystem=datasources/data-source=KeycloakMariaDBDS:add(jndi-name=java:jboss/datasources/KeycloakMariaDBDS, driver-name=mysql, connection-url=jdbc:mysql://localhost:3306/rhsso74, user-name=rhsso74, password=redhat) {"outcome" => "success"} [standalone@localhost:9990 /] [standalone@localhost:9990 /] /subsystem=datasources/data-source=KeycloakMariaDBDS:test-connection-in-pool { "outcome" => "success", "result" => [true] } [standalone@localhost:9990 /] [standalone@localhost:9990 /] reload [standalone@localhost:9990 /] [standalone@localhost:9990 /] exit [ssoadmin@testvm bin]$
Step 3: Update the SSO JPA connection to point to the new DataSource
You have to stop the server instance for SSO before updating the JPA connection:
[ssoadmin@testvm bin]$ cp -p /home/ssoadmin/RH-SSO_SETUP/RH-SSO_7.x/7.4.x/LATEST/rh-sso-7.4/standalone/configuration/standalone.xml /home/ssoadmin/RH-SSO_SETUP/RH-SSO_7.x/7.4.x/LATEST/rh-sso-7.4/standalone/configuration/standalone.xml.SAVE_Backup [ssoadmin@testvm bin]$ [ssoadmin@testvm bin]$ vi /home/ssoadmin/RH-SSO_SETUP/RH-SSO_7.x/7.4.x/LATEST/rh-sso-7.4/standalone/configuration/standalone.xml ... <subsystem xmlns="urn:jboss:domain:keycloak-server:1.1"> ... <spi name="connectionsJpa"> <provider name="default" enabled="true"> <properties> <!-- <property name="dataSource" value="java:jboss/datasources/KeycloakDS"/> --> <property name="dataSource" value="java:jboss/datasources/KeycloakMariaDBDS"/> <property name="initializeEmpty" value="true"/> <property name="migrationStrategy" value="update"/> <property name="migrationExport" value="${jboss.home.dir}/keycloak-database-update.sql"/> </properties> </provider> </spi> ... ... [ssoadmin@testvm bin]$
Step 4: Restart SSO
In this step, you will restart the server instance and check to make sure that its database model is loaded into the database:
[ssoadmin@testvm bin]$ ./standalone.sh
...
21:14:37,090 INFO [org.jboss.as] (MSC service thread 1-2) WFLYSRV0049: Red Hat Single Sign-On 7.4.0.GA (WildFly Core 10.1.2.Final-redhat-00001) starting
...
21:14:42,034 INFO [org.jboss.as.connector.subsystems.datasources] (MSC service thread 1-6) WFLYJCA0001: Bound data source [java:jboss/datasources/KeycloakMariaDBDS]
...
21:14:49,568 INFO [org.keycloak.connections.jpa.updater.liquibase.LiquibaseJpaUpdaterProvider] (ServerService Thread Pool -- 67) Initializing database schema. Using changelog META-INF/jpa-changelog-master.xml
...
21:15:02,735 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: Red Hat Single Sign-On 7.4.0.GA (WildFly Core 10.1.2.Final-redhat-00001) started in 26903ms - Started 598 of 893 services (602 services are lazy, passive or on-demand)
Connect to the MariaDB or MySQL database and check the SSO database model:
[root@testvm ~]# mysql -h localhost -urhsso74 -predhat MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | rhsso74 | +--------------------+ 2 rows in set (0.00 sec) MariaDB [(none)]> MariaDB [(none)]> use `rhsso74`; MariaDB [rhsso74]> show tables; +-------------------------------+ | Tables_in_rhsso74 | +-------------------------------+ | ADMIN_EVENT_ENTITY | | ASSOCIATED_POLICY | | AUTHENTICATION_EXECUTION | | AUTHENTICATION_FLOW | | AUTHENTICATOR_CONFIG | | AUTHENTICATOR_CONFIG_ENTRY | | BROKER_LINK | | CLIENT | | CLIENT_ATTRIBUTES | | CLIENT_AUTH_FLOW_BINDINGS | | CLIENT_DEFAULT_ROLES | | CLIENT_INITIAL_ACCESS | | CLIENT_NODE_REGISTRATIONS | | CLIENT_SCOPE | | CLIENT_SCOPE_ATTRIBUTES | | CLIENT_SCOPE_CLIENT | | CLIENT_SCOPE_ROLE_MAPPING | | CLIENT_SESSION | | CLIENT_SESSION_AUTH_STATUS | | CLIENT_SESSION_NOTE | | CLIENT_SESSION_PROT_MAPPER | | CLIENT_SESSION_ROLE | | CLIENT_USER_SESSION_NOTE | | COMPONENT | | COMPONENT_CONFIG | | COMPOSITE_ROLE | | CREDENTIAL | | DATABASECHANGELOG | | DATABASECHANGELOGLOCK | | DEFAULT_CLIENT_SCOPE | | EVENT_ENTITY | | FEDERATED_IDENTITY | | FEDERATED_USER | | FED_USER_ATTRIBUTE | | FED_USER_CONSENT | | FED_USER_CONSENT_CL_SCOPE | | FED_USER_CREDENTIAL | | FED_USER_GROUP_MEMBERSHIP | | FED_USER_REQUIRED_ACTION | | FED_USER_ROLE_MAPPING | | GROUP_ATTRIBUTE | | GROUP_ROLE_MAPPING | | IDENTITY_PROVIDER | | IDENTITY_PROVIDER_CONFIG | | IDENTITY_PROVIDER_MAPPER | | IDP_MAPPER_CONFIG | | KEYCLOAK_GROUP | | KEYCLOAK_ROLE | | MIGRATION_MODEL | | OFFLINE_CLIENT_SESSION | | OFFLINE_USER_SESSION | | POLICY_CONFIG | | PROTOCOL_MAPPER | | PROTOCOL_MAPPER_CONFIG | | REALM | | REALM_ATTRIBUTE | | REALM_DEFAULT_GROUPS | | REALM_DEFAULT_ROLES | | REALM_ENABLED_EVENT_TYPES | | REALM_EVENTS_LISTENERS | | REALM_REQUIRED_CREDENTIAL | | REALM_SMTP_CONFIG | | REALM_SUPPORTED_LOCALES | | REDIRECT_URIS | | REQUIRED_ACTION_CONFIG | | REQUIRED_ACTION_PROVIDER | | RESOURCE_ATTRIBUTE | | RESOURCE_POLICY | | RESOURCE_SCOPE | | RESOURCE_SERVER | | RESOURCE_SERVER_PERM_TICKET | | RESOURCE_SERVER_POLICY | | RESOURCE_SERVER_RESOURCE | | RESOURCE_SERVER_SCOPE | | RESOURCE_URIS | | ROLE_ATTRIBUTE | | SCOPE_MAPPING | | SCOPE_POLICY | | USERNAME_LOGIN_FAILURE | | USER_ATTRIBUTE | | USER_CONSENT | | USER_CONSENT_CLIENT_SCOPE | | USER_ENTITY | | USER_FEDERATION_CONFIG | | USER_FEDERATION_MAPPER | | USER_FEDERATION_MAPPER_CONFIG | | USER_FEDERATION_PROVIDER | | USER_GROUP_MEMBERSHIP | | USER_REQUIRED_ACTION | | USER_ROLE_MAPPING | | USER_SESSION | | USER_SESSION_NOTE | | WEB_ORIGINS | +-------------------------------+ 93 rows in set (0.01 sec) MariaDB [rhsso74]> select ID, NAME, ACCOUNT_THEME, ADMIN_THEME, DEFAULT_LOCALE from REALM; +----------------+----------------+------------------+-------------+----------------+ | ID | NAME | ACCOUNT_THEME | ADMIN_THEME | DEFAULT_LOCALE | +----------------+----------------+------------------+-------------+----------------+ | master | master | keycloak-preview | NULL | NULL | +----------------+----------------+------------------+-------------+----------------+ 1 rows in set (0.00 sec) MariaDB [rhsso74]>
Step 5: Recreate the admin user for SSO
This step is needed because you have switched the database SSO is using to MariaDB or MySQL. The admin user created earlier is in the default H2 database, which is not used anymore:
[ssoadmin@testvm bin]$ ./add-user-keycloak.sh -r master -u admin -p redhat Added 'admin' to '/home/ssoadmin/RH-SSO_SETUP/RH-SSO_7.x/7.4.x/LATEST/rh-sso-7.4/standalone/configuration/keycloak-add-user.json', restart server to load user [ssoadmin@testvm bin]$
Step 6: Final testing and validation
Start the SSO server instance:
[ssoadmin@testvm bin]$ ./standalone.sh ... 22:20:04,239 INFO [org.jboss.as] (MSC service thread 1-1) WFLYSRV0049: Red Hat Single Sign-On 7.4.0.GA (WildFly Core 10.1.2.Final-redhat-00001) starting ... 22:20:22,469 INFO [org.keycloak.services] (ServerService Thread Pool -- 68) KC-SERVICES0006: Importing users from '/home/ssoadmin/RH-SSO_SETUP/RH-SSO_7.x/7.4.x/LATEST/rh-sso-7.4/standalone/configuration/keycloak-add-user.json' 22:20:23,322 INFO [org.keycloak.services] (ServerService Thread Pool -- 68) KC-SERVICES0009: Added user 'admin' to realm 'master' ... 22:20:23,949 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: Red Hat Single Sign-On 7.4.0.GA (WildFly Core 10.1.2.Final-redhat-00001) started in 19857ms - Started 598 of 893 services (602 services are lazy, passive or on-demand)
Verify that the admin user has been created in the database:
MariaDB [rhsso74]> select ID, USERNAME, REALM_ID from USER_ENTITY; +--------------------------------------+------------------+----------------+ | ID | USERNAME | REALM_ID | +--------------------------------------+------------------+----------------+ | 075d1cb9-fb4d-4437-80f8-f4397b1b5370 | admin | master | +--------------------------------------+------------------+----------------+ 1 row in set (0.00 sec) MariaDB [rhsso74]>
Access the admin console in the SSO server instance by opening your browser, loading http://localhost:8080/auth
, and logging in as admin/redhat
.
Next steps with SSO
To keep learning about using Red Hat's single sign-on technology, you can play with the SSO quickstarts and Keycloak quickstarts on GitHub. Also, check out the documentation for Red Hat's single sign-on technology and the SSO 7.4 release.
Coming up next ...
My next article in this series will show you how to deploy the SSO container image in OpenShift. Future articles will cover topics and use cases such as SSO migration and upgrades across different database flavors, and tricks and tips for connecting to an external database using a custom JDBC driver. I'll also share more powerful features of Red Hat's single sign-on technology and other topics related to SSO integration, such as integrating with third-party OpenID Connect and Security Assertion Markup Language (SAML) vendors, clustering while using Nginx as a load balancer or reverse proxy, and using the Proof Key for Code Exchange (PKCE) extension in SSO. Stay tuned!
Last updated: February 11, 2024