Invite user to register and automatically join a group

What I want to achieve is the following: A permitted person should be able to invite a user to create an account and directly join a specific group.
The user does not have an account yet.

The solution I currently have in mind involves the following steps:

  1. The permitted person generates an invite link, which contains a token
  2. The user receives the link, fills out the registration form, verifies their email and has a working account and is a member of the target group

The generation of the invite links should be handled in an external system.
However I’m unsure if the registration could already be done with Keycloak (and a custom extension).

Is it sufficient to implement an extension of the data-model which contains the token, the target group and a valid flag and the registration validator (there is already one in place) will get this from the url (or a hidden field in the form) and evaluate the token, add the group to the user and invalidate the token?
Has someone already done this or something similar?

Were you able to implement this flow?

I’ve got something working though it is not fully tested yet.

I’ve added a JPA and the according liquibase migrations (rather painful to add these) and extended my custom registration form and validator.

The invite links look like this: http://localhost:8080/auth/realms/master/protocol/openid-connect/registrations?client_id=account&response_type=code&scope=email&kc_locale=de&token=8f8fefa7-b5bd-40ed-84da-9e4e84679364 and the token parameter is added by a few lines of javascript into a hidden form field.

The validator is similar to keycloak-extensions/PlaceholderRegistrationProfile.java at master · zonaut/keycloak-extensions · GitHub and just extends the success method to look like this

    // Check for hidden form field token
    // If it exists try to get the token information form the database
    if (formData.containsKey("token")) {
        KeycloakSession session = context.getSession();
        EntityManager em = session.getProvider(JpaConnectionProvider.class).getEntityManager();
        RegistrationToken registrationToken = em.find(RegistrationToken.class, formData.getFirst("token"));

        // Token found and not already used/expired
        // Add user to group
        if (registrationToken != null && registrationToken.isValid()) {
            GroupModel group = context.getRealm().getGroupById(registrationToken.getGroupId());
            user.joinGroup(group);
            registrationToken.setValid(false);
        }
    }