use of org.keycloak.storage.ldap.idm.model.LDAPObject 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.storage.ldap.idm.model.LDAPObject in project keycloak by keycloak.
the class LDAPSamlIdPInitiatedVaryingLetterCaseTest method afterImportTestRealm.
@Override
protected void afterImportTestRealm() {
getTestingClient().server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
RealmModel appRealm = ctx.getRealm();
// Delete all LDAP users
LDAPTestUtils.removeAllLDAPUsers(ctx.getLdapProvider(), appRealm);
// Add some new LDAP users for testing
LDAPObject user = LDAPTestUtils.addLDAPUser(ctx.getLdapProvider(), appRealm, USER_NAME_LDAP, USER_FIRST_NAME, USER_LAST_NAME, USER_EMAIL, USER_STREET, USER_POSTAL_CODE);
LDAPTestUtils.updateLDAPPassword(ctx.getLdapProvider(), user, USER_PASSWORD);
});
ComponentRepresentation ldap = testRealm().components().query(null, "org.keycloak.storage.UserStorageProvider").get(0);
ComponentRepresentation ldapMapper = new ComponentRepresentation();
ldapMapper.setName("uid-to-user-attr-mapper");
ldapMapper.setProviderId(UserAttributeLDAPStorageMapperFactory.PROVIDER_ID);
ldapMapper.setProviderType("org.keycloak.storage.ldap.mappers.LDAPStorageMapper");
ldapMapper.setParentId(ldap.getId());
MultivaluedHashMap<String, String> config = new MultivaluedHashMap<>();
config.add(UserAttributeLDAPStorageMapper.USER_MODEL_ATTRIBUTE, "ldapUid");
config.add(UserAttributeLDAPStorageMapper.LDAP_ATTRIBUTE, "uid");
config.add(UserAttributeLDAPStorageMapper.READ_ONLY, "true");
config.add(UserAttributeLDAPStorageMapper.IS_MANDATORY_IN_LDAP, "true");
ldapMapper.setConfig(config);
testRealm().components().add(ldapMapper);
}
use of org.keycloak.storage.ldap.idm.model.LDAPObject in project keycloak by keycloak.
the class LDAPRoleMappingsTest method test03_importRoleMappings.
@Test
public void test03_importRoleMappings() {
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
RealmModel appRealm = ctx.getRealm();
LDAPTestUtils.addOrUpdateRoleLDAPMappers(appRealm, ctx.getLdapModel(), LDAPGroupMapperMode.IMPORT);
// Add some role mappings directly in LDAP
ComponentModel roleMapperModel = LDAPTestUtils.getSubcomponentByName(appRealm, ctx.getLdapModel(), "realmRolesMapper");
LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ctx.getLdapModel());
RoleLDAPStorageMapper roleMapper = LDAPTestUtils.getRoleMapper(roleMapperModel, ldapProvider, appRealm);
LDAPObject robLdap = ldapProvider.loadLDAPUserByUsername(appRealm, "robkeycloak");
roleMapper.addRoleMappingInLDAP("realmRole1", robLdap);
roleMapper.addRoleMappingInLDAP("realmRole2", robLdap);
// Get user and check that he has requested roles from LDAP
UserModel rob = session.users().getUserByUsername(appRealm, "robkeycloak");
RoleModel realmRole1 = appRealm.getRole("realmRole1");
RoleModel realmRole2 = appRealm.getRole("realmRole2");
RoleModel realmRole3 = appRealm.getRole("realmRole3");
if (realmRole3 == null) {
realmRole3 = appRealm.addRole("realmRole3");
}
Set<RoleModel> robRoles = rob.getRealmRoleMappingsStream().collect(Collectors.toSet());
Assert.assertTrue(robRoles.contains(realmRole1));
Assert.assertTrue(robRoles.contains(realmRole2));
Assert.assertFalse(robRoles.contains(realmRole3));
// Add some role mappings in model and check that user has it
rob.grantRole(realmRole3);
robRoles = rob.getRealmRoleMappingsStream().collect(Collectors.toSet());
Assert.assertTrue(robRoles.contains(realmRole3));
// Delete some role mappings in LDAP and check that it doesn't have any effect and user still has role
deleteRoleMappingsInLDAP(roleMapper, robLdap, "realmRole1");
deleteRoleMappingsInLDAP(roleMapper, robLdap, "realmRole2");
robRoles = rob.getRealmRoleMappingsStream().collect(Collectors.toSet());
Assert.assertTrue(robRoles.contains(realmRole1));
Assert.assertTrue(robRoles.contains(realmRole2));
// Delete role mappings through model and verifies that user doesn't have them anymore
rob.deleteRoleMapping(realmRole1);
rob.deleteRoleMapping(realmRole2);
rob.deleteRoleMapping(realmRole3);
robRoles = rob.getRealmRoleMappingsStream().collect(Collectors.toSet());
Assert.assertFalse(robRoles.contains(realmRole1));
Assert.assertFalse(robRoles.contains(realmRole2));
Assert.assertFalse(robRoles.contains(realmRole3));
});
}
use of org.keycloak.storage.ldap.idm.model.LDAPObject in project keycloak by keycloak.
the class LDAPRoleMappingsTest method test05_getRolesFromUserMemberOfStrategyTest.
// KEYCLOAK-5848
// Test GET_ROLES_FROM_USER_MEMBEROF_ATTRIBUTE with custom 'Member-Of LDAP Attribute'. As a workaround, we are testing this with custom attribute "street"
// just because it's available on all the LDAP servers
@Test
public void test05_getRolesFromUserMemberOfStrategyTest() throws Exception {
ComponentRepresentation realmRoleMapper = findMapperRepByName("realmRolesMapper");
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
RealmModel appRealm = ctx.getRealm();
// Create street attribute mapper
LDAPTestUtils.addUserAttributeMapper(appRealm, ctx.getLdapModel(), "streetMapper", "street", LDAPConstants.STREET);
// Find DN of "group1"
ComponentModel mapperModel = LDAPTestUtils.getSubcomponentByName(appRealm, ctx.getLdapModel(), "realmRolesMapper");
RoleLDAPStorageMapper roleMapper = LDAPTestUtils.getRoleMapper(mapperModel, ctx.getLdapProvider(), appRealm);
LDAPObject ldapRole = roleMapper.loadLDAPRoleByName("realmRole1");
String ldapRoleDN = ldapRole.getDn().toString();
// Create new user in LDAP. Add him some "street" referencing existing LDAP Group
LDAPObject carlos = LDAPTestUtils.addLDAPUser(ctx.getLdapProvider(), appRealm, "carloskeycloak", "Carlos", "Doel", "carlos.doel@email.org", ldapRoleDN, "1234");
LDAPTestUtils.updateLDAPPassword(ctx.getLdapProvider(), carlos, "Password1");
// Update group mapper
LDAPTestUtils.updateGroupMapperConfigOptions(mapperModel, RoleMapperConfig.USER_ROLES_RETRIEVE_STRATEGY, RoleMapperConfig.GET_ROLES_FROM_USER_MEMBEROF_ATTRIBUTE, RoleMapperConfig.MEMBEROF_LDAP_ATTRIBUTE, LDAPConstants.STREET);
appRealm.updateComponent(mapperModel);
});
ComponentRepresentation streetMapper = findMapperRepByName("streetMapper");
testingClient.server().run(session -> {
LDAPTestContext ctx = LDAPTestContext.init(session);
RealmModel appRealm = ctx.getRealm();
// Get user in Keycloak. Ensure that he is member of requested group
UserModel carlos = session.users().getUserByUsername(appRealm, "carloskeycloak");
Set<RoleModel> carlosRoles = carlos.getRealmRoleMappingsStream().collect(Collectors.toSet());
RoleModel realmRole1 = appRealm.getRole("realmRole1");
RoleModel realmRole2 = appRealm.getRole("realmRole2");
Assert.assertTrue(carlosRoles.contains(realmRole1));
Assert.assertFalse(carlosRoles.contains(realmRole2));
});
// Revert mappers
testRealm().components().component(streetMapper.getId()).remove();
testRealm().components().component(realmRoleMapper.getId()).remove();
realmRoleMapper.setId(null);
testRealm().components().add(realmRoleMapper);
}
use of org.keycloak.storage.ldap.idm.model.LDAPObject in project keycloak by keycloak.
the class LDAPRoleMappingsTest method deleteRoleMappingsInLDAP.
private static void deleteRoleMappingsInLDAP(RoleLDAPStorageMapper roleMapper, LDAPObject ldapUser, String roleName) {
LDAPObject ldapRole1 = roleMapper.loadLDAPRoleByName(roleName);
roleMapper.deleteRoleMappingInLDAP(ldapUser, ldapRole1);
}
Aggregations