Callback (hook) on User creation

I wonder if there is something like a hook or a callback to activate, either programmatically or via admin console, to trigger some action (call a remote service, for ex.) when a new User is created via admin console?

1 Like

Hi,

take a look at the spi-event-listener example in https://github.com/zonaut/keycloak-extensions and see if this helps you further.

1 Like

O, cool, good to know! Thank you for sharing that. :+1:

@zonaut, it is not clear enought how to proceed after copying the spi-event-listener-0.0.1-SNAPSHOT.jar into ~/keycloak-11.0.2/standalone/deployments foldder (I’m using a standalone instance of Keycloak). Should I create a custom class implementing EventListenerProviderFactory as it is done in this code-source example or there is another way to go? Thank you.

After deployment you need to configure it.
Take a loot at the readme file on how to set it up https://github.com/zonaut/keycloak-extensions/blob/master/spi-event-listener/README.md -> Keycloak admin console configuration
If it isn’t detected try to restart Keycloak so it’s picked up.

I’ve already done all that is described in README of the extension. The question is what is next after

select our pl_event_listener

Imagine that I’d like to trigger an action once a new user is created via Admin Console. How to branch the Kycloak listener to an external service (no matter, Kafka, a Java micro-service, etc.)?

Have you taken a look at the UserVerifiedTransaction example which is executed on the event(s) you listen on and calls an external service through an API call.
The call session.getTransactionManager().enlistPrepare(userVerifiedTransaction); executes this call, you probably will need to do this on the AdminEvent listener

You’ll probably be interested in

  • onEvent(AdminEvent adminEvent, boolean b) -> ResourceType.USER + OperationType.CREATE
1 Like

As far as I understood, I’ll have to override public void onEvent(AdminEvent adminEvent, boolean b) method to be able to listen to admin events. An instance of AdminEvent has some methods, especially the getOperationType() could be interesting which returns an OperationType enum or the getResourceType() method that returns an Enum of ResourceType, where the one of USER could be interested. Right?

Yep, you were faster this time :smiley: So, I have to:

  • create a separate micro-service
  • package it as a jar
  • deploy the jar into the ~/keycloak-11.0.2/standalone/deployments folder.

Right?

Yes, that sounds about right.
Good luck and let us know how it went.

How do we get the user details for the DELETE callback. I mean when a user gets deleted I want the user details as well, currently they are null?

Did you find an answer for the DELETE callback ?
I saw the discussion about pre-delete event but I don’t see how implement it.

The other way to get a user deletion event is to register a ProviderEventListener of type UserModel.UserRemovedEvent with the KeycloakSessionFactory. You can set this up in the postInit method of any ProviderFactory you create.

  @Override
  public void postInit(KeycloakSessionFactory factory) {
    factory.register(
        (event) -> {
          if (event instanceof UserModel.UserRemovedEvent)
            //do something here with the UserRemovedEvent
            //the user is available via event.getUser()
        });
  }

javadoc for the event is here:
https://www.keycloak.org/docs-api/15.0/javadocs/org/keycloak/models/UserModel.UserRemovedEvent.html

2 Likes

Brilliant, this was exactly what I was looking for. Thanks :kiss:

I was able to follow along in this thread and hook into the user-creation process via a custom extension, which is great! I’m just left with one issue.

When a user is created, we’re sending an event off to our own servers to let it do some user-creation tasks as well. Our servers may reject for a number of reasons, like, the username including certain characters we do not support, or, maybe our server is just down at the moment and can’t pick up the request. Either way, we’d like to it if the user did not get created in these scenarios.

When the user-creation is rejected for whatever reason, we’re currently throwing a RuntimeException within our keycloak extension. I had hoped this would cancel the user creation process and put everything back to how it was. Instead, it seems the user is being created within ldap anyways, but keycloak itself is unaware of the new, partially-created user until I sync the two.

The keycloak APIs have all of this transaction/rollback logic built into it, which makes it sound like its supposed to be able to gracefully support these sorts of errors. Is this a bug, or is there something I need to be doing differently?

(If needed, I can put together a minimal extension to reproduce the problem and report it if this really is a bug)

What you are describing sound correct. However, I have spent the last month on a project related to transactions in Keycloak, and while their approach sounds good, I have found it lacking in execution. There are cases where, when dealing with a remote system, they don’t really make an attempt to manually rollback a transaction if there is no integrated, built-in transaction mechanism in the remote system. Although I don’t know if that’s the problem in your LDAP scenario, but it’s my guess.

1 Like

Worst comes to worse, I guess I could always try deleting the user myself if a network error occurs. I’m sure they provide some sort of API to do so, though I may need to first tell it to sync with ldap before I can delete. I’m just a bit scared of doing that - deleting the user being created while we’re in the middle of the user-creation process sounds like a recipe for disaster - even if keycloak doesn’t choke on that now, it might in a future version.