Keycloak on Fedora Workstation with Podman

Photo by Brett Jordan on Unsplash

Keycloak is an open source identity provider (IdP) with single-sign on (SSO) capabilities. It supports the most widely used enterprise authentication protocols, namely OpenID Connect (OIDC), OAuth 2.0, and SAML. With Keycloak, users sign in once and share the same identity across multiple applications and platforms in a transparent manner. On the other hand, applications defer authentication to Keycloak using a standard protocol without managing the authentication flow themselves.

This article will guide you through setting up Keycloak and using it on Fedora Linux with SSL/TLS enabled using Podman.

Keycloak boasts several advantages over competing solutions such as Dex and Authentik:

The steps described in this article will guide you through setting up Keycloak on Fedora Linux with SSL/TLS enabled using Podman. Once our Keycloak server is up and running, we will:

  1. Create the first realm example-com representing our organization
  2. Enforce mandatory MFA for all users in our realm
  3. Create the first user johndoe representing an employee in our organization
  4. Create the first client keycloak-spa corresponding to the Keycloak demo single-page application (SPA)
  5. Log in to the Keycloak realm via the demo application to validate the configuration

System requirements

To get started you will need a physical or virtual machine running Fedora Workstation with the following specifications:

  • Minimum 4G of RAM (8G+ recommended)
  • Minimum 2 vCPU cores (4+ vCPU recommended)
  • Sufficient available storage – a few GB should suffice

Generating certificates for SSL/TLS

Applications deferring authentication to Keycloak will exchange sensitive credentials during the authentication process. As such, never run Keycloak with plain HTTP in production as it transmits credentials in plaintext over the network. Instead, generate the necessary SSL/TLS certificates, add a custom root certificate authority (CA) to the system trust, and start Keycloak with HTTPs using the certificates to ensure a secure, encrypted connection.

Installing the OpenSSL command line tool

Install the OpenSSL package used for generating SSL/TLS certificates:

sudo dnf install --refresh -y openssl

Next, create the directory $HOME/ssl/ for these certificates and enter it:

mkdir -p "$HOME/ssl/"
pushd "$HOME/ssl/"

Generating the CA certificate-key pair

Now generate a CA key and certificate for internal use within the organization example.com. We will use the CA key to sign certificate signing requests (CSRs) resulting in SSL/TLS certificates used to encrypt HTTPs traffic for internal websites and services. The CA certificate are also used to verify the validity of the SSL/TLS certificates presented by internal websites and services. CAs serve as an anchor of trust so their certificates should be long lived, e.g. with a validity period of 10 years.

openssl req \
    -x509 \
    -new \
    -nodes \
    -keyout my-custom-ca.key \
    -sha256 \
    -days 3650 \
    -out my-custom-ca.crt \
    -subj '/CN=My custom CA/DC=localhost'

This creates a CA key my-custom-ca.key and the corresponding CA certificate my-custom-ca.crt.

Inspect the CA certificate with the following command:

$ openssl x509 -text -noout -in my-custom-ca.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            76:56:b9:13:b4:85:f4:36:0d:d0:2a:18:d3:de:f3:2f:25:76:f5:b0
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = My custom CA, DC = localhost
        Validity
            Not Before: Feb 25 02:11:46 2024 GMT
            Not After : Feb 22 02:11:46 2034 GMT
        Subject: CN = My custom CA, DC = localhost
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:ba:0b:7e:fb:88:e6:6f:f3:c2:3b:cc:3c:5d:18:
                    cf:bc:c1:ff:e3:98:3a:52:2c:82:dc:d7:14:75:8a:
                    58:fc:26:d7:97:9e:ee:73:c0:56:79:77:5b:97:96:
                    5c:f9:6a:d1:0c:bc:96:4d:e3:48:4c:e8:91:77:1e:
                    58:22:23:b2:7d:50:2e:2e:5d:c5:7a:85:0e:e4:b4:
                    73:64:5d:85:2a:81:fe:e1:04:3d:6a:5d:0f:99:4b:
                    e8:82:7b:c4:06:36:3f:67:b7:19:08:1b:56:28:d0:
                    b1:0d:f5:52:55:06:88:97:87:a5:be:ba:11:a2:eb:
                    a4:da:6d:c7:3e:1f:5d:46:1f:da:a3:26:19:0a:ea:
                    42:67:8e:ab:7a:77:d5:db:c0:24:d1:c7:10:86:b9:
                    ef:0a:ad:3f:22:8d:17:f5:26:1e:38:23:ba:5f:7c:
                    6b:f6:e8:41:1f:ed:6a:a6:77:3e:f6:55:ef:06:08:
                    f3:a8:f3:a3:4f:9b:d4:2c:fe:b0:62:c1:1d:8e:c0:
                    6f:97:d9:e4:ec:a7:e6:6d:62:31:8a:f7:3e:9a:4f:
                    3b:92:c4:04:b6:2c:9b:b2:4d:b8:bc:8a:72:c1:67:
                    9f:8a:60:cf:a5:7f:84:75:a3:c9:48:60:dd:6a:b9:
                    e4:ec:91:3f:6d:cc:ec:a3:8a:44:ea:1c:62:01:92:
                    09:2d
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier: 
                69:0F:42:C2:FC:D7:BB:79:D3:B6:5A:31:D9:A9:B0:3C:DA:C3:78:1D
            X509v3 Authority Key Identifier: 
                69:0F:42:C2:FC:D7:BB:79:D3:B6:5A:31:D9:A9:B0:3C:DA:C3:78:1D
            X509v3 Basic Constraints: critical
                CA:TRUE
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        8d:15:51:ae:d6:67:6f:18:b2:88:30:c2:91:a8:25:16:3c:97:
        19:f1:c6:d4:4a:95:0f:ec:21:97:f8:aa:ec:78:5d:22:66:4e:
        84:a6:e3:61:be:bd:a2:b3:6a:48:f7:0e:95:f5:95:02:14:63:
        28:cc:c8:6d:07:86:3d:9d:f1:f5:8b:5c:a9:4f:d2:98:0d:1a:
        26:cd:3e:ef:8c:e7:0c:e6:10:31:94:ad:c3:6c:83:82:d9:7e:
        fe:c7:85:c4:40:d7:36:7a:fb:6e:79:f9:c4:64:77:59:d6:6c:
        f5:24:36:fd:f4:2a:97:ec:58:0c:c2:6c:16:87:d6:4f:7e:88:
        9d:16:c8:fa:5f:aa:44:52:3b:36:99:34:64:e2:b9:a8:1b:e8:
        f2:94:95:ab:ae:12:42:ab:11:4d:9b:e5:c3:5c:85:07:2c:1e:
        7e:2e:ef:88:ad:44:eb:90:a0:b1:28:c5:a6:4f:0e:1c:47:6a:
        34:da:a0:5a:1a:9a:a9:b0:fe:77:f1:e3:99:90:59:47:4b:52:
        d2:e5:5d:9b:46:6e:04:fe:4f:87:75:13:ab:0a:a8:74:c4:c8:
        80:54:cd:6b:db:4a:ee:86:bc:5c:32:9e:5f:29:8b:50:3f:0c:
        ab:32:49:ff:ce:36:9c:cd:e4:4c:78:da:ce:a1:4d:a5:a3:84:
        51:41:52:49

Look out for the following fields when inspecting a CA certificate:

  • Issuer: the subject of the authority who issued the certificate. In the case of a root CA, this is the CA itself
  • Subject: who this certificate represents
  • X509v3 extensions: metadata indicating the nature of the certificate (CA:TRUE) and associated identity information

Be accustomed to inspecting certificates with the command shown above as it is useful for troubleshooting when certificates do not function as expected, e.g. when your browser warns that a certificate is invalid even though you already trust the root CA that signed it.

Before we proceed, add the CA certificate to the system trust. This ensures that any certificates issued by this CA are recognized as valid and trustworthy.

sudo trust anchor --store my-custom-ca.crt
sudo update-ca-trust

Generating a CSR for our Keycloak instance

Now generate a CSR for the Keycloak instance which will be exposed on https://localhost:8443/.

openssl req \
    -new \
    -newkey rsa:2048 \
    -nodes \
    -keyout localhost.key \
    -sha256 \
    -out localhost.csr \
    -subj '/CN=My custom certificate/DC=localhost' \
    -addext 'subjectAltName=DNS:localhost' \
    -addext 'basicConstraints=critical,CA:FALSE' \
    -addext 'keyUsage=digitalSignature' \
    -addext 'extendedKeyUsage=serverAuth'

This generates a certificate key localhost.key and the corresponding CSR localhost.csr. The CSR is then handed over to the CA for signing which generates an SSL/TLS certificate for use in the Keycloak instance.

Inspect the CSR with a similar command:

$ openssl req -text -noout -in localhost.csr
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: CN = My custom certificate, DC = localhost
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:dc:15:3a:92:03:aa:26:c9:1f:b2:a7:fb:3a:70:
                    6a:64:cc:f7:2e:68:88:3b:44:88:d7:f7:59:86:4c:
                    94:c5:88:65:4d:4c:2c:f5:e3:6d:02:8b:e9:16:b8:
                    fc:b1:7b:e1:ca:dd:17:12:75:7e:3b:97:78:01:bd:
                    e9:e4:a2:9c:c3:62:74:e6:32:00:6a:3f:9a:4d:e6:
                    d5:46:b0:c3:79:40:d3:8c:18:6c:41:0b:b8:6f:84:
                    15:bf:37:29:7f:46:d9:5d:0f:2a:d9:06:21:1d:17:
                    64:fb:ec:9f:c1:62:0e:e5:df:48:cf:c9:0e:ea:3e:
                    47:4e:dd:00:95:ac:38:fb:03:bf:8b:13:34:57:49:
                    01:26:05:06:d5:dc:39:34:12:2e:2b:f5:a7:3a:d1:
                    03:94:ce:5c:2b:28:67:2e:2d:09:85:b6:53:0a:f3:
                    9b:00:62:29:d5:84:df:e0:b4:a9:0a:81:a1:f3:0a:
                    e3:fc:71:5d:fe:d7:c7:8b:f7:e5:bb:e6:51:0a:5f:
                    d5:06:5d:7f:cf:48:28:96:b6:d0:a4:60:6f:f5:08:
                    0f:ce:6f:a3:8f:c4:b7:db:c0:79:33:1b:02:e8:ad:
                    95:fc:df:b9:6a:ef:31:f2:1c:11:3c:56:4a:4c:07:
                    1e:53:24:d6:36:2a:e3:3e:4f:3b:b8:64:68:56:70:
                    81:29
                Exponent: 65537 (0x10001)
        Attributes:
            Requested Extensions:
                X509v3 Subject Alternative Name: 
                    DNS:localhost
                X509v3 Basic Constraints: critical
                    CA:FALSE
                X509v3 Key Usage: 
                    Digital Signature
                X509v3 Extended Key Usage: 
                    TLS Web Server Authentication
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        ce:e7:20:cd:f4:86:86:0e:66:95:4d:59:1c:8b:94:9e:8b:dd:
        97:ac:96:8e:bd:ea:96:c7:e4:2f:a8:af:fa:71:e9:aa:ce:85:
        f1:bd:62:a5:8f:5b:07:f1:25:f0:c9:0f:b1:9e:ef:85:af:fc:
        cd:1b:09:e0:c5:41:0b:26:67:35:32:9e:8a:c8:b5:97:14:d6:
        74:e6:dc:9b:de:bf:06:b1:10:28:29:33:c0:48:7c:93:28:29:
        1b:92:43:ae:0c:2c:37:d0:ba:ac:bc:92:c9:61:e8:d1:ba:67:
        ab:36:ee:cb:ad:bc:df:7e:12:92:e4:95:34:a9:4c:c0:8d:3b:
        90:01:37:b0:bf:9b:41:94:52:a6:a9:a2:9b:87:f8:11:bf:80:
        4e:68:6a:37:11:82:12:50:56:f1:e8:fb:2c:1e:5d:e2:7f:27:
        f9:18:f0:32:e0:d8:75:e6:e2:be:4d:62:10:5d:ac:cb:fd:22:
        65:3d:84:74:cf:f6:34:78:ea:85:29:49:52:b2:5d:96:ff:40:
        cb:e7:cb:4d:0a:c3:da:8b:af:92:5d:51:74:98:49:7a:66:da:
        33:ef:5e:95:ca:f0:7a:2b:19:bd:82:56:2f:c1:08:8e:33:37:
        7a:76:88:cb:81:9c:56:77:dc:ac:6c:b4:a0:c2:8d:ff:8e:6e:
        a6:7e:dd:4f

Here, pay attention to the requested extensions, in particular the X509v3 Subject Alternative Name which defines the DNS domain name(s) for which the signed certificate will be valid.

Signing our CSR with the CA key

Pass this CSR over to the CA for signing. SSL/TLS certificates should be renewed on a regular basis so set the validity period to a shorter interval, e.g. 1 year.

openssl x509 \
    -req \
    -days 365 \
    -in localhost.csr \
    -CA my-custom-ca.crt \
    -CAkey my-custom-ca.key \
    -out localhost.crt \
    -set_serial 01 \
    -sha256 \
    -copy_extensions copy

The -copy-extensions copy option preserves the CSR requested extensions in the signed certificate localhost.crt. Confirm this is the case:

$ openssl x509 -text -noout -in localhost.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = My custom CA, DC = localhost
        Validity
            Not Before: Feb 25 03:31:09 2024 GMT
            Not After : Feb 24 03:31:09 2025 GMT
        Subject: CN = My custom certificate, DC = localhost
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:dc:15:3a:92:03:aa:26:c9:1f:b2:a7:fb:3a:70:
                    6a:64:cc:f7:2e:68:88:3b:44:88:d7:f7:59:86:4c:
                    94:c5:88:65:4d:4c:2c:f5:e3:6d:02:8b:e9:16:b8:
                    fc:b1:7b:e1:ca:dd:17:12:75:7e:3b:97:78:01:bd:
                    e9:e4:a2:9c:c3:62:74:e6:32:00:6a:3f:9a:4d:e6:
                    d5:46:b0:c3:79:40:d3:8c:18:6c:41:0b:b8:6f:84:
                    15:bf:37:29:7f:46:d9:5d:0f:2a:d9:06:21:1d:17:
                    64:fb:ec:9f:c1:62:0e:e5:df:48:cf:c9:0e:ea:3e:
                    47:4e:dd:00:95:ac:38:fb:03:bf:8b:13:34:57:49:
                    01:26:05:06:d5:dc:39:34:12:2e:2b:f5:a7:3a:d1:
                    03:94:ce:5c:2b:28:67:2e:2d:09:85:b6:53:0a:f3:
                    9b:00:62:29:d5:84:df:e0:b4:a9:0a:81:a1:f3:0a:
                    e3:fc:71:5d:fe:d7:c7:8b:f7:e5:bb:e6:51:0a:5f:
                    d5:06:5d:7f:cf:48:28:96:b6:d0:a4:60:6f:f5:08:
                    0f:ce:6f:a3:8f:c4:b7:db:c0:79:33:1b:02:e8:ad:
                    95:fc:df:b9:6a:ef:31:f2:1c:11:3c:56:4a:4c:07:
                    1e:53:24:d6:36:2a:e3:3e:4f:3b:b8:64:68:56:70:
                    81:29
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Alternative Name: 
                DNS:localhost
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Key Usage: 
                Digital Signature
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication
            X509v3 Subject Key Identifier: 
                F0:5D:A9:79:38:3B:83:EA:D0:C6:CF:91:0E:6F:67:72:DE:45:3A:04
            X509v3 Authority Key Identifier: 
                A1:EA:2F:AB:B1:95:AE:9C:56:48:1C:B5:6B:42:8A:61:2C:0B:DB:18
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        c1:b0:c6:89:64:76:b1:ab:2e:bc:c7:fd:bd:d2:31:9f:20:8d:
        c0:8e:1d:d7:70:f1:a6:72:7d:49:23:33:f3:f5:e6:2d:eb:20:
        f4:c5:ea:a1:f2:1b:24:a2:ad:b9:b6:c9:03:66:03:dd:1b:41:
        f2:21:c7:ed:31:21:63:21:56:2d:a1:5d:31:cd:91:85:8f:ef:
        a3:84:b0:34:59:ba:30:2b:da:ec:c5:55:8e:5d:c9:a6:da:e4:
        24:9e:76:b5:ca:83:46:fb:91:33:43:26:53:93:5c:2f:52:c0:
        23:ce:63:3f:ab:1e:46:89:cf:6c:3c:a4:26:80:76:b1:d6:85:
        d6:84:9a:db:6b:93:fe:3b:51:1a:2e:b8:8b:c7:76:c0:e1:bd:
        2d:cb:1d:de:fe:13:a4:57:18:76:b9:76:dd:5a:6f:79:49:cf:
        ed:44:b8:4b:97:ac:81:87:55:1c:0b:30:3b:84:ae:27:8a:97:
        bc:72:c8:96:65:f1:bd:63:85:0e:4c:d7:9d:4e:e4:9d:4d:b0:
        a1:8c:13:53:6a:a3:ba:cf:eb:ae:08:28:b2:5a:ec:0a:f4:e0:
        23:14:2f:c0:35:8b:da:a4:31:42:61:c9:2d:f9:57:3e:16:36:
        09:6c:59:37:3b:2e:06:2c:ee:9b:2c:66:fd:38:92:47:8c:2e:
        b8:5e:7c:19

Now leave the $HOME/ssl/ directory:

popd

Deploying the Keycloak instance with Podman

Set an initial administrator username and password. You should replace the examples below with more secure defaults:

export KEYCLOAK_ADMIN="admin" # replace me!
export KEYCLOAK_ADMIN_PASSWORD="P@ssw0rd" # replace me!

Now fetch the latest Keycloak image from Quay.io and run it:

podman run \
    --rm \
    -d \
    -p 8443:8443 \
    -e KEYCLOAK_ADMIN="${KEYCLOAK_ADMIN}" \
    -e KEYCLOAK_ADMIN_PASSWORD="${KEYCLOAK_ADMIN_PASSWORD}" \
    -v "$HOME/ssl/:/ssl/:U,Z,ro" \
    --name keycloak \
    quay.io/keycloak/keycloak:latest \
    start \
    --hostname=localhost \
    --https-certificate-file=/ssl/localhost.crt \
    --https-certificate-key-file=/ssl/localhost.key

The Keycloak instance binds to port 8443 and uses the certificate and key generated in a previous step for SSL/TLS encryption, bind-mounted into the container read-only with the correct ownership and SELinux context (U,Z,ro).

Visit https://localhost:8443/ in a web browser and click on “Administration Console” which presents a login portal. Enter the administrator credentials in the login portal and click “Sign In” which brings us to the administrator console.

Keycloak homepage
Keycloak master realm login portal
Keycloak master realm admin console

Notice that we are in the master realm. The master realm exists by default in Keycloak and should only be used to manage other realms. A realm in Keycloak is a tenant which represents different things depending on the context:

  • In a service provider context where a Keycloak instance is accessible to enterprise customers as a managed service, a tenant is an independent organization with its own identity and access management (IAM)
  • In an organizational context where a Keycloak instance is deployed for internal usage within the organization, a tenant is a department or organizational unit (OU) sharing a common base IdP such as the top-level corporate Active Directory domain

Creating a realm for the organization

Now create a realm for the example.com organization.

Click on the dropdown to the top left and select “Create realm”.

Create a new realm

Fill in example-com as the realm name and click “Create”.

Create example-com realm

Observe that we are now in the administration console for the example-com realm.

example-com realm admin console

Enforcing mandatory MFA for all users in the realm

MFA is the practice of adding a second layer of authentication and is widely employed by organizations. Instead of solely verifying what a person “knows” (the password), MFA also verifies what a person “has” to gain confidence in securely associating a natural entity with a digital identity. This is something such as a time-based one-time password (TOTP) generated by a mobile hardware or software device. This provides an additional layer of protection for accounts which may have their password compromised, though an account with a compromised password should change their password immediately in any case.

Keycloak supports enforcing mandatory MFA at both the user and realm level. Suppose the organization’s IT security policy mandates that all corporate accounts be secured via MFA. This policy can then be satisfied by enabling OTP as a required action at the realm level. We’ll also enforce that passwords be changed at initial login so only the account owner knows their own password.

Navigate to the menu to the left and click “Authentication”, then select “Required actions” and ensure both “Configure OTP” and “Update Password” are enabled as default actions.

Keycloak - enforcing mandatory MFA for all users in the realm

Creating an account for John Doe

John Doe has just joined the organization as a developer. As part of the onboarding process, let’s create an account for John Doe.

Select “Users > Add User”.

Users > Add User

Fill in the username johndoe and any other fields as desired, then click “Create”.

Keycloak - create user johndoe

Navigate to the “Credentials” tab and click “Set password”.

Set a password for John Doe

Fill in a suitable initial password for John Doe and click “Save”.

Determine and confirm the initial password for John Doe

Click “Save password” to confirm the action.

Save the new password

Congratulations, you have created an account for John Doe and set an initial password!

Keycloak - password successfully created for John Doe

Creating a client for the Keycloak SPA demo application

Platforms and applications integrating with Keycloak do so via clients. A client represents an application from Keycloak’s perspective.

Let’s test the Keycloak instance using an application. Fortunately, the Keycloak project conveniently provides a demo application so we don’t have to write our own. But first, we need to create a client for the app.

Select “Clients > Create client”.

Keycloak - create a new client

Preserve the client type as “OpenID Connect” and fill in the client ID as keycloak-spa, then click “Next”.

Keycloak - fill in client name

Ensure “Standard flow” is checked and click “Next”.

Keycloak client capability config

Now fill in the following details and click “Save”:

  • Valid redirect URLs: https://www.keycloak.org/app/*
  • Web origins: https://www.keycloak.org (without a trailing slash)
Specify valid redirect URLs and web origin for client

Congratulations, you have set up your first client on Keycloak!

Keycloak client application created

Installing the Authenticator MFA app on Flathub

Before proceeding to log in as John Doe, remember that mandatory MFA is enabled so we’ll need an app to set it up during our first login.

Keycloak explicitly supports the following TOTP applications which can be installed on a mobile device:

But for a change, let’s see a TOTP app available on Fedora Linux. Authenticator is an open source GNOME application for generating TOTP codes available under the copyleft GPLv3+ license. It is part of the GNOME Circle, readily available on Flathub and integrates well with Fedora Workstation. Just make sure that Flathub is enabled as a repository source in GNOME Software, then find and install the app.

Enable the Flathub repository on GNOME Software for Fedora
Flathub Authenticator MFA app

Logging in as John Doe with SSO

Now visit the demo application at https://www.keycloak.org/app/, fill in the configuration and click “Save”:

  • Keycloak URL: https://localhost:8443 (without the trailing slash)
  • Realm: example-com
  • Client: keycloak-spa
Keycloak SPA demo configuration

Click “Sign in”.

Sign in to Keycloak SPA

Fill in John Doe’s username and initial password, then click “Sign in”.

Log in to example-com realm as johndoe

You will be prompted to configure MFA authentication based on TOTP. Open your Authenticator app, scan the QR code to add the application, then fill in the generated TOTP password and name the MFA device “Authenticator”. Click “Submit”.

Initial MFA setup for John Doe

Reset the initial password and ensure it is strong and secure, then click “Submit”.

Set a new password for John Doe

Congratulations, you are now logged in as John Doe in the Keycloak SPA demo app via your Keycloak instance!

Keycloak SPA login successful

Cleaning up

Stop the Keycloak instance, then delete the SSL/TLS certificates created earlier. The Keycloak container was configured to be deleted automatically once stopped via the –rm flag.

podman stop keycloak
sudo rm -rf "$HOME/ssl/"

Concluding remarks and going further

Keycloak is an open source, enterprise-ready IdP supporting the most widely used authentication protocols. This enables it to readily integrate with a wide range of applications and platforms, including enterprise-grade orchestration platforms such as Kubernetes. Furthermore, it can be readily deployed to a wide range of environments, including on traditional servers / VMs, as a standalone container with Podman (and Docker), and on container orchestration platforms such as Kubernetes and OpenShift.

We have barely scratched the surface of Keycloak configuration in this lab. Keycloak can act directly as an IdP backend, as in this lab, or act as a connector to existing enterprise IdP backends, such as LDAP and Active Directory. Furthermore, by associating users with groups and roles, platforms integrating with Keycloak for authentication can apply role-based access control (RBAC) to enterprise identities for a scalable method of managing access to resources in a centralized manner.

Fedora Project community

7 Comments

  1. RG

    Nice article Donald! I must say I struggled a bit with openssl and those crazy extensions but your commands were much clearer from what I was doing. I think it is worth adding that keycloak is the upstream version of the red hat sso. There were also some breaking changes starting version 18/20 onwards. As for the trust command… I was expecting chrome and mozilla to have their own ca-store… So how did this work… I need to verify and probably reproduce.

    • Thank you for your suggestions and glad you enjoyed the article 🙂 I find the OpenSSL commands arcane as well, and it doesn’t help that most sources out there cram all the command-line arguments in a single line which makes the entire command extremely difficult to parse (-:

      Regarding the Firefox / Chrome CA trust, I believe that they are configured to use the OS-level system trust for native package formats like rpm and deb, but for portable packages like Flatpak (and Snap), they can’t access the OS-level system trust by default so use their own CA trust database

    • Speaking of the breaking change in versions 18/20 onwards, we’ve deployed the Red Hat build of Keycloak (RHBK) on OpenShift using the certified operator in a PoC setting at our workplace, but soon realized that there’s no supported option to inject custom CA certificates for secure LDAPS connections to Active Directory with the current Quarkus distribution of Keycloak, at least not without building a custom container image, so we finally settled for Dex as our OIDC authentication solution for our production Kubernetes cluster which supports our particular use case (OIDC connector to Active Directory backend) 😉

  2. Marcelo Sales

    Nice article, congratulations. I wanted to further enrich this article with some information that may be useful.

    The first point would be the system requirements. To accomplish what you demonstrate in this article, this infrastructure would not be necessary. It could run everything with 1 vCPU and 512MB of RAM. Perhaps what you mentioned as recommended is for some productive environment and this has to be studied and analyzed according to the requirements.

    The second case is about connectivity with LDAPS. Surely Keycloak supports connection to LDAPS. There are several use cases for Keycloak acting as an identity federator through OIDC. Even using the operator, it is possible to map a volume with a truststore configured via keycloak start parameters; it is not necessarily necessary to customize an image to achieve this objective. And speaking of customizing the image, this is one of the best features I see in Keycloak, its immense customization and extension capacity. From a security point of view, it makes perfect sense to customize images with additional features since in this sense, each corporation has its own parameters and requirements.

    • Thank you for your input and suggestions, glad you enjoyed the article 🙂

      The minimum system requirements suggested in this article assume that the Keycloak container is running directly on a Fedora Workstation installation complete with a GNOME desktop environment. In our experience, modern editions of Fedora Workstation with the default GNOME desktop environment require at least 4G of RAM to run smoothly without locking up. Of course, if the container is run within a headless Fedora Server installation then 1G of RAM should be enough. For production deployments, we recommend deploying on an existing Kubernetes or OpenShift cluster using the Keycloak operator which automates much of the configuration and setup.

      Regarding LDAPS support with a custom CA, we might have missed something since we’re not all that familiar with Quarkus or the Java ecosystem in general, but it would be helpful if the option for configuring a custom CA for LDAPS connections was exposed directly via the Keycloak CR under a single key, perhaps a reference to a secret containing the CA certificate like with Dex, or the process of doing so more clearly documented on the official website since we assume it’s a common requirement in enterprises. Though I agree that most medium to large enterprises with complex requirements will likely need to customize the Keycloak image for their specific use cases either way.

  3. Tom

    Would be nice to break down those openssl commands, and maybe use a config file. I always struggle with the openssl swiss army knife, but I was/am trying to create the certificate signed by an existing authority. Not sure I did it all right, but “start-dev” instead of a “start” enabled me to get things up and running (probably because the parent certificate wasnt in the trust store for keycloak’s container).

    I appreciate the great article – it allowed me to get a OIDC server up and running so I can continue development on some software!

    • Thanks for your suggestions and glad you managed to get Keycloak up and running with the instructions presented in this article 🙂

      Indeed, the OpenSSL swiss army knife is its own beast and it was only until very recently that I started to really understand what some of those command-line options mean and how they work (-:

Comments are Closed

The opinions expressed on this website are those of each author, not of the author's employer or of Red Hat. Fedora Magazine aspires to publish all content under a Creative Commons license but may not be able to do so in all cases. You are responsible for ensuring that you have the necessary permission to reuse any work on this site. The Fedora logo is a trademark of Red Hat, Inc. Terms and Conditions