Skip to content

Keycloak-DatastoreProvider storing data in an Apache Cassandra NoSQL-database.

License

Notifications You must be signed in to change notification settings

opdt/keycloak-cassandra-extension

Repository files navigation

CI Maven Central Sonarcloud

Cassandra storage extension for Keycloak

Uses Apache Cassandra to store and retrieve entities of all storage areas except authorization and events. Requires Keycloak >= 23.0.0.

⚠️ Keycloak 23 support is still early stages and mostly untested. Use version 1.3.2-22.0.1 for Keycloak up until 22.x.x.

How to use

⚠️ Important information: Since map storage has been removed from Keycloak, using different storage providers for different storage areas (like users, roles) requires you to implement your own DatastoreProvider. If "cache mode" is active (KC_COMMUNITY_DATASTORE_CASSANDRA_CACHE_ENABLED=true), default providers (jpa) are used for non-cache areas.

The following parameters might be needed in addition to the configuration options of this extension (see below):

CLI-Parameter Description
--features-disabled=authorization Disable authorization (this is essential as otherwise Keycloak tries to use InfinispanStoreFactory at a lot of places)
--spi-connections-jpa-legacy-enabled=false Deactivate automatic JPA schema migration

Configuration options

CLI-Parameter Description
--spi-cassandra-connection-default-port Cassandra CQL-Port
--spi-cassandra-connection-default-contact-points Comma-separated list of cassandra node-endpoints
--spi-cassandra-connection-default-local-datacenter Local datacenter name
--spi-cassandra-connection-default-username Username
--spi-cassandra-connection-default-password Password
--spi-cassandra-connection-default-keyspace Keyspace-name (will be generated by the extension if it does not exist at startup-time)
--spi-cassandra-connection-default-replication-factor Replication factor used if the extension creates the keyspace with simple strategy

Deviations from standard storage providers

User Lookup

Due to Cassandras query first nature, users can only be looked up by specific fields. UserProvider::searchForUserStream supports the following subset of Keycloaks standard search attributes:

  • keycloak.session.realm.users.query.search for a case insensitive username search
  • keycloak.session.realm.users.query.include_service_account to include service accounts
  • email for an email search

UserProvider::searchForUserByUserAttributeStream by default iterates all users in the entire database to filter for the requested attribute in-memory. For efficient searches, attributes can be defined as indexed attributes by prefixing their name with indexed., e.g. indexed.businessKey

Conditional updates / optimistic locking

All write-queries are done conditionally via Cassandra Lightweight Transactions. Therefore we store a version column in each of the tables. To be able to use this to get notified if a conflicting change occured after data was read, the entityVersion is exposed via a readonly attribute readonly.entityVersion. In order to pass a version in update operations, one can use the corresponding attribute internal.entityVersion.

Uniqueness across username and password

This extension supports additional checks to prevent setting username to a value that is already as email of another user and setting email to a value used as username.

To enable these checks for a realm, set its attribute enableCheckForDuplicatesAcrossUsernameAndEmail to true (default when not set: false)

Multi-Tab Refresh Token Rotation

There is a long-standing bug inside Keycloak which prevents independent refresh token rotations on multiple tabs, using the same client: keycloak/keycloak#14122 This extension implements a workaround which is only active when refreshTokenMaxReuse is equal to 0. Then the last refresh is tracked per refresh token instead of per client session. Additionally, a grace period can be set via refreshTokenReuseInterval realm attribute. Refresh token reuses during this grace period are allowed, which can be useful in case of retries / network problems.

Contributing

Before contributing to Keycloak Cassandra, please read our contributing guidelines.

Private image registries

If you use a private image registry, you can use the .testcontainers file in your user directory to override all image-registries used by the tests. See https://www.testcontainers.org/features/image_name_substitution/

Example:

docker.client.strategy=org.testcontainers.dockerclient.EnvironmentAndSystemPropertyClientProviderStrategy
hub.image.name.prefix=private-registry/3rd-party/

Debugging

Debugging can be enabled via mvn -Dmaven.surefire.debug verify (Port 5005).

Using an external cassandra instance

If you want to use an external cassandra instance on localhost (Port 9042) you can use mvn -Dkeycloak.testsuite.start-cassandra-container=false verify

About

Keycloak-DatastoreProvider storing data in an Apache Cassandra NoSQL-database.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published