[keycloak-user] Limiting user registrations to closed set

luke at code-house.org luke at code-house.org
Wed Apr 4 11:07:05 EDT 2018


Since there was no answer in this topic, I can leave an answer for other people who may look for something similar.

I created a new registration flow definition with additional form action at beginning of it. My custom form action contains validation rules working on top of form data. Based on received attributes validation fails registration attempt if external system client do not contain matching user record. Thanks to that no database write attempt is made and there is no need for implementing user storage provider. I attach pseudo code for reference. There are lots of missing pieces, but it should give general idea how problem can be approached.

public class InternalUserFormAction implements FormAction {

   public static final String PROVIDER_ID = “internal-user-form-action";

   @Override
   public void validate(ValidationContext context) {
       AuthenticatorConfigModel config = context.getAuthenticatorConfig();

       // form action have one option which is external system uri, which should be called in order to check if user who is attempted to made account exists.
       String externalSystemURI = Constants.DEFAULT_SYSTEM_URI;
       if (config != null && config.getConfig() != null) {
           externalSystemURI = config.getConfig().getOrDefault(Constants.SYSTEM_URI_OPTION_NAME, Constants.DEFAULT_SYSTEM_URI);
       }

       MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
       List<FormMessage> errors = new ArrayList<>();

       String eventError = Errors.INVALID_REGISTRATION;

       Optional<String> firstName = validateAndGet(formData, errors, RegistrationPage.FIELD_FIRST_NAME, Messages.MISSING_FIRST_NAME);
       Optional<String> lastName = validateAndGet(formData, errors, RegistrationPage.FIELD_LAST_NAME, Messages.MISSING_LAST_NAME);
       Optional<String> email = validateAndGet(formData, errors, RegistrationPage.FIELD_EMAIL, Messages.MISSING_EMAIL);
       Optional<String> phone = validateAndGet(formData, errors, Constants.MOBILE_NUMBER_ATTRIBUTE, "missing_phone_number");
 
       if (errors.size() > 0) {
           fail(context, formData, eventError, errors);
           return;
       } else {
           ExternalSystemClient client = new ExternalSystemClient(externalSystemURI);
           Optional<InternalUser> internalUser = ex.find(
               firstName.orElse(null),
               lastName.orElse(null),
               email.orElse(null),
               phone.orElse(null)
           ));

           if (!internalUser.isPresent()) {
               // final check if all above data is valid
               errors.add(new FormMessage(“generic", "unknown_member"));
               fail(context, formData, eventError, errors);
               return;
           }

           context.success();
       }
   }
}

Cheers,
Łukasz
—
Twitter: ldywicki
Blog: http://dywicki.pl
Code-House - http://code-house.org

> On 29 Mar 2018, at 00:44, Łukasz Dywicki <luke at code-house.org> wrote:
> 
> Hi all,
> I have a case which is quite simple in terms of logic - I have existing
> database of users with attributes such first and last name, as well as
> email. I miss username and password or just password if I decide to use
> email as login. I would like to use attributes I know for validation of
> new user registrations.
> Any registration attempt with uknown email, first and last should be denied.
> Sadly due to necessity to host user self registration in mobile app I
> had to move it outside of keycloak. This means I use a small utility to
> create accounts using admin api.
> 
> I've tried to use UserStorageProvider, but this SPI is not permited to
> "deny" user registration. When I try to add new user, it goes in even if
> there is no matching combination of attributes. Which SPI is valid for
> my use case?
> 
> Kind regards,
> Lukasz




More information about the keycloak-user mailing list