javapostgresqlkeycloakinfinispan

Infinispan doesn't write any sessions in JDBC persisted cache in Keycloak 21.0.2


I'm trying to configure database-persisted sessions in Keycloak 21.0.2 I have created my custom settings file for infinispan cache cache-ispn-jdbc-persistence.xml

<?xml version="1.0" encoding="UTF-8"?>

<infinispan
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="urn:infinispan:config:14.0 http://www.infinispan.org/schemas/infinispan-config-14.xsd"
        xmlns="urn:infinispan:config:14.0">

    <cache-container name="keycloak">
        <transport lock-timeout="60000" />
        <local-cache name="realms">
            <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">
            <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="2">
            <expiration />
            <persistence passivation="false">
                <string-keyed-jdbc-store
                        xmlns="urn:infinispan:config:store:jdbc:14.0"
                        dialect="POSTGRES"
                        shared="true"
                        segmented="false"
                        purge="false"
                        preload="true">
                    <connection-pool
                            connection-url="jdbc:postgresql://postgres:5432/keycloak?ApplicationName=keycloak-ispn"
                            username="dbuser"
                            password="dbpwd"
                            driver="org.postgresql.Driver"/>
                    <string-keyed-table create-on-start="true" fetch-size="10000" prefix="ispn">
                        <id-column name="id" type="VARCHAR(255)" />
                        <data-column name="datum" type="BYTEA" />
                        <timestamp-column name="timestamp" type="BIGINT" />
                    </string-keyed-table>
                </string-keyed-jdbc-store>
            </persistence>
        </distributed-cache>
        <distributed-cache name="clientSessions" owners="2">
            <expiration />
            <persistence passivation="false">
                <string-keyed-jdbc-store
                        xmlns="urn:infinispan:config:store:jdbc:14.0"
                        dialect="POSTGRES"
                        shared="true"
                        segmented="false"
                        purge="false"
                        preload="true">
                    <connection-pool
                            connection-url="jdbc:postgresql://postgres:5432/keycloak?ApplicationName=keycloak-ispn"
                            username="dbuser"
                            password="dppwd"
                            driver="org.postgresql.Driver"/>
                    <string-keyed-table create-on-start="true" fetch-size="10000" prefix="ispn">
                        <id-column name="id" type="VARCHAR(255)" />
                        <data-column name="datum" type="BYTEA" />
                        <timestamp-column name="timestamp" type="BIGINT" />
                    </string-keyed-table>
                </string-keyed-jdbc-store>
            </persistence>
        </distributed-cache>
        <distributed-cache name="authenticationSessions" owners="2">
            <expiration lifespan="-1"/>
        </distributed-cache>
        <distributed-cache name="offlineSessions" owners="2">
            <expiration lifespan="-1"/>
        </distributed-cache>
        <distributed-cache name="offlineClientSessions" owners="2">
            <expiration lifespan="-1"/>
        </distributed-cache>
        <distributed-cache name="loginFailures" owners="2">
            <expiration lifespan="-1"/>
        </distributed-cache>
        <local-cache name="authorization">
            <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"/>
        </replicated-cache>
        <local-cache name="keys">
            <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>
        <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"/>
        </distributed-cache>
    </cache-container>
</infinispan>

It creates following tables: ispn_clientSessions, ispn_clientSessions_META, ispn_sessions, ispn_sessions_META. The *_META tables store some data. However when I log in as admin in Keycloak ispn_clientSessions and ispn_sessions are staying emty. Also nothing is stored after logout. Restarting the Keycloak causes session destruction.

Please help me to figure out why sessions are not saved.


Solution

  • I have solved the problem myself. The cause why sessions tables were empty was that Keycloak prevents saving cached entities when infinispan is used as its local cache. It adds some flags that skip saving data. See: CacheDecorators class here

    So there are two ways to solve this. Either to use external instance of Infinispan and make Keycloak to use it, either patch the CacheDecorators class to turn off adding the SKIP_CACHE_STORE flags. I have chosen the second way. I assembled my own version of keycloak-model-infinispan.jar and mounted it into the Keycloak container. Thanks to Thomas Darimont and his solution