Extensions et SPI Keycloak 35 min de lecture

Custom Authenticators et Event Listeners

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.