Retrieving a trusted client token within a Keycloak addon (SPI)

420 Views Asked by At

As part of our effort to be GDPR compliant, I’m trying to extend our Keycloak server with some custom functionality, to be triggered 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 was easy. It's implemented as a SPI event listener, following this example:

@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().getId());
            }
        });
}

But I'm stuck on the second task (sending the HTTP request). The other service is set up to require a trusted client token, using a designated Keycloak Client and scope. The equivalent POST request to auth/realms/{realm}/protocol/openid-connect/token is done 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

I can’t find out how to do that from within the SPI code. I can retrieve a regular Access Token (as described in this other SO post):

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's not the token I need. 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.

Besides, I'm not sure if it is even possible to retrieve a trusted client token for a user that is in the process of being deleted. In other words, I don’t know if the UserRemovedEvent is fired before, during or after the user is actually deleted, or if Keycloak waits until any custom EventHandlers have finished running.

(In order to figure that out, I'll try if it is possible to retrieve that token using a regular http POST request from within the add-on code, but I have no idea if it's possible to connect to Keycloak like that from inside. I'll update the question if that works.)

I'd greatly appreciate any suggestion!

(I also asked this in the Keycloak discourse group here but it looks as if it will remain unanswered there)

0

There are 0 best solutions below