Configuring X.509 Client Certificate Based User Authentication in Red Hat Build of Keycloak with a Customer Trust Heirarchy [RHBK]
Note
If you found this repo helpful or you found a bug, please feel free to submit a PR, drop me an email [email protected], or even just star the repo. I welcome any and all feedback.
This repository outlines the steps needed to configure X.509 certificate based user authentication. This is useful in such circumstances as clients wishing to use a HSPD-12 compliant PIV, CAC, or other similar "smart" card that uses client certificates to provide attestation. It includes not only the steps needed to configure RHBK (Red Hat build of Keycloak), but also how to create a simple certificate trust heirarchy to test this.
Note this is made available for demonstration purposes and is not representative of a production ready configuration. Further steps would be required.
Thank you to GitHub chelliot-rh for this kindly assistance with creating and testing this solution.
-
Make directories we will need:
mkdir -p rhbk-testing/CA
-
Change directories:
cd rhbk-testing/CA
-
We're going to have to create a X509 certificate trust heirarchy in order to properly test this out. We'll first create a root-CA and 2 end-entity certificates for the user1 and server that we will use to test. Since we're creating a new root-CA, we will also have to configure the trust heirarchy.
-
Generate the private key and pem encoded certificate for the root-CA:
openssl ecparam -out CA.consulting.redhat.com.key -name secp384r1 -genkey openssl req -x509 -new -key CA.consulting.redhat.com.key -out CA.consulting.redhat.com.crt -outform pem -sha384 -subj "/C=US/ST=VA/L=TYSONS/O=RED HAT/OU=CONSULTING/CN=CA.consulting.redhat.com"
-
Now that we have our CA, we will generate private keys for the server (
rhbksrvr
) and client (user1
)openssl ecparam -out rhbksrvr.consulting.redhat.com.key -name secp384r1 -genkey openssl ecparam -out user1.consulting.redhat.com.key -name secp384r1 -genkey
-
Create a Certificate Signing Request (CSR) for the newly created server (
rhbksrvr
) and client (user1
) keys:openssl req -new -nodes -key rhbksrvr.consulting.redhat.com.key -outform pem -out rhbksrvr.consulting.redhat.com.csr -sha384 -subj "/C=US/ST=VA/L=TYSONS/O=RED HAT/OU=CONSULTING/CN=rhbksrvr.consulting.redhat.com" openssl req -new -nodes -key user1.consulting.redhat.com.key -outform pem -out user1.consulting.redhat.com.csr -sha384 -subj "/C=US/ST=VA/L=TYSONS/O=RED HAT/OU=CONSULTING/CN=user1.consulting.redhat.com"
-
Use the root-CA you created in step 4 to sign the server and user1 CSRs:
openssl x509 -req -in rhbksrvr.consulting.redhat.com.csr -CA CA.consulting.redhat.com.crt -CAkey CA.consulting.redhat.com.key -CAcreateserial -out rhbksrvr.consulting.redhat.com.crt -days 2048 -sha384 openssl x509 -req -in user1.consulting.redhat.com.csr -CA CA.consulting.redhat.com.crt -CAkey CA.consulting.redhat.com.key -CAcreateserial -out user1.consulting.redhat.com.crt -days 2048 -sha384
-
Convert the pem format certicate to PKCS12 format:
openssl pkcs12 -export -out rhbksrvr.consulting.redhat.com.p12 -inkey rhbksrvr.consulting.redhat.com.key -in rhbksrvr.consulting.redhat.com.crt -certfile CA.consulting.redhat.com.crt -password pass:JBossRocks#123 -name "rhbksrvr.consulting.redhat.com" openssl pkcs12 -export -out user1.consulting.redhat.com.p12 -inkey user1.consulting.redhat.com.key -in user1.consulting.redhat.com.crt -certfile CA.consulting.redhat.com.crt -password pass:JBossRocks#123 -name "user1.consulting.redhat.com"
-
Now convert the PKCS12 format files to Java Keystore (JKS) format:
keytool -importkeystore -destkeystore rhbksrvr.consulting.redhat.com.jks -srckeystore rhbksrvr.consulting.redhat.com.p12 -srcstoretype PKCS12 -srcalias "rhbksrvr.consulting.redhat.com" -destalias "rhbksrvr.consulting.redhat.com" -srcstorepass JBossRocks#123 -deststorepass JBossRocks#123 keytool -importkeystore -destkeystore user1.consulting.redhat.com.jks -srckeystore user1.consulting.redhat.com.p12 -srcstoretype PKCS12 -srcalias "user1.consulting.redhat.com" -destalias "user1.consulting.redhat.com" -srcstorepass JBossRocks#123 -deststorepass JBossRocks#123
-
Let's add our root CA to a trusted CAs file:
cat CA.consulting.redhat.com.crt >> CA.crt
-
Convert that trusted CAs fiile to a java keystore truststore:
keytool -import -alias "CA.consulting.redhat.com" -file CA.consulting.redhat.com.crt -keystore trusts.jks -storepass JBossRocks#123 -noprompt
-
Download
Red Hat build of Keycloak 24.0.6 Server
: Red Hat build of Keycloak Download -
Switch up a directory so that you're in
./rhbk-testing
cd ..
-
Copy the downloaded RHBK to the
./rhbk-testing
directorycp ~/Downloads/rhbk-24.0.6.zip .
-
Unzip RHBK:
unzip rhbk-24.0.6.zip
-
Change directories into the new rhbk directory:
cd ./rhbk-24.0.6
-
Copy the previously created truststore (
trusts.jks
) and the server's PEM encoded certificate/key pair (rhbksrvr.consulting.redhat.com.crt
&rhbksrvr.consulting.redhat.com.key
) into the current directory:cp ../CA/trusts.jks . cp ../CA/rhbksrvr.consulting.redhat.com.crt . cp ../CA/rhbksrvr.consulting.redhat.com.key .
-
Add the PKCS12 certificate/key pair file
rhbk-testing/CA/user1.consulting.redhat.com.p12
to your browser with passwordJBossRocks#123
-
We'll now start rhbk. We will need to pass in the following arguments though:
Argument Value Purpose --hostname
0.0.0.0
Allowing us to explicitly set the hostname RHBK will listen on --https-certificate-file
./rhbksrvr.consulting.redhat.com.crt
The location of the public key certificate that RHBK will present to clients connecting --https-certificate-key-file
./rhbksrvr.consulting.redhat.com.key
The location of the private key that RHBK will present to clients connecting --https-trust-store-file
./trusts.jks
The location of the truststore to be used for validating connecting clientts in the case of mutual TLS --https-trust-store-password
JBossRocks#123
The password for the https-trust-store-file --https-trust-store-type
jks
The format of https-trust-store-file --https-client-auth
request
By setting request, RHBK will request client certificates as part of a mTLS connection. It will still succeed without a client certificate when set to request
. To mandate client certificates set this torequired
./bin/kc.sh start --https-certificate-file=./rhbksrvr.consulting.redhat.com.crt --https-certificate-key-file=./rhbksrvr.consulting.redhat.com.key --https-trust-store-file=./trusts.jks --https-trust-store-password=JBossRocks#123 --https-trust-store-type=jks --hostname=0.0.0.0 --hostname-debug=true --https-client-auth=request --verbose
-
Once RHBK is up and running, open https://0.0.0.0:8443 in the browser of your choice. You've not setup your browser to trust this CA, so simply select proceed anyways:
-
Examine the certificate in your browser and confirm it's the one we supplied on the command line:
-
Create an administrative user of your choice. In my case I used
admin
and clickCreate user
: -
It should confirm the user was created. Now click
Open Administration Console
: -
Now supply your newly created admin credentials and click
Sign In
: -
Now from the dropdown menu on the topright, click
Create realm
: -
Name the new realm
x509-test
, clickCreate
: -
Go to Authentication on the left hand side menu:
-
Select the
brower
and in the vertical menu, selectDuplicate
: -
Name it
x509-browser-flow
and clickDuplicate
: -
To the newly created
x509-browser-flow
clickAdd step
: -
Add a
X509/Validate Username Form
step and clickAdd
-
Shift
X509/Validate Username Form
step to belowIdentity Provider Redirector
and set the Requirement field toAlternative
-
Click the gear icon next to the
X509/Validate Username Form
step: -
In the config popup set
Alias
tox509-step
. Alter theA regular expression to extract user idenity
field toCN=(.*?)(?:,|$)
. Set theUser mapping method
toUsername or Email
and clear out theA name of user attribute
field. Lastly clickSave
. This will examine the certificate presented by the client and will lookup a user based on the commonname, CN, field of the certificate: -
Now click the
Action
menu in the top right and selectBind Flow
: -
Choose
Browser flow
and clickSave
: -
Go to Users:
-
Click
Create new user
-
Set the
Username
to the CN we created for our client user, in this caseuser1.consulting.redhat.com
and clickCreate
: -
Now in a new private window in the brower you added the client certificate to, navigate to https://0.0.0.0:8443/realms/x509-test/account/#/. It should now prompt you for the client certificate, which you should elect to provide:
-
RHBK should now ask if you want to continue to login via certificate as that user. Click
Continue
-
It will now ask you to supply some basic user information for the account. Please supply it and click
Submit
: -
You should now be successfully logged in as
user1.consulting.redhat.com
to thex509-test
realm of RHBK!