Bhavin Kanzariya
Bhavin Kanzariya

Reputation: 1

using Kecloak's EventListenerProvider how to restricting creating role at client level if the same role doesn’t exist on realm[V:25.0.1]

We are working on one usecase where we want to restric creating role at client level if the same role name doesn’t existing on realm level.

We did try this with EventListenerProvider and with that we were able to get those exceptions logged into terminal/logs but that was not restricting anything on UI instead it was creating role on client level. which means with EventListenerProvider we were just getting that into log only and there are no pop-ups/messages or even not stopping client to creat role.

Attaching the java files that i had in custom event lister. CustomEventListenerProvider.java


package com.example.keycloak;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.ws.rs.ForbiddenException;
import org.jboss.logging.Logger;
import org.keycloak.events.Event;
import org.keycloak.events.EventListenerProvider;
import org.keycloak.events.admin.AdminEvent;
import org.keycloak.events.admin.OperationType;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelDuplicateException;
import org.keycloak.models.RoleModel;
import org.keycloak.events.admin.ResourceType;

import java.io.IOException;


public class CustomEventListenerProvider implements EventListenerProvider {

    private final KeycloakSession session;
    private final ObjectMapper objectMapper = new ObjectMapper();

    public CustomEventListenerProvider(KeycloakSession session) {
        this.session = session;
    }


    @Override
    public void onEvent(Event event) {

    }

    @Override
    public void onEvent(AdminEvent event, boolean includeRepresentation) {
        if (event.getOperationType() == OperationType.CREATE &&
                event.getResourceType() == ResourceType.CLIENT_ROLE) {
            try {
                JsonNode representation = objectMapper.readTree(event.getRepresentation());
                String roleName = representation.get("name").asText();

                RoleModel realmRole = session.roles().getRealmRole(session.getContext().getRealm(), roleName);
                if (realmRole == null) {
                    throw new Exception("Client-level role creation is not allowed unless the same role exists at the realm level.");
                }
            } catch (Exception e) {
                throw new ModelDuplicateException("Failed to parse event representation");
            }
        }
    }

    @Override
    public void close() {
        // Cleanup resources if needed
    }

}

src/main/java/com/example/keycloak/CustomEventListenerProviderFactory.java

package com.example.keycloak;

import org.keycloak.Config;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.events.EventListenerProvider;
import org.keycloak.events.EventListenerProviderFactory;

public class CustomEventListenerProviderFactory implements EventListenerProviderFactory {

    @Override
    public EventListenerProvider create(KeycloakSession session) {
        return new CustomEventListenerProvider(session);
    }

    @Override
    public void init(Config.Scope config) {
        // Initialization code if necessary
    }

    @Override
    public void postInit(KeycloakSessionFactory factory) {
        // Post initialization code if necessary
    }

    @Override
    public void close() {
        // Cleanup code if necessary
    }

    @Override
    public String getId() {
        return "custom-event-listener";
    }
}

src/main/resources/META-INF/services/org.keycloak.events.EventListenerProviderFactory com.example.keycloak.CustomEventListenerProviderFactory

Then I created .jar, moved that jar into the provider folder, and built and ran keycloak.(As per this doc) Ps: After login, i have enabled that customer event lister under realm setting.

Upvotes: 0

Views: 43

Answers (0)

Related Questions