sso

Keycloak 26 Doesnt Show Custom User Attributes Tab

Had this problem and quite giving me a headache for a while, somehow the latest Keycloak version is not showing Attributes tab in Users menu which preventing me from creating a new custom user attribute.

Actually it is quite simple for enabling the custom attributes tab, we can go to Realm Settings menu and select the Unmanaged Attributes as Enabled.

The result would be like this,

Debugging HTTP Request and Responses in Red Hat Single Sign On

Red Hat Single Sign On (RHSSO) or its opensource project, which is Keycloak, is an open-source software product to allow single sign-on with identity and access management which can be deployed as a cloud service or containerized application. For this sample, we are trying to debug and print all http requests and responses that comes to RHSSO 7.4.6 which is being deployed on Openshift, for debugging purpose. But we also need to be very careful since it will print all http content which might contains sensitive values.

Okay, so lets start with creating a file “sso.cli” which have below content,

/subsystem=undertow/configuration=filter/expression-filter=requestDumperExpression:add(expression="dump-request")
/subsystem=undertow/server=default-server/host=default-host/filter-ref=requestDumperExpression:add

And deploy it as a ConfigMap,

$ oc create configmap jboss-cli --from-file=sso-extensions.cli=sso.cli

Next is mount it as a volume to RHSSO DeploymentConfig

$ oc set volume dc/sso --add --name=jboss-cli \
		-m /opt/eap/extensions -t configmap --configmap-name=jboss-cli \ 
		--default-mode='0755' --overwrite

Rollout the corresponding DeploymentConfig and we can observe that http request-response logs now is showing, we can use this curl command to test

$ curl --location --request POST 'https://sso.url/auth/realms/realm/protocol/openid-connect/userinfo' \
--header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiw......YXNzPlSVE2Oj0ImIQd6zQkw2UEMiEyJz8FrsVaS7x2M8mQjy-xQrSTGZVXKWR7KLHa-MCRx4S33Ja5nQuD3K_VVihKTyn4cOHnQ'

with below logs as the result

21:46:28,071 INFO  [io.undertow.request.dump] (default task-1) 
----------------------------REQUEST---------------------------
               URI=/auth/realms/realm/protocol/openid-connect/userinfo
 characterEncoding=null
     contentLength=0
       contentType=null
            header=accept=*/*
            header=accept-encoding=gzip, deflate, br
            header=forwarded=for=10.161.5.3;host=sso.url;proto=https
            header=authorization=Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiw......YXNzPlSVE2Oj0ImIQd6zQkw2UEMiEyJz8FrsVaS7x2M8mQjy-xQrSTGZVXKWR7KLHa-MCRx4S33Ja5nQuD3K_VVihKTyn4cOHnQ
            header=x-forwarded-proto=https
            header=x-forwarded-port=443
            header=x-forwarded-for=10.161.5.3
            header=content-length=0
            header=host=sso.url
            header=x-forwarded-host=sso.url
            locale=[]
            method=POST
          protocol=HTTP/1.1
       queryString=
        remoteAddr=/10.161.5.3:0
        remoteHost=10.161.5.3
            scheme=https
              host=sso.url
        serverPort=8443
          isSecure=true
--------------------------RESPONSE--------------------------
     contentLength=73
       contentType=application/json
            header=X-XSS-Protection=1; mode=block
            header=X-Frame-Options=SAMEORIGIN
            header=Referrer-Policy=no-referrer
            header=Date=Wed, 06 Nov 2024 14:46:28 GMT
            header=Connection=keep-alive
            header=WWW-Authenticate=Bearer realm="realm", error="invalid_token", error_description="Token verification failed"
            header=Strict-Transport-Security=max-age=31536000; includeSubDomains
            header=X-Content-Type-Options=nosniff
            header=Content-Type=application/json
            header=Content-Length=73
            status=401

==============================================================

Importing a Custom SPI into Keycloak Operator in Openshift

Keycloak Operator provide a convenient method for uploading a custom SPI into Keycloak instances, and that is by using an extensions inside Keycloak YAML operator.

apiVersion: keycloak.org/v1alpha1
kind: Keycloak
metadata: 
  namespace: my-redhat-sso
  labels:
    app: sso
spec:
  extensions:
    - >-
      https://url/custom-sso-spi-1.0.0.jar
  externalAccess:
    enabled: true
  externalDatabase:
    enabled: true
  instances: 1

Rollout your Keycloak pod, and you can see that Keycloak instance is now having a custom SPI embedded within it.

Error PKIX path building failed When Connecting to Keycloak with a Self Signed Certificate

For this scenario im using Keycloak version 17, which are being installed by using below command.

docker pull quay.io/keycloak/keycloak:17.0.0

And being run by using below command,

docker run -p 8443:8443 -e KC_HOSTNAME=localhost:8443 \ 
	-e KC_HOSTNAME_URL=https://localhost:8443 -e KC_DB=mysql \ 
	-e KC_DB_USERNAME=keycloak -e KC_DB_PASSWORD=password \ 
	-e KC_DB_URL=jdbc:mysql://192.168.56.1:3306/keycloak_db \
	quay.io/keycloak/keycloak:17.0.0 start

As for the Spring Boot sourcecode, we are utilizing the same code that are being used in below article,

https://github.com/edwin/spring-boot-and-rhsso

So lets start by setting up our application.properties to pointing to Keycloak’s HTTPS port

keycloak.auth-server-url=https://localhost:8443/
keycloak.realm=external
keycloak.resource=client
keycloak.public-client=false
keycloak.bearer-only=false
keycloak.principal-attribute=preferred_username
keycloak.credentials.secret=xxxxxx

But when HTTPS is created by using a self signed certificate, it will display below error from the Java application console.

o.k.adapters.KeycloakDeployment - Failed to load URLs from https://localhost:8443/realms/external/.well-known/openid-configuration
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:349)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:292)
	at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:287)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439)
	at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306)
	at java.base/sun.security.validator.Validator.validate(Validator.java:264)
	at java.base/sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:313)
	at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:222)
	at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:129)
	at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1340)
	... 86 common frames omitted
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
	at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
	at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297)
	at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434)
	... 92 common frames omitted

Thats why we need to include Keycloak’s custom SSL certificate into our Spring Boot application so that Spring Boot able to recognize a self sign certificate.

We can start by using OpenSSL to capture Keycloak’s SSL Certificate

echo "" | openssl s_client -connect localhost:8443  -showcerts 2>/dev/null | openssl x509 -out certfile.cert

It will generate a certificate which is belongs to Keycloak, next step is to create a truststore to contain the corresponding certificate. Below command will create a keystore with the name of “customcacerts” and its password which is “changeit”

keytool -import -alias ca -file certfile.cert \
         -keystore customcacerts  -storepass changeit

And we can run our Spring Boot application with below command, using the created truststore and its password as parameter.

java -Djavax.net.ssl.trustStore=customcacerts \
         -Djavax.net.ssl.trustStorePassword=changeit -jar spring-boot.jar

Error user_session_not_found when Using Keycloak’s UserInfo API

Had this error on Keycloak console,

09:49:35,417 WARN  [org.keycloak.events] (default task-145) type=USER_INFO_REQUEST_ERROR, 
realmId=internal, clientId=my-client-id, userId=null, ipAddress=10.20.24.35, 
error=user_session_not_found, auth_method=validate_access_token

Basically it happens when a specific user hitting a UserInfo API request bringing their active JWT token. JWT token is generated after a user successfully login to Keycloak, either via Login page or Rest API, and to be used in their internal application.

Also the error seems happening, generated JWT token seems to be invalid after 30minutes despite we update access token lifespan into 1 hour.

Finally i realized that this error keeps happening because i was updating the wrong configuration. It is supposed to be the “SSO Session Idle” configuration, in the “Tokens” tab in “Realm Settings” that need to be updated.

After change it into 1 Hour, i can see that my JWT token is successfully validated using UserInfo API for at most 1 hour after being created.