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:
The permitted person generates an invite link, which contains a token
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?
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.
// 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);
}
}