5

I need to integrate keycloak with an existing application. Users log in with username and password. Unfortunately, the application supports case-sensitive usernames and must continue to do so.

When creating the Custom User Storage Provider, at the entry point public UserModel getUserByUsername(String username, RealmModel realm) I get the username, but it has already been converted to a case insensitive String.

Here is an example which illustrates the situation.

username input received username users in database
John Doe john doe john doe, John Doe

I am aware that keycloak does not support case sensitive users, but for retrieving the users from the database I need to be able to distinguish the users. Is it possible to access the original input of the username?

lio
  • 53
  • 1
  • 3

1 Answers1

7

like you noticed correctly, usernames (and also email) are converted to lowercase in Keycloak. This behaviour is introduced by the UserCacheSession-class. The only way i found to get around this is to disable user caching globally in the Keycloak instance. This can be done by setting the appropriate configuration values inside standalone.xml, standalone-ha.xml or domain.xml (depending on your setup like described here).

The config block should be changed from

<spi name="userCache">
    <provider name="default" enabled="true"/>
</spi>

to

<spi name="userCache">
    <provider name="default" enabled="false"/>
</spi>

You can also use the JBoss CLI for this. If you're using a docker based setup, this could look like the following.

Dockerfile:

FROM jboss/keycloak:latest
USER root
COPY disable-usercache.cli /opt/jboss/startup-scripts/disable-usercache.cli
USER 1000

disable-usercache.cli:

embed-server --server-config=standalone-ha.xml --std-out=echo
batch

/subsystem=keycloak-server/spi=userCache/provider=default/:write-attribute(name=enabled,value=false)

run-batch
stop-embedded-server

If you need further samples you can have a look here.

If you've disabled the usercache, the username variable should be passed as given by the user.

Please note: of course you'll lose some performance if you turn of user caching because Keycloak will query the user storage each time a user has to be looked up. So it might be worth implementing your own case senisitive user cache and overwrite the default one by updating the userCache SPI inside your servers configuration file.

EDIT 03/2022: since Keycloak 17 is now powered by Quarkus, the mentioned WildFly script disable-usercache.cli won't work anymore. Until June 2022 you could use the legacy WildFly powered distribution of Keycloak 17 or have a look at the migration guide to see how to migrate towards Quarkus.

EDIT 11/2022: for Quarkus powered Keycloak instances, you'll have to locate the file conf/cache-ispn.xml. The default configuration contains a block for caching users like this:

<infinispan
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="urn:infinispan:config:11.0 http://www.infinispan.org/schemas/infinispan-config-11.0.xsd"
        xmlns="urn:infinispan:config:11.0">
    <cache-container name="keycloak">
        <!-- DELETE THIS BLOCK -->
        <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>
        <!-- UNTIL HERE -->
    </cache-container>
</infinispan>

Delete the appropriate block to disable the user cache. Read more about how to configure caching in the docs.

Robin Windey
  • 176
  • 1
  • 5