Retrieving a trusted client token within a custom SPI

I’m trying to create some custom actions to happen when a user is removed:

  • sending a confirmation message to a Slack channel
  • sending a HTTP request to another service we built, to delete any assets that user might have created there

The first one works fine. I buit a SPI event listener using the example of user xgp here, which works like a charm:

@Override
public void postInit(KeycloakSessionFactory keycloakSessionFactory) {
    keycloakSessionFactory.register(
        (event) -> {
            // the user is available via event.getUser()
            if (event instanceof UserModel.UserRemovedEvent){
                userRemovedMessageHandler.handleUserRemoveEvent(session, (UserRemovedEvent) event);
                LOG.debug("User removed event happened for user: " + ((UserRemovedEvent) event).getUser().getEmail());
            }
        });
}

I’m stuck on how to accomplish the second action. The other service is set up to require a trusted client token using a specific Keycloak client and can be retrieved with a POST request to auth/realms/{realm}/protocol/openid-connect/token with these parameters:

grant_type: password
username: {user that is about to be deleted}
password: {user password}
client_id: {the specific client}
client_secret: {that client's secret}
scope: usersets

… but I can’t find out how to do that from within the SPI code. I tried it like this:

private String getAccessToken(KeycloakSession session, UserModel deleteUser) {
    KeycloakContext keycloakContext = session.getContext();

    AccessToken token = new AccessToken();
    token.subject(deleteUser.getId());
    token.issuer(Urls.realmIssuer(keycloakContext.getUri().getBaseUri(), keycloakContext.getRealm().getName()));
    token.issuedNow();
    token.expiration((int) (token.getIat() + 60L)); //Lifetime of 60 seconds

    KeyWrapper key = session.keys().getActiveKey(keycloakContext.getRealm(), KeyUse.SIG, "RS256");

    return new JWSBuilder().kid(key.getKid()).type("JWT").jsonContent(token).sign(
        new AsymmetricSignatureSignerContext(key));
}

but that produces a wholly different token. In order to retrieve the required trusted client token I’d need the internal Keycloak / SPI-equivalent of the above POST request but I can’t figure out how to do that or where to look.

And other than that, I wonder if it is even possible to get a token like that for a user that is being deleted. I don’t know if the UserRemovedEvent is fired before, during or after the user is actually deleted, or if Keycloak waits until the EventHandler has finished whatever it is doing. Though it is evidently possible to retrieve the user details in the handler.

Any ideas how to accomplish this?
Thanks :star2: