Pat's
Pat's

Reputation: 51

Keycloak EventListener - Update Events Details in Keycloak 18

I'm working with a custom EventListenerProvider in Keycloak 18 to handle LOGIN and LOGIN_ERROR events. I aim to modify the Event object details by adding a custom attribute (like orgId) and have the updated details reflected in the event processing. However, although I can see the orgId in the logs, the event details are not being updated with the custom orgId attribute value as expected.

Expectation: The custom orgId should be added to the event details, and I should see the updated details in the LOGIN event processing.

 public TenantEventListenerProvider(KeycloakSession keycloakSession) {
    this.keycloakSession = keycloakSession;
    Consumer<Event> eventConsumer = this::processEvent;
    BiConsumer<AdminEvent, Boolean> adminEventConsumer = this::processAdminEvent;
    this.tx = new EventListenerTransaction(adminEventConsumer, eventConsumer);
    //keycloakSession.getTransactionManager().enlistAfterCompletion(tx);
  }

  @Override
  public void onEvent(Event event) {
    LOGGER.infof("Event is %s", event);
    if (event.getType() == EventType.LOGIN || event.getType() == EventType.LOGIN_ERROR) {
      String userId = event.getUserId();
      String clientId = event.getClientId();
      String orgId = extractOrgId(event);
      // Clone the event
      Event clonedEvent = event.clone();

      Map<String, String> eventDetails = new HashMap<>(event.getDetails());
      eventDetails.put("orgId", orgId);

      clonedEvent.setDetails(eventDetails);

      LOGGER.infof("Captured Event: %s | User: %s | Tenant: %s | Client: %s",
          event.getType().name(), userId, orgId, clientId);
      tx.addEvent(clonedEvent);
     //keycloakSession.getTransactionManager().enlistAfterCompletion(this.tx);

    }

  }

Is there something I might be missing in how the event details are updated in Keycloak?

Any suggestions on how to correctly handle this would be greatly appreciated!

Upvotes: 0

Views: 52

Answers (1)

Navin Gelot
Navin Gelot

Reputation: 1334

I was searching for a similar solution, but it didn’t work for me.
This might be helpful—rather than using an attribute, you can use cookies.

You can set a cookie and retrieve it whenever needed, even on the UI side.

NewCookie errorCookie = new NewCookie.Builder("login_error")
                                .value("Access denied when authenticating with Microsoft")
                                .path("/")
                                .domain("localhost")
                                .comment("Login Error")
                                .maxAge(160)  // Cookie expiry (in seconds)
                                .build();
                        session.getContext().getHttpResponse().setCookieIfAbsent(errorCookie);

Upvotes: 0

Related Questions