Custom UserStorageProvider: Where do I make a call to my external REST API to persist a new user?

As it seems, I’m not the only one struggling to wrap my head around the persisting a new user by calling my external REST API.

The public UserModel addUser(RealmModel realmModel, String username) method is expected to return either null (indicating that I don’t want the user to be created in this provider), or a UserModel, for example:

MyAccount account = new MyAccount();
account.setUsername(username);
return new UserAdapter(session, realmModel, model, account);

Later on, all the other attributes will be added to the account object.

If I’m directly connected to my database, it will be (at least I understood it like that) automatically persisted.

The question is, however, what do I do if I rely on RESTful API for persisting/removing, etc. my user - how do I send this completed instance of MyAccount via my external REST API to be saved remotely (in my custom storage)?

I managed to find a place in which all user attributes are available as a string representation - by implementing a custom EventListenerProvider and listening to Events and AdminEvents.

At this point I’m initiating a new user creation from the Keycloak Admin Console, which means, by listening to AdminEvents, I’m able to send my external REST API call from the

@Override
public void onEvent(final AdminEvent adminEvent, final boolean includeRepresentation) { ... }

method, in which is the representation available.

This is, I’m afraid not ideal because, should something go wrong with the account creation on the custom storage end, SPI is not aware of that and it still proceeds as usual, displaying “User created successfully” toast in the Console, while the page that is supposed to show the newly created user fails to display because obviously the new user doesn’t exist in the custom storage.

May be what you need is a custom User Storage based on the User Storage SPI

Well, I’m actually doing just that. However, I need to send my newly created user via my own REST API to be created remotely (at the backend), hence the confusion as to where do I, according to best practice, make that API call.