Implementing custom user registration with setting default attributes

Hi, have not found any examples of my case online. Never done it before, so might be missing something. When new user registers their account, I want them to have some attributes set by default.
My code:

package org.example;

import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.storage.user.UserRegistrationProvider;

public class CustomUserRegistrationProvider implements UserRegistrationProvider {

  private final KeycloakSession session;

  public CustomUserRegistrationProvider(KeycloakSession session) {
    this.session = session;
  }


  @Override
  public UserModel addUser(RealmModel realm, String username) {
    UserModel user = session.users().addUser(realm, username);
    // Set the default attributes for newly registered
    user.setSingleAttribute("TYPE", "USER");
    user.setSingleAttribute("STATUS", "NOT_REGISTERED");
    return user;
  }

  @Override
  public boolean removeUser(RealmModel realmModel, UserModel userModel) {
    return false;
  }

}

Added new file resources/META-INF/services/org.keycloak.storage.UserRegistrationProvider with the value of org.example.CustomUserRegistrationProvider

Packaged the project, put the .jar file under \providers in the Keycloak folder, ran commands kc build, kc start-dev, registered new user and expected to find new attributes created for a user, but it did not work. Any ideas what I am doing wrong?

1 Like

You are using an interface of the User Storage Provider SPI, which is IMHO not suitable for your use case.

Iā€™d recommend to do such things with an event-listener, listening to the REGISTRATION event, then setting the attributes on the user. This way, you are loosely coupled of the auth/registration flow.

Thanks @dasniko for the suggestion. Seems like that on REGISTER event, custom attributes are not persisted. Although on LOGIN event they are.
If anyone needs, I have solved the issue this way:

import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.Provider;
import org.keycloak.authentication.FormContext;
import org.keycloak.authentication.forms.RegistrationUserCreation;

@Provider
public class CustomRegistrationUserCreation extends RegistrationUserCreation {

  private static final String ID = "custom-registration-user-creation";
  private static final String REGISTRATION_STATUS = "user.attributes.REGISTRATION_STATUS";
  private static final String NOT_REGISTERED = "NOT_REGISTERED";
  private static final String USER_TYPE = "user.attributes.USER_TYPE";
  private static final String USER = "USER";

  @Override
  public String getId() {
    return ID;
  }

  @Override
  public String getDisplayType() {
    return "Registration User Creation with default attributes added";
  }

  @Override
  public String getHelpText() {
    return "Adds attributes to user on registration";
  }

  @Override
  public void success(FormContext context) {
    MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
    formData.add(REGISTRATION_STATUS, NOT_REGISTERED);
    formData.add(USER_TYPE, USER);
    super.success(context);
  }

}

Also org.keycloak.authentication.FormActionFactory file needs to be added to META-INF/services