GithubHelp home page GithubHelp logo

Comments (9)

zalavaari avatar zalavaari commented on July 17, 2024 1

Okay, my mistake. I've forgot to add the user.attributes prefix to my attributes.

from keycloak-extension-playground.

redbaron09 avatar redbaron09 commented on July 17, 2024 1

Thanks for taking the time to get back to me.
The first part was the problem for me. I was missing the link between your comment about prefixing the attribute and the problem I was seeing.
Here's something close to what I did to get it working:

public void success(FormContext context) {
   MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
   formData.add("user.attributes.my_terms_attr", String.valueOf(System.currentTimeMillis()));
   super.success(context);
}

from keycloak-extension-playground.

dvlpphb avatar dvlpphb commented on July 17, 2024 1

This is the full code that is working for us:

package xxx;

import com.google.auto.service.AutoService;
import org.keycloak.authentication.FormActionFactory;
import org.keycloak.authentication.FormContext;
import org.keycloak.authentication.ValidationContext;
import org.keycloak.authentication.forms.RegistrationUserCreation;
import org.keycloak.events.Errors;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.models.utils.FormMessage;
//import org.jboss.logging.Logger;

import javax.ws.rs.core.MultivaluedMap;
import java.util.List;
//import java.util.Map;

@AutoService(FormActionFactory.class)
public class CustomRegistrationUserCreation extends RegistrationUserCreation {
	//private static final Logger LOG = Logger.getLogger(CustomRegistrationUserCreation.class);

    public static final String ID = "xxx-registration-user-creation";

    public static final String TERMS_FIELD = "user.attributes.termsAccepted";
    public static final String TERMS_ACCEPTED_ATTRIBUTE = "user.attributes.termsLastChangeTimestamp";
    public static final String TERMS_IP_ADDRESS_ATTRIBUTE = "user.attributes.termsLastChangeIpAddress";
    public static final String TERMS_REQUIRED = "termsRequired";
    public static final String TERMS_REQUIRED_MESSAGE = "termsRequiredMessage";

    public static final String MARKETING_FIELD = "user.attributes.marketingAccepted";
    public static final String MARKETING_ACCEPTED_ATTRIBUTE = "user.attributes.marketingLastChangeTimestamp";
    public static final String MARKETING_IP_ADDRESS_ATTRIBUTE = "user.attributes.marketingLastChangeIpAddress";

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

    @Override
    public String getDisplayType() {
        return "Custom: Registration User Creation with Terms and Conditions";
    }

    @Override
    public void validate(ValidationContext context) {

        //MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
        //LOG.debugf("\n\n\n\n\ntermsAccepted formData" + formData);
        //LOG.debugf("\n\n\n\n\ntermsAccepted field" + TERMS_FIELD);

//boolean termsAccepted = formData.containsKey(TERMS_FIELD);
        String termsAccepted = formData.getFirst(TERMS_FIELD);
        //String termsAccepted = formData.get(TERMS_FIELD);
        //LOG.debugf("\n\n\n\n\ntermsAccepted" + String.valueOf(termsAccepted));

        if (! termsAccepted.equals("1")) {
            context.error(Errors.INVALID_REGISTRATION);
            formData.remove(TERMS_FIELD);

            List<FormMessage> errors = List.of(new FormMessage(TERMS_FIELD, TERMS_REQUIRED_MESSAGE));
            context.validationError(formData, errors);
            return;
		} else {
			String termsTimestamp = String.valueOf(System.currentTimeMillis());
			//LOG.debugf("\n\n\n\n\ntermsAccepted" + String.valueOf(termsTimestamp));
            formData.add(TERMS_ACCEPTED_ATTRIBUTE, termsTimestamp);

			String termsIpAddress = context.getConnection().getRemoteAddr();
			//LOG.debugf("\n\n\n\n\ntermsAccepted" + String.valueOf(termsIpAddress));
            formData.add(TERMS_IP_ADDRESS_ATTRIBUTE, termsIpAddress);

			boolean marketingAccepted = formData.containsKey(MARKETING_FIELD);
			//LOG.debugf("\n\n\n\n\ntermsAccepted" + String.valueOf(marketingAccepted));

			String marketingTimestamp = String.valueOf(System.currentTimeMillis());
			//LOG.debugf("\n\n\n\n\ntermsAccepted" + String.valueOf(marketingTimestamp));
			formData.add(MARKETING_ACCEPTED_ATTRIBUTE, marketingTimestamp);

			String marketingIpAddress = context.getConnection().getRemoteAddr();
			//LOG.debugf("\n\n\n\n\ntermsAccepted" + String.valueOf(marketingIpAddress));
			formData.add(MARKETING_IP_ADDRESS_ATTRIBUTE, marketingIpAddress);
		}
        super.validate(context);
    }

    @Override
    public void buildPage(FormContext context, LoginFormsProvider form) {
        form.setAttribute(TERMS_REQUIRED, true);
    }
}

from keycloak-extension-playground.

zalavaari avatar zalavaari commented on July 17, 2024

Same here. (with KeyCloak 16.1.1)

from keycloak-extension-playground.

dvlpphb avatar dvlpphb commented on July 17, 2024

The code is wrong.

In the success function keycloak has already inserted data into database. If you add attribute to userModel there that attribute will never be saved into database.

I have changed the approch, i removed the success function and changed the validate function like:

    public void validate(ValidationContext context) {
        MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
        // Now i use a radio instead of checkbox
        String termsAccepted = formData.getFirst(TERMS_FIELD);

        if (! termsAccepted.equals("1")) {
            context.error(Errors.INVALID_REGISTRATION);
            formData.remove(TERMS_FIELD);

            List<FormMessage> errors = List.of(new FormMessage(TERMS_FIELD, TERMS_REQUIRED_MESSAGE));
            context.validationError(formData, errors);
            return;
        } else {
	    String termsTimestamp = String.valueOf(System.currentTimeMillis());
            formData.add(TERMS_ACCEPTED_ATTRIBUTE, termsTimestamp);
	}
        super.validate(context);
    }

from keycloak-extension-playground.

zalavaari avatar zalavaari commented on July 17, 2024

Thank you for sharing!

from keycloak-extension-playground.

zalavaari avatar zalavaari commented on July 17, 2024

Hmm... are you sure formData.add(TERMS_ACCEPTED_ATTRIBUTE, termsTimestamp); is the correct line here?

from keycloak-extension-playground.

redbaron09 avatar redbaron09 commented on July 17, 2024

Thanks for sharing!
I'm experiencing a similar issue with custom attributes not saving during registration.
However, I'm unable to get it working with the example validate function you've provided.
Can you provide a more complete example?

from keycloak-extension-playground.

zalavaari avatar zalavaari commented on July 17, 2024

Hi!

Two things I learned here:

  1. The custom atttibutes must begin with the user.attributes. prefix.
  2. As @dvlpphb mentioned the current success(FormContext context) not works, but it can be fixed:
public void success(FormContext context) {
   MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
   formData.add(TERMS_ACCEPTED_ATTRIBUTE, String.valueOf(System.currentTimeMillis()));
   super.success(context);
}

from keycloak-extension-playground.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.