Comments (9)
Okay, my mistake. I've forgot to add the user.attributes
prefix to my attributes.
from keycloak-extension-playground.
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.
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.
Same here. (with KeyCloak 16.1.1)
from keycloak-extension-playground.
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.
Thank you for sharing!
from keycloak-extension-playground.
Hmm... are you sure formData.add(TERMS_ACCEPTED_ATTRIBUTE, termsTimestamp);
is the correct line here?
from keycloak-extension-playground.
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.
Hi!
Two things I learned here:
- The custom atttibutes must begin with the
user.attributes.
prefix. - 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)
- dynamic idp redirector with OTP HOT 6
- there is no Alternative option in Email code Form Execution. HOT 1
- Developing using intellj jetbrains HOT 1
- Is this possible to test new endpoints during the test?
- install auth-trust-device extension fails
- BUILD FAILURE : Failed to execute goal on project integration-arquillian-util
- use remember me cookie to start authentication
- session.users().getUserById already NULL when onEvent is called after a DELETE request? HOT 2
- otp backupcodes incompatible with 16.x HOT 2
- Extend login with username cookie HOT 1
- Could not initialize class org.xnio.channels.Channels
- localhost:8081 inaccessible from Windows host machine via WSL2 (fixed) HOT 1
- Auth-trust-device: NullPointerException during first device registration/authentication
- auth-require-role-extension stopped working on Keycloak 18.0.2 (Quarkus) HOT 2
- The attribute terms_accepted is not created under 18.0.2 Quarkus
- auth-trust-device show invalid username or password
- auth-require-group-extension is not working for version 16.1.1
- jaxrs-request-filter-extension not intercepting the requests.
- Abandoned
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from keycloak-extension-playground.