Service Provider Interface (SPI) contracts and abstractions for the Keycloak identity and access management server enabling extensibility through custom providers
npx @tessl/cli install tessl/maven-org-keycloak--keycloak-server-spi@26.2.0Keycloak Server SPI (Service Provider Interface) is the core extensibility framework for the Keycloak identity and access management server. It provides comprehensive interfaces and contracts that enable developers to create custom providers for authentication, user storage, credential management, session handling, and other extensibility points.
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-server-spi</artifactId>
<version>26.2.5</version>
<scope>provided</scope>
</dependency>import org.keycloak.provider.Provider;
import org.keycloak.provider.ProviderFactory;
import org.keycloak.provider.Spi;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.ClientModel;
import org.keycloak.component.ComponentModel;// Implementing a custom provider
public class MyCustomProvider implements UserStorageProvider {
private KeycloakSession session;
private ComponentModel model;
public MyCustomProvider(KeycloakSession session, ComponentModel model) {
this.session = session;
this.model = model;
}
@Override
public UserModel getUserById(RealmModel realm, String id) {
// Custom user lookup implementation
return null;
}
@Override
public void close() {
// Cleanup resources
}
}
// Creating a provider factory
public class MyCustomProviderFactory implements UserStorageProviderFactory<MyCustomProvider> {
public static final String PROVIDER_ID = "my-custom-provider";
@Override
public MyCustomProvider create(KeycloakSession session, ComponentModel model) {
return new MyCustomProvider(session, model);
}
@Override
public String getId() {
return PROVIDER_ID;
}
}The Keycloak Server SPI is built around several key architectural patterns:
Foundation interfaces for creating extensible Keycloak providers. Essential for all custom integrations.
public interface Provider {
void close();
}
public interface ProviderFactory<T extends Provider> {
T create(KeycloakSession session);
void init(Config.Scope config);
void postInit(KeycloakSessionFactory factory);
void close();
String getId();
}
public interface Spi {
boolean isInternal();
String getName();
Class<? extends Provider> getProviderClass();
Class<? extends ProviderFactory> getProviderFactoryClass();
}Central session interfaces providing access to all Keycloak services and transaction management.
public interface KeycloakSession extends AutoCloseable {
KeycloakContext getContext();
KeycloakTransactionManager getTransactionManager();
<T extends Provider> T getProvider(Class<T> clazz);
RealmProvider realms();
UserProvider users();
ClientProvider clients();
}
public interface KeycloakContext {
URI getAuthServerUrl();
String getContextPath();
UriInfo getUri();
HttpHeaders getRequestHeaders();
RealmModel getRealm();
ClientModel getClient();
}Primary model interfaces representing Keycloak entities like realms, users, clients, and roles.
public interface RealmModel extends RoleContainerModel {
String getId();
String getName();
String getDisplayName();
void setDisplayName(String displayName);
boolean isEnabled();
void setEnabled(boolean enabled);
SslRequired getSslRequired();
void setSslRequired(SslRequired sslRequired);
}
public interface UserModel extends RoleMapperModel {
String getId();
String getUsername();
void setUsername(String username);
String getFirstName();
void setFirstName(String firstName);
String getLastName();
void setLastName(String lastName);
String getEmail();
void setEmail(String email);
}
public interface ClientModel extends ProtocolMapperContainerModel, ScopeContainerModel, RoleContainerModel {
String getId();
String getClientId();
void setClientId(String clientId);
String getName();
void setName(String name);
boolean isEnabled();
void setEnabled(boolean enabled);
}Interfaces for integrating external user stores and implementing custom user storage providers.
public interface UserStorageProvider extends Provider {
// Base interface for user storage providers
}
public interface UserLookupProvider {
UserModel getUserById(RealmModel realm, String id);
UserModel getUserByUsername(RealmModel realm, String username);
UserModel getUserByEmail(RealmModel realm, String email);
}
public interface UserQueryProvider extends UserQueryMethodsProvider, UserCountMethodsProvider {
Stream<UserModel> searchForUserStream(RealmModel realm, String search);
Stream<UserModel> searchForUserStream(RealmModel realm, String search, Integer firstResult, Integer maxResults);
Stream<UserModel> getGroupMembersStream(RealmModel realm, GroupModel group);
}Framework for handling various credential types including passwords, OTP, and WebAuthn.
public interface CredentialProvider extends Provider {
String getType();
CredentialModel createCredential(RealmModel realm, UserModel user, CredentialModel credential);
boolean deleteCredential(RealmModel realm, UserModel user, String credentialId);
CredentialModel getCredentialFromModel(CredentialModel model);
}
public interface CredentialInputValidator {
boolean supportsCredentialType(String credentialType);
boolean isConfiguredFor(RealmModel realm, UserModel user, String credentialType);
boolean isValid(RealmModel realm, UserModel user, CredentialInput input);
}
public interface CredentialInputUpdater {
boolean supportsCredentialType(String credentialType);
boolean updateCredential(RealmModel realm, UserModel user, CredentialInput input);
void disableCredentialType(RealmModel realm, UserModel user, String credentialType);
}Interfaces for managing authentication flows, user sessions, and client sessions.
public interface AuthenticationSessionModel extends CommonClientSessionModel {
String getTabId();
RootAuthenticationSessionModel getParentSession();
Map<String, ExecutionStatus> getExecutionStatus();
void setExecutionStatus(String authenticator, ExecutionStatus status);
void clearExecutionStatus();
UserModel getAuthenticatedUser();
void setAuthenticatedUser(UserModel user);
}
public interface UserSessionModel {
String getId();
RealmModel getRealm();
UserModel getUser();
String getLoginUsername();
String getIpAddress();
String getAuthMethod();
int getStarted();
int getLastSessionRefresh();
void setLastSessionRefresh(int seconds);
}Configuration-driven component system for managing provider instances and their configurations.
public interface ComponentFactory<T extends Provider> extends ProviderFactory<T> {
T create(KeycloakSession session, ComponentModel model);
void validateConfiguration(KeycloakSession session, RealmModel realm, ComponentModel model) throws ComponentValidationException;
void onCreate(KeycloakSession session, RealmModel realm, ComponentModel model);
void onUpdate(KeycloakSession session, RealmModel realm, ComponentModel oldModel, ComponentModel newModel);
}
public class ComponentModel {
private String id;
private String name;
private String providerId;
private String providerType;
private String parentId;
private String subType;
private MultivaluedHashMap<String, String> config;
}Framework for customizing Keycloak UI themes and handling internationalization.
public interface Theme {
String getName();
String getParentName();
String getImportName();
Type getType();
URL getTemplate(String name) throws IOException;
InputStream getResourceAsStream(String path) throws IOException;
Properties getMessages() throws IOException;
Properties getProperties() throws IOException;
}
public interface ThemeSelectorProvider extends Provider {
String getThemeName(Theme.Type type);
}
public interface LocaleSelectorProvider extends Provider {
Locale resolveLocale(RealmModel realm, UserModel user);
}Extensible validation system for form fields and user input validation.
public interface Validator {
String getId();
ValidationResult validate(Object input, String inputHint, ValidationContext context, ValidatorConfig config) throws ValidationException;
}
public interface ValidationContext extends AttributeContext {
KeycloakSession getSession();
Attributes getAttributes();
RealmModel getRealm();
UserModel getUser();
}
public class ValidationResult {
public static final ValidationResult VALID = new ValidationResult();
private final boolean valid;
private final Set<ValidationError> errors;
}Secure secrets management through vault provider integration.
public interface VaultProvider extends Provider {
VaultRawSecret obtainSecret(String vaultSecretId);
}
public interface VaultStringSecret extends VaultCharSecret {
Optional<String> get();
default String getOrDefault(String defaultValue) {
return get().orElse(defaultValue);
}
}
public interface VaultTranscriber {
String transcribe(String value);
}// Core model enumerations
public enum SslRequired {
ALL, EXTERNAL, NONE
}
// Authentication execution status
public enum ExecutionStatus {
SUCCESS, FAILED, SETUP_REQUIRED, ATTEMPTED, SKIPPED, CHALLENGED, FLOW_RESET
}
// Provider event base interface
public interface ProviderEvent {
// Marker interface for provider events
}
// Component validation exception
public class ComponentValidationException extends Exception {
public ComponentValidationException(String message);
public ComponentValidationException(String message, Object... parameters);
}
// Model exceptions
public class ModelException extends RuntimeException {
public ModelException(String message);
public ModelException(String message, Throwable cause);
}
public class ModelDuplicateException extends ModelException {
public ModelDuplicateException(String message);
public String getDuplicateFieldName();
public Object getDuplicateFieldValue();
}