use of org.keycloak.models.utils.UserModelDelegate in project keycloak by keycloak.
the class IdpReviewProfileAuthenticator method actionImpl.
@Override
protected void actionImpl(AuthenticationFlowContext context, SerializedBrokeredIdentityContext userCtx, BrokeredIdentityContext brokerContext) {
EventBuilder event = context.getEvent();
// velias: looks like UPDATE_PROFILE event is not fired. IMHO it should not be fired here as user record in keycloak is not changed, user doesn't exist yet
event.event(EventType.UPDATE_PROFILE).detail(Details.CONTEXT, UserProfileContext.IDP_REVIEW.name());
MultivaluedMap<String, String> formData = context.getHttpRequest().getDecodedFormParameters();
UserModelDelegate updatedProfile = new UserModelDelegate(null) {
@Override
public String getId() {
return userCtx.getId();
}
@Override
public Map<String, List<String>> getAttributes() {
return userCtx.getAttributes();
}
@Override
public Stream<String> getAttributeStream(String name) {
return userCtx.getAttribute(name).stream();
}
@Override
public void setAttribute(String name, List<String> values) {
userCtx.setAttribute(name, values);
}
@Override
public void removeAttribute(String name) {
userCtx.getAttributes().remove(name);
}
@Override
public String getFirstAttribute(String name) {
return userCtx.getFirstAttribute(name);
}
@Override
public String getUsername() {
return userCtx.getUsername();
}
};
UserProfileProvider profileProvider = context.getSession().getProvider(UserProfileProvider.class);
UserProfile profile = profileProvider.create(UserProfileContext.IDP_REVIEW, formData, updatedProfile);
try {
String oldEmail = userCtx.getEmail();
profile.update((attributeName, userModel, oldValue) -> {
if (attributeName.equals(UserModel.EMAIL)) {
context.getAuthenticationSession().setAuthNote(UPDATE_PROFILE_EMAIL_CHANGED, "true");
event.clone().event(EventType.UPDATE_EMAIL).detail(Details.CONTEXT, UserProfileContext.IDP_REVIEW.name()).detail(Details.PREVIOUS_EMAIL, oldEmail).detail(Details.UPDATED_EMAIL, profile.getAttributes().getFirstValue(UserModel.EMAIL)).success();
}
});
} catch (ValidationException pve) {
List<FormMessage> errors = Validation.getFormErrorsFromValidation(pve.getErrors());
Response challenge = context.form().setErrors(errors).setAttribute(LoginFormsProvider.UPDATE_PROFILE_CONTEXT_ATTR, userCtx).setFormData(formData).createUpdateProfilePage();
context.challenge(challenge);
return;
}
userCtx.saveToAuthenticationSession(context.getAuthenticationSession(), BROKERED_CONTEXT_NOTE);
logger.debugf("Profile updated successfully after first authentication with identity provider '%s' for broker user '%s'.", brokerContext.getIdpConfig().getAlias(), userCtx.getUsername());
String newEmail = profile.getAttributes().getFirstValue(UserModel.EMAIL);
event.detail(Details.UPDATED_EMAIL, newEmail);
// Ensure page is always shown when user later returns to it - for example with form "back" button
context.getAuthenticationSession().setAuthNote(ENFORCE_UPDATE_PROFILE, "true");
context.success();
}
use of org.keycloak.models.utils.UserModelDelegate in project keycloak by keycloak.
the class HardcodedAttributeMapper method proxy.
@Override
public UserModel proxy(final LDAPObject ldapUser, UserModel delegate, RealmModel realm) {
String userModelAttrName = getUserModelAttribute();
String attributeValue = getAttributeValue();
delegate = new UserModelDelegate(delegate) {
@Override
public Stream<String> getAttributeStream(String name) {
if (userModelAttrName.equals(name)) {
return Stream.of(attributeValue);
}
return super.getAttributeStream(name);
}
@Override
public boolean isEmailVerified() {
if (userModelAttrName.equals("emailVerified")) {
return Boolean.valueOf(attributeValue);
}
return super.isEmailVerified();
}
@Override
public boolean isEnabled() {
if (userModelAttrName.equals("enabled")) {
return Boolean.valueOf(attributeValue);
}
return super.isEnabled();
}
};
return delegate;
}
use of org.keycloak.models.utils.UserModelDelegate in project keycloak by keycloak.
the class UserAttributeLDAPStorageMapper method proxy.
@Override
public UserModel proxy(final LDAPObject ldapUser, UserModel delegate, RealmModel realm) {
final String userModelAttrName = getUserModelAttribute();
final String ldapAttrName = getLdapAttributeName();
boolean isAlwaysReadValueFromLDAP = parseBooleanParameter(mapperModel, ALWAYS_READ_VALUE_FROM_LDAP);
final boolean isMandatoryInLdap = parseBooleanParameter(mapperModel, IS_MANDATORY_IN_LDAP);
final boolean isBinaryAttribute = parseBooleanParameter(mapperModel, IS_BINARY_ATTRIBUTE);
// For writable mode, we want to propagate writing of attribute to LDAP as well
if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && !isReadOnly()) {
delegate = new TxAwareLDAPUserModelDelegate(delegate, ldapProvider, ldapUser) {
@Override
public void setSingleAttribute(String name, String value) {
if (UserModel.USERNAME.equals(name)) {
setUsername(value);
} else if (UserModel.EMAIL.equals(name)) {
setEmail(value);
} else if (setLDAPAttribute(name, value)) {
super.setSingleAttribute(name, value);
}
}
@Override
public void setAttribute(String name, List<String> values) {
if (UserModel.USERNAME.equals(name)) {
setUsername((values != null && values.size() > 0) ? values.get(0) : null);
} else if (UserModel.EMAIL.equals(name)) {
setEmail((values != null && values.size() > 0) ? values.get(0) : null);
} else if (setLDAPAttribute(name, values)) {
super.setAttribute(name, values);
}
}
@Override
public void removeAttribute(String name) {
if (!UserModel.USERNAME.equals(name)) {
// do not remove username
if (setLDAPAttribute(name, null)) {
super.removeAttribute(name);
}
}
}
@Override
public void setUsername(String username) {
String lowercaseUsername = KeycloakModelUtils.toLowerCaseSafe(username);
checkDuplicateUsername(userModelAttrName, lowercaseUsername, realm, ldapProvider.getSession(), this);
setLDAPAttribute(UserModel.USERNAME, lowercaseUsername);
super.setUsername(lowercaseUsername);
}
@Override
public void setEmail(String email) {
String lowercaseEmail = KeycloakModelUtils.toLowerCaseSafe(email);
checkDuplicateEmail(userModelAttrName, email, realm, ldapProvider.getSession(), this);
setLDAPAttribute(UserModel.EMAIL, email);
super.setEmail(lowercaseEmail);
}
@Override
public void setEnabled(boolean enabled) {
setLDAPAttribute(UserModel.ENABLED, Boolean.toString(enabled));
super.setEnabled(enabled);
}
@Override
public void setLastName(String lastName) {
setLDAPAttribute(UserModel.LAST_NAME, lastName);
super.setLastName(lastName);
}
@Override
public void setFirstName(String firstName) {
setLDAPAttribute(UserModel.FIRST_NAME, firstName);
super.setFirstName(firstName);
}
@Override
public void setEmailVerified(boolean verified) {
setLDAPAttribute(UserModel.EMAIL_VERIFIED, Boolean.toString(verified));
super.setEmailVerified(verified);
}
protected boolean setLDAPAttribute(String modelAttrName, Object value) {
if (modelAttrName.equalsIgnoreCase(userModelAttrName)) {
if (UserAttributeLDAPStorageMapper.logger.isTraceEnabled()) {
UserAttributeLDAPStorageMapper.logger.tracef("Pushing user attribute to LDAP. username: %s, Model attribute name: %s, LDAP attribute name: %s, Attribute value: %s", getUsername(), modelAttrName, ldapAttrName, value);
}
markUpdatedAttributeInTransaction(modelAttrName);
if (value == null) {
if (isMandatoryInLdap) {
ldapUser.setSingleAttribute(ldapAttrName, LDAPConstants.EMPTY_ATTRIBUTE_VALUE);
} else {
ldapUser.setAttribute(ldapAttrName, new LinkedHashSet<String>());
}
} else if (value instanceof String) {
ldapUser.setSingleAttribute(ldapAttrName, (String) value);
} else {
List<String> asList = (List<String>) value;
if (asList.isEmpty() && isMandatoryInLdap) {
ldapUser.setSingleAttribute(ldapAttrName, LDAPConstants.EMPTY_ATTRIBUTE_VALUE);
} else {
ldapUser.setAttribute(ldapAttrName, new LinkedHashSet<>(asList));
}
}
if (isBinaryAttribute) {
UserAttributeLDAPStorageMapper.logger.debugf("Skip writing model attribute '%s' to DB for user '%s' as it is mapped to binary LDAP attribute.", userModelAttrName, getUsername());
return false;
} else {
return true;
}
}
return true;
}
};
} else if (isBinaryAttribute) {
delegate = new UserModelDelegate(delegate) {
@Override
public void setSingleAttribute(String name, String value) {
if (name.equalsIgnoreCase(userModelAttrName)) {
logSkipDBWrite();
} else {
super.setSingleAttribute(name, value);
}
}
@Override
public void setAttribute(String name, List<String> values) {
if (name.equalsIgnoreCase(userModelAttrName)) {
logSkipDBWrite();
} else {
super.setAttribute(name, values);
}
}
@Override
public void removeAttribute(String name) {
if (name.equalsIgnoreCase(userModelAttrName)) {
logSkipDBWrite();
} else {
super.removeAttribute(name);
}
}
private void logSkipDBWrite() {
logger.debugf("Skip writing model attribute '%s' to DB for user '%s' as it is mapped to binary LDAP attribute", userModelAttrName, getUsername());
}
};
}
// We prefer to read attribute value from LDAP instead of from local Keycloak DB
if (isAlwaysReadValueFromLDAP) {
delegate = new UserModelDelegate(delegate) {
@Override
public String getFirstAttribute(String name) {
if (name.equalsIgnoreCase(userModelAttrName)) {
return ldapUser.getAttributeAsString(ldapAttrName);
} else {
return super.getFirstAttribute(name);
}
}
@Override
public Stream<String> getAttributeStream(String name) {
if (name.equalsIgnoreCase(userModelAttrName)) {
Collection<String> ldapAttrValue = ldapUser.getAttributeAsSet(ldapAttrName);
if (ldapAttrValue == null) {
return Stream.empty();
} else {
return ldapAttrValue.stream();
}
} else {
return super.getAttributeStream(name);
}
}
@Override
public Map<String, List<String>> getAttributes() {
Map<String, List<String>> attrs = new HashMap<>(super.getAttributes());
// Ignore UserModel properties
if (userModelProperties.get(userModelAttrName.toLowerCase()) != null) {
return attrs;
}
Set<String> allLdapAttrValues = ldapUser.getAttributeAsSet(ldapAttrName);
if (allLdapAttrValues != null) {
attrs.put(userModelAttrName, new ArrayList<>(allLdapAttrValues));
}
return attrs;
}
@Override
public String getEmail() {
if (UserModel.EMAIL.equalsIgnoreCase(userModelAttrName)) {
return ldapUser.getAttributeAsString(ldapAttrName);
} else {
return super.getEmail();
}
}
@Override
public boolean isEnabled() {
if (UserModel.ENABLED.equalsIgnoreCase(userModelAttrName)) {
return Boolean.parseBoolean(ldapUser.getAttributeAsString(ldapAttrName));
} else {
return super.isEnabled();
}
}
@Override
public boolean isEmailVerified() {
if (UserModel.EMAIL_VERIFIED.equalsIgnoreCase(userModelAttrName)) {
return Boolean.parseBoolean(ldapUser.getAttributeAsString(ldapAttrName));
} else {
return super.isEmailVerified();
}
}
@Override
public String getLastName() {
if (UserModel.LAST_NAME.equalsIgnoreCase(userModelAttrName)) {
return ldapUser.getAttributeAsString(ldapAttrName);
} else {
return super.getLastName();
}
}
@Override
public String getFirstName() {
if (UserModel.FIRST_NAME.equalsIgnoreCase(userModelAttrName)) {
return ldapUser.getAttributeAsString(ldapAttrName);
} else {
return super.getFirstName();
}
}
};
}
return delegate;
}
use of org.keycloak.models.utils.UserModelDelegate in project keycloak by keycloak.
the class LdapManyObjectsInitializerCommand method addLDAPUser.
private static LDAPObject addLDAPUser(LDAPStorageProvider ldapProvider, RealmModel realm, final String username, final String firstName, final String lastName, final String email, String groupsDN, int startOffsetGroups, int countGroups) {
UserModel helperUser = new UserModelDelegate(null) {
@Override
public String getUsername() {
return username;
}
@Override
public String getFirstName() {
return firstName;
}
@Override
public String getLastName() {
return lastName;
}
@Override
public String getEmail() {
return email;
}
@Override
public Stream<String> getAttributeStream(String name) {
if (UserModel.FIRST_NAME.equals(name)) {
return Stream.of(firstName);
} else if (UserModel.LAST_NAME.equals(name)) {
return Stream.of(lastName);
} else if (UserModel.EMAIL.equals(name)) {
return Stream.of(email);
} else if (UserModel.USERNAME.equals(name)) {
return Stream.of(username);
} else if ("street".equals(name)) {
Stream.Builder<String> builder = Stream.builder();
for (int i = startOffsetGroups; i < startOffsetGroups + countGroups; i++) {
String groupName = "group" + i;
LDAPDn groupDn = LDAPDn.fromString(groupsDN);
groupDn.addFirst("cn", groupName);
builder.add(groupDn.toString());
}
return builder.build();
} else {
return Stream.empty();
}
}
};
return LDAPUtils.addUserToLDAP(ldapProvider, realm, helperUser);
}
use of org.keycloak.models.utils.UserModelDelegate in project keycloak by keycloak.
the class HardcodedLDAPRoleStorageMapper method proxy.
@Override
public UserModel proxy(LDAPObject ldapUser, UserModel delegate, RealmModel realm) {
return new UserModelDelegate(delegate) {
@Override
public Stream<RoleModel> getRealmRoleMappingsStream() {
Stream<RoleModel> realmRoleMappings = super.getRealmRoleMappingsStream();
RoleModel role = getRole(realm);
if (role != null && role.getContainer().equals(realm)) {
realmRoleMappings = Stream.concat(realmRoleMappings, Stream.of(role));
}
return realmRoleMappings;
}
@Override
public Stream<RoleModel> getClientRoleMappingsStream(ClientModel app) {
Stream<RoleModel> clientRoleMappings = super.getClientRoleMappingsStream(app);
RoleModel role = getRole(realm);
if (role != null && role.getContainer().equals(app)) {
return Stream.concat(clientRoleMappings, Stream.of(role));
}
return clientRoleMappings;
}
@Override
public boolean hasDirectRole(RoleModel role) {
return super.hasDirectRole(role) || role.equals(getRole(realm));
}
@Override
public boolean hasRole(RoleModel role) {
return super.hasRole(role) || role.equals(getRole(realm));
}
@Override
public Stream<RoleModel> getRoleMappingsStream() {
Stream<RoleModel> roleMappings = super.getRoleMappingsStream();
RoleModel role = getRole(realm);
if (role != null) {
roleMappings = Stream.concat(roleMappings, Stream.of(role));
}
return roleMappings;
}
@Override
public void deleteRoleMapping(RoleModel role) {
if (role.equals(getRole(realm))) {
throw new ModelException("Not possible to delete role. It's hardcoded by LDAP mapper");
} else {
super.deleteRoleMapping(role);
}
}
};
}
Aggregations