p2-inc / keycloak-events

Useful Keycloak event listener implementations and utilities.
https://phasetwo.io
Other
195 stars 36 forks source link

java.lang.NullPointerException - org.keycloak.models.UserModel.getUsername() #66

Closed spinanicky closed 3 months ago

spinanicky commented 4 months ago

With Keycloak 25.0.2, the following error occurs. When trying to use the webhook and deleting a group, keycloak fails to send the event.

I am using the latest V.30 tag (using clean build).

docker compose up with a keycloak-events build within a custom image (only has events jar and a theme added):

services:
  keycloak:
    container_name: ae-keycloak
    image: ae-keycloak:25.0.2
    ports:
      - "8090:8080"
    environment:
      - KEYCLOAK_ADMIN=admin
      - KEYCLOAK_ADMIN_PASSWORD=admin
    extra_hosts:
      - "host.docker.internal:host-gateway"
    command:
      - start-dev
    restart: no

Create a new realm in admin console.

In the created realm:

  1. Create a new user "user@email.internal" with a random, non-temporary password
  2. Add ext-event-webhook to the event listener list and add a webhook
  3. create a new group
  4. delete the group and you should see the following error
2024-07-24 20:53:50,561 WARN  [io.phasetwo.keycloak.events.WebhookSenderEventListenerProvider] (executor-thread-39) Error converting and scheduling event: org.keycloak.events.admin.AdminEvent@529cfc54: java.lang.NullPointerException: Cannot invoke "org.keycloak.models.UserModel.getUsername()" because "user" is null

    at io.phasetwo.keycloak.events.WebhookSenderEventListenerProvider.completeAdminEventAttributes(WebhookSenderEventListenerProvider.java:166)

    at io.phasetwo.keycloak.events.WebhookSenderEventListenerProvider.onEvent(WebhookSenderEventListenerProvider.java:69)

    at org.keycloak.services.resources.admin.AdminEventBuilder.send(AdminEventBuilder.java:290)

    at org.keycloak.services.resources.admin.AdminEventBuilder.success(AdminEventBuilder.java:272)

    at org.keycloak.services.resources.admin.GroupResource.deleteGroup(GroupResource.java:159)

This does not happen on the master realm in my testing, only in a new realm

Thank you to @xgp for pointing out where int he code it is failing: https://github.com/p2-inc/keycloak-events/blob/main/src/main/java/io/phasetwo/keycloak/events/WebhookSenderEventListenerProvider.java#L166

Let me know if you need additional information.

xgp commented 4 months ago

Is the user who is deleting the group a member of a different realm than where the group is? I.e. the master admin is deleting a group in the X realm?

If so, I think I see how it fails to lookup the user.

spinanicky commented 4 months ago

Correct

xgp commented 4 months ago

Got it. So that line is failing because it assumes the authenticated user is in the same realm as the action of the event, which it may not be in case of the master realm. I think the fix logic should be something like:

    user = getUserById(actionRealm, userId)
    if user is null
        user = getUserById(masterRealm, userId)

I don't believe there's a case where the fallback could be anything but the master realm

xgp commented 4 months ago

@rtufisi can you take a look at this when you have time?

rtufisi commented 4 months ago

@rtufisi can you take a look at this when you have time?

Sure

xgp commented 3 months ago

Fixed in #68