Le systeme SPI de Keycloak
Keycloak est concu autour de Service Provider Interfaces (SPI). Chaque fonctionnalite est un SPI remplacable ou extensible : authentification, stockage, themes, protocoles, etc.
Custom Authenticator
Un Authenticator custom permet d'ajouter des etapes d'authentification personnalisees dans les flows.
public class IPCheckAuthenticator implements Authenticator {
@Override
public void authenticate(AuthenticationFlowContext context) {
String clientIP = context.getConnection()
.getRemoteAddr();
List<String> allowedIPs = getConfiguredIPs(context);
if (allowedIPs.contains(clientIP)) {
context.success();
} else {
context.failureChallenge(
AuthenticationFlowError.ACCESS_DENIED,
context.form()
.setError("ipNotAllowed")
.createErrorPage(Response.Status.FORBIDDEN)
);
}
}
@Override
public void action(AuthenticationFlowContext context) {
// Traitement apres soumission de formulaire
}
@Override
public boolean requiresUser() { return false; }
@Override
public boolean configuredFor(
KeycloakSession session, RealmModel realm, UserModel user
) { return true; }
}
Factory pour l'Authenticator
public class IPCheckAuthenticatorFactory
implements AuthenticatorFactory {
public static final String PROVIDER_ID = "ip-check";
@Override
public Authenticator create(KeycloakSession session) {
return new IPCheckAuthenticator();
}
@Override
public String getId() { return PROVIDER_ID; }
@Override
public String getDisplayType() {
return "IP Address Check";
}
@Override
public List<ProviderConfigProperty> getConfigProperties() {
return List.of(
new ProviderConfigProperty(
"allowed-ips", "Allowed IPs",
"Liste des IPs autorisees (separees par virgule)",
ProviderConfigProperty.STRING_TYPE, ""
)
);
}
}
Event Listener SPI
Les Event Listeners reagissent aux evenements Keycloak (login, logout, erreurs, admin events).
public class AuditEventListener
implements EventListenerProvider {
@Override
public void onEvent(Event event) {
if (event.getType() == EventType.LOGIN) {
String userId = event.getUserId();
String ip = event.getIpAddress();
// Envoyer vers SIEM, base d'audit, etc.
auditService.log("LOGIN", userId, ip);
}
if (event.getType() == EventType.LOGIN_ERROR) {
// Alerter sur les tentatives echouees
alertService.notify("Failed login from " +
event.getIpAddress());
}
}
@Override
public void onEvent(AdminEvent event, boolean includeRep) {
// Auditer les actions admin
auditService.logAdmin(
event.getOperationType().name(),
event.getResourcePath()
);
}
@Override
public void close() {}
}
Enregistrement du SPI
# META-INF/services/org.keycloak.authentication.AuthenticatorFactory
com.example.IPCheckAuthenticatorFactory
# META-INF/services/org.keycloak.events.EventListenerProviderFactory
com.example.AuditEventListenerFactory
Astuce : Utilisez le SDK Keycloak pour developper et tester vos extensions localement avant de deployer en production.