420.4 Keycloak and ABP framework applications - chempkovsky/CS82ANGULAR GitHub Wiki
- First, we will describe the steps for installing Keycloak. The steps include:
- Instaling PostgreSql
- Installing Keycloak
- Installing Infinispan
- Integrating Keycloak and Infinispan
- Each node will be installed in the separate virtual machine.
- Ubuntu 24.04 LTS will be used as the operating system for each node.
- We are not going to use clusters for now
- In this article we will describe the steps for integrating steps of Keycloak and Infinispan.
- Currently we failed to integrate Infinispan and Keycloak. But we will tell how we tried to achieve the result.
- A year ago we had success for a pair infinispan_15.0.7 and keycloak_25.0.4 with unreadable data in the Infinispan console
- Here is some discussions
- https://www.keycloak.org/server/caching
- https://github.com/keycloak/keycloak/discussions/12538
- https://github.com/keycloak/keycloak/discussions/21890
- https://github.com/keycloak/keycloak/issues/26064
- https://github.com/Kritika/medium/blob/main/cache-ispn.xml
- https://github.com/Kritika/medium/blob/main/infinispan.xml
- https://medium.com/@kritika.tripathi28/keycloak-quarkus-distribution-with-standalone-infinispan-set-up-db0d74d55c63
- Integration consists of four steps
- copying some libraries from Infinispan to Keycloak
- modification of the
/opt/keycloak-26.3.0/conf/cache-ispn.xml-file - modification of the
/opt/infinispan-server-15.2.0.Final/server/conf/infinispan.xml-file - running Keycloak with
--cache=ispnswitch
- One of the way to get correct integration setting is to use middleware_automation.keycloak
- maybe after deployment we will see the correct setting
- first goto to Deploy Keycloak single sign-on with Ansible
- the source (Infinispan)
/opt/infinispan-server-15.2.0.Final/lib/infinispan-commons-15.2.0.Final.jar
- destination (Keycloak)
/opt/keycloak-26.3.0/lib/lib/boot/infinispan-commons-15.2.0.Final.jar
- Note: copy to lib/boot folder (!!!)
- modify the file
sudo nano /opt/keycloak-26.3.0/conf/cache-ispn.xml
Click to show the code
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2019 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<infinispan
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:infinispan:config:15.0 http://www.infinispan.org/schemas/infinispan-config-15.0.xsd"
xmlns="urn:infinispan:config:15.0">
<cache-container name="keycloak">
<transport lock-timeout="60000"/>
<local-cache name="realms" simple-cache="true">
<encoding>
<key media-type="application/x-java-object"/>
<value media-type="application/x-java-object"/>
</encoding>
<memory max-count="10000"/>
</local-cache>
<local-cache name="users" simple-cache="true">
<encoding>
<key media-type="application/x-java-object"/>
<value media-type="application/x-java-object"/>
</encoding>
<memory max-count="10000"/>
</local-cache>
<distributed-cache name="sessions" owners="1">
<!--
<expiration lifespan="-1"/>
<memory max-count="10000"/>
-->
<remote-store xmlns="urn:infinispan:config:store:remote:15.0"
cache="sessions"
purge="false"
preload="false"
segmented="false"
shared="true"
raw-values="true"
marshaller="org.infinispan.commons.marshall.ProtoStreamMarshaller">
<!--
marshaller="org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory"
-->
<remote-server host="10.183.97.12" port="11222" />
<security>
<authentication server-name="infinispan">
<digest username="yury" password="Qq01011967" realm="default"/>
</authentication>
</security>
</remote-store>
</distributed-cache>
<distributed-cache name="authenticationSessions" owners="2">
<!--
<expiration lifespan="-1"/>
-->
<remote-store xmlns="urn:infinispan:config:store:remote:15.0"
cache="authenticationSessions"
purge="false"
preload="false"
segmented="false"
shared="true"
raw-values="true"
marshaller="org.infinispan.commons.marshall.ProtoStreamMarshaller">
<!--
marshaller="org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory"
-->
<remote-server host="10.183.97.12" port="11222" />
<security>
<authentication server-name="infinispan">
<digest username="yury" password="Qq01011967" realm="default"/>
</authentication>
</security>
</remote-store>
</distributed-cache>
<distributed-cache name="offlineSessions" owners="1">
<!--
<expiration lifespan="-1"/>
<memory max-count="10000"/>
-->
<remote-store xmlns="urn:infinispan:config:store:remote:15.0"
cache="offlineSessions"
purge="false"
preload="false"
segmented="false"
shared="true"
raw-values="true"
marshaller="org.infinispan.commons.marshall.ProtoStreamMarshaller">
<!--
marshaller="org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory"
-->
<remote-server host="10.183.97.12" port="11222" />
<security>
<authentication server-name="infinispan">
<digest username="yury" password="Qq01011967" realm="default"/>
</authentication>
</security>
</remote-store>
</distributed-cache>
<distributed-cache name="clientSessions" owners="1">
<!--
<expiration lifespan="-1"/>
<memory max-count="10000"/>
-->
<remote-store xmlns="urn:infinispan:config:store:remote:15.0"
cache="clientSessions"
purge="false"
preload="false"
segmented="false"
shared="true"
raw-values="true"
marshaller="org.infinispan.commons.marshall.ProtoStreamMarshaller">
<!--
marshaller="org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory"
-->
<remote-server host="10.183.97.12" port="11222" />
<security>
<authentication server-name="infinispan">
<digest username="yury" password="Qq01011967" realm="default"/>
</authentication>
</security>
</remote-store>
</distributed-cache>
<distributed-cache name="offlineClientSessions" owners="1">
<!--
<expiration lifespan="-1"/>
<memory max-count="10000"/>
-->
<remote-store xmlns="urn:infinispan:config:store:remote:15.0"
cache="offlineClientSessions"
purge="false"
preload="false"
segmented="false"
shared="true"
raw-values="true"
marshaller="org.infinispan.commons.marshall.ProtoStreamMarshaller">
<!--
marshaller="org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory"
-->
<remote-server host="10.183.97.12" port="11222" />
<security>
<authentication server-name="infinispan">
<digest username="yury" password="Qq01011967" realm="default"/>
</authentication>
</security>
</remote-store>
</distributed-cache>
<distributed-cache name="loginFailures" owners="2">
<!--
<expiration lifespan="-1"/>
-->
<remote-store xmlns="urn:infinispan:config:store:remote:15.0"
cache="loginFailures"
purge="false"
preload="false"
segmented="false"
shared="true"
raw-values="true"
marshaller="org.infinispan.commons.marshall.ProtoStreamMarshaller">
<!--
marshaller="org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory"
-->
<remote-server host="10.183.97.12" port="11222" />
<security>
<authentication server-name="infinispan">
<digest username="yury" password="Qq01011967" realm="default"/>
</authentication>
</security>
</remote-store>
</distributed-cache>
<local-cache name="authorization" simple-cache="true">
<encoding>
<key media-type="application/x-java-object"/>
<value media-type="application/x-java-object"/>
</encoding>
<memory max-count="10000"/>
</local-cache>
<replicated-cache name="work">
<!--
<expiration lifespan="-1"/>
-->
<remote-store xmlns="urn:infinispan:config:store:remote:15.0"
cache="work"
purge="false"
preload="false"
segmented="false"
shared="true"
raw-values="true"
marshaller="org.infinispan.commons.marshall.ProtoStreamMarshaller">
<!--
marshaller="org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory"
-->
<remote-server host="10.183.97.12" port="11222" />
<security>
<authentication server-name="infinispan">
<digest username="yury" password="Qq01011967" realm="default"/>
</authentication>
</security>
</remote-store>
</replicated-cache>
<local-cache name="keys" simple-cache="true">
<encoding>
<key media-type="application/x-java-object"/>
<value media-type="application/x-java-object"/>
</encoding>
<expiration max-idle="3600000"/>
<memory max-count="1000"/>
</local-cache>
<local-cache name="crl" simple-cache="true">
<encoding>
<key media-type="application/x-java-object"/>
<value media-type="application/x-java-object"/>
</encoding>
<expiration lifespan="-1"/>
<memory max-count="1000"/>
</local-cache>
<distributed-cache name="actionTokens" owners="2">
<!--
<encoding>
<key media-type="application/x-java-object"/>
<value media-type="application/x-java-object"/>
</encoding>
<expiration max-idle="-1" lifespan="-1" interval="300000"/>
<memory max-count="-1"/>
-->
<remote-store xmlns="urn:infinispan:config:store:remote:15.0"
cache="actionTokens"
purge="false"
preload="false"
segmented="false"
shared="true"
raw-values="true"
marshaller="org.infinispan.commons.marshall.ProtoStreamMarshaller">
<!--
marshaller="org.keycloak.cluster.infinispan.KeycloakHotRodMarshallerFactory"
-->
<remote-server host="10.183.97.12" port="11222" />
<security>
<authentication server-name="infinispan">
<digest username="yury" password="Qq01011967" realm="default"/>
</authentication>
</security>
</remote-store>
</distributed-cache>
</cache-container>
</infinispan>
- modify the file
sudo nano /opt/infinispan-server-15.2.0.Final/server/conf/infinispan.xml
Click to show the code
<infinispan
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:infinispan:config:15.2 https://infinispan.org/schemas/infinispan-config-15.2.xsd
urn:infinispan:server:15.2 https://infinispan.org/schemas/infinispan-server-15.2.xsd"
xmlns="urn:infinispan:config:15.2"
xmlns:server="urn:infinispan:server:15.2">
<!--
<jgroups>
<stack name="jdbc" extends="tcp">
<JDBC_PING2 stack.combine="REPLACE" stack.position="MPING" />
</stack>
</jgroups>
<cache-container>
<transport stack="jdbc" server:data-source="ds" />
</cache-container>
-->
<cache-container name="default" statistics="true">
<transport cluster="${infinispan.cluster.name:cluster}" stack="${infinispan.cluster.stack:tcp}" node-name="${infinispan.node.name:}"/>
<security>
<authorization/>
</security>
<distributed-cache name="sessions">
<expiration lifespan="-1"/>
<memory max-count="10000"/>
<encoding media-type="application/x-protostream"/>
</distributed-cache>
<distributed-cache name="authenticationSessions" owners="2">
<expiration lifespan="-1"/>
<encoding media-type="application/x-protostream"/>
</distributed-cache>
<distributed-cache name="offlineSessions" owners="1">
<expiration lifespan="-1"/>
<memory max-count="10000"/>
<encoding media-type="application/x-protostream"/>
</distributed-cache>
<distributed-cache name="clientSessions" owners="1">
<expiration lifespan="-1"/>
<memory max-count="10000"/>
<encoding media-type="application/x-protostream"/>
</distributed-cache>
<distributed-cache name="offlineClientSessions" owners="1">
<expiration lifespan="-1"/>
<memory max-count="10000"/>
<encoding media-type="application/x-protostream"/>
</distributed-cache>
<distributed-cache name="loginFailures" owners="2">
<expiration lifespan="-1"/>
<encoding media-type="application/x-protostream"/>
</distributed-cache>
<replicated-cache name="work">
<expiration lifespan="-1"/>
<encoding media-type="application/x-protostream"/>
</replicated-cache>
<distributed-cache name="actionTokens" owners="2">
<!--
<encoding>
<key media-type="application/x-java-object"/>
<value media-type="application/x-java-object"/>
</encoding>
-->
<expiration max-idle="-1" lifespan="-1" interval="300000"/>
<memory max-count="-1"/>
<encoding media-type="application/x-protostream"/>
</distributed-cache>
</cache-container>
<server xmlns="urn:infinispan:server:15.2">
<!--
<data-sources>
<data-source name="ds"
jndi-name="jdbc/postgres"
statistics="true">
<connection-factory driver="org.postgresql.Driver"
url="jdbc:postgresql://10.183.97.10:5432/infinispandb"
username="infinispan"
password="infinispan">
</connection-factory>
<connection-pool initial-size="1"
max-size="10"
min-size="3"
background-validation="1s"
idle-removal="1m"
blocking-timeout="1s"
leak-detection="10s"/>
</data-source>
</data-sources>
-->
<interfaces>
<interface name="public">
<inet-address value="${infinispan.bind.address:10.183.97.12}"/>
</interface>
</interfaces>
<socket-bindings default-interface="public" port-offset="${infinispan.socket.binding.port-offset:0}">
<socket-binding name="default" port="${infinispan.bind.port:11222}"/>
</socket-bindings>
<security>
<security-realms>
<security-realm name="default">
<!-- Uncomment to enable TLS on the realm -->
<!-- server-identities>
<ssl>
<keystore path="server.pfx"
password="password" alias="server"
generate-self-signed-certificate-host="localhost"/>
</ssl>
</server-identities-->
<properties-realm/>
</security-realm>
</security-realms>
</security>
<endpoints socket-binding="default" security-realm="default">
<endpoint>
<hotrod-connector name="hotrod">
<authentication>
<sasl mechanisms="DIGEST-MD5" server-name="infinispan" />
</authentication>
</hotrod-connector>
<rest-connector name="rest"/>
</endpoint>
</endpoints>
</server>
</infinispan>
- restart infinispan service
- run Keycloak with the command
cd /opt/keycloak-26.3.0
sudo /opt/keycloak-26.3.0/bin/kc.sh start --optimized --cache=ispn
- we had an issue with "actionTokens" at Infinispan side.