JBoss.orgCommunity Documentation
Keycloak is designed to cover most use-cases without requiring custom code, but we also want it to be customizable. To achive this Keycloak has a number of SPIs which you can implement your own providers for.
To implement an SPI you need to implement it's ProviderFactory and Provider interfaces. You also need to
create a provider-configuration file. For example to implement the Event Listener SPI you need to implement
EventListenerProviderFactory and EventListenerProvider and also provide the file
META-INF/services/org.keycloak.events.EventListenerProviderFactory
For example to implement the Event Listener SPI you start by implementing EventListenerProviderFactory:
{ package org.acme.provider; import ... public class MyEventListenerProviderFactory implements EventListenerProviderFactory { private List<Event> events; public String getId() { return "my-event-listener"; } public void init(Config.Scope config) { int max = config.getInt("max"); events = new MaxList(max); } public EventListenerProvider create(KeycloakSession session) { return new MyEventListenerProvider(events); } public void close() { events = null; } } }
The example uses a MaxList which has a maximum size and is concurrency safe. When the maximum size is reached and new entries are added the oldest entry is removed. Keycloak creates a single instance of EventListenerProviderFactory which makes it possible to store state for multiple requests. EventListenerProvider instances are created by calling create on the factory for each requests so these should be light-weight.
Next you would implement EventListenerProvider:
{ package org.acme.provider; import ... public class MyEventListenerProvider implements EventListenerProvider { private List<Event> events; public MyEventListenerProvider(List<Event> events) { this.events = events; } @Override public void onEvent(Event event) { events.add(event); } @Override public void close() { } } }
The file META-INF/services/org.keycloak.events.EventListenerProviderFactory
should
contain the full name of your ProviderFactory implementation:
{ org.acme.provider.MyEventListenerProviderFactory }
Keycloak loads provider implementations from the file-system. By default all JARs inside
standalone/configuration/providers
are loaded. This is simple, but requires all providers
to share the same library. All provides also inherit all classes from the Keycloak class-loader. In the future
we'll add support to load providers from modules, which allows better control of class isolation.
To register your provider simply copy the JAR including the ProviderFactory and Provider classes and the
provider configuration file to standalone/configuration/providers
.
You can also define multiple provider class-path if you want to create isolated class-loaders. To do this edit keycloak-server.json and add more classpath entries to the providers array. For example:
{ "providers": [ "classpath:provider1.jar;lib-v1.jar", "classpath:provider2.jar;lib-v2.jar" ] }
The above example will create two separate class-loaders for providers. The classpath entries follow the same syntax as Java classpath, with ';' separating multiple-entries. Wildcard is also supported allowing loading all jars (files with .jar or .JAR extension) in a folder, for example:
{ "providers": [ "classpath:/home/user/providers/*" ] }
Here's a list of the available SPIs and a brief description. For more details on each SPI refer to individual sections.