How to access the original case sensitive username input in custom user storage provider of keycloak?

Viewed 1757

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?

1 Answers

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 like 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.

Related