8000 Add option to Force enable users created on Active Directory by oculos · Pull Request #16980 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ public boolean isActiveDirectory() {
String vendor = getVendor();
return vendor != null && vendor.equals(LDAPConstants.VENDOR_ACTIVE_DIRECTORY);
}

public boolean isEnableAdUser() {
String enableAdUser = config.getFirst(LDAPConstants.ENABLED_AD_USER_ON_REGISTRATION);
return Boolean.parseBoolean(enableAdUser);
}

public boolean isValidatePasswordPolicy() {
String validatePPolicy = config.getFirst(LDAPConstants.VALIDATE_PASSWORD_POLICY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package org.keycloak.storage.ldap;

import java.security.SecureRandom;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
Expand Down Expand Up @@ -297,7 +299,7 @@ public UserModel addUser(RealmModel realm, String username) {
user.setSingleAttribute(LDAPConstants.LDAP_ID, ldapObject.getUuid());
user.setSingleAttribute(LDAPConstants.LDAP_ENTRY_DN, ldapObject.getDn().toString());
});

// Add the user to the default groups and add default required actions
UserModel proxy = proxy(realm, user, ldapUser, true);
proxy.grantRole(realm.getDefaultRole());
Expand All @@ -310,6 +312,14 @@ public UserModel addUser(RealmModel realm, String username) {
.map(RequiredActionProviderModel::getAlias)
.forEachOrdered(proxy::addRequiredAction);

// If Active Directory and enable user by default is set, give it a random password
if (ldapIdentityStore.getConfig().isEnableAdUser()){
LDAPOperationDecorator operationDecorator = null;
ldapIdentityStore.updatePassword(ldapUser, getRandomValue(), operationDecorator);
ldapUser.setSingleAttribute(LDAPConstants.USER_ACCOUNT_CONTROL,"512");
ldapIdentityStore.update(ldapUser);
}

return proxy;
}

Expand Down Expand Up @@ -857,5 +867,18 @@ public LDAPObject loadLDAPUserByUuid(RealmModel realm, String uuid) {
return ldapQuery.getFirstResult();
}
}

private static final String CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVW1234567890%$!@*^-_";

// Generate random character of length 30.
protected String getRandomValue() {
SecureRandom r = new SecureRandom();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 25; i++) {
char c = CHARS.charAt(r.nextInt(CHARS.length()));
sb.append(c);
}
return sb.toString();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ private static List<ProviderConfigProperty> getConfigProps(ComponentModel parent
.property().name(LDAPConstants.VENDOR)
.type(ProviderConfigProperty.STRING_TYPE)
.add()
.property().name(LDAPConstants.ENABLED_AD_USER_ON_REGISTRATION)
.type(ProviderConfigProperty.BOOLEAN_TYPE)
.defaultValue("false")
.add()
.property().name(LDAPConstants.USE_PASSWORD_MODIFY_EXTENDED_OP)
.type(ProviderConfigProperty.BOOLEAN_TYPE)
.add()
Expand Down Expand Up @@ -288,12 +292,24 @@ public void validateConfiguration(KeycloakSession session, RealmModel realm, Com
throw new ComponentValidationException("ldapErrorEditModeMandatory");
}

// validatePasswordPolicy applicable only for WRITABLE mode
// validatePasswordPolicy and enableAdUser applicable only for WRITABLE mode
if (cfg.getEditMode() != UserStorageProvider.EditMode.WRITABLE) {
if (cfg.isValidatePasswordPolicy()) {
throw new ComponentValidationException("ldapErrorValidatePasswordPolicyAvailableForWritableOnly");
}
if (cfg.isEnableAdUser()){
throw new ComponentValidationException("ldapErrorEnableAdUserAvalaibleForWritableOnly");
}
}

// Enable AD User only available for vendor Active Directory
if (!cfg.isActiveDirectory()){
if (cfg.isEnableAdUser()){
throw new ComponentValidationException("ldapErrorEnableAdUserAvalaibleForAdOnly");
}

}


if (!userStorageModel.isImportEnabled() && cfg.getEditMode() == UserStorageProvider.EditMode.UNSYNCED) {
throw new ComponentValidationException("ldapErrorCantEnableUnsyncedAndImportOff");
Expand Down
10000
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,6 @@
"roleHelp": "Role to grant to user. Click 'Select Role' button to browse roles, or just type it in the textbox. To reference an application role the syntax is appname.approle, i.e. myapp.myrole.",
"groupHelp": "Group to add the user in. Fill the full path of the group including path. For example: '/root-group/child-group'.",
"ldapAttributeNameHelp": "Name of the LDAP attribute, which will be added to the new user during registration",
"ldapAttributeValueHelp": "Value of the LDAP attribute, which will be added to the new user during registration. You can either hardcode any value like 'foo' but you can also use some special tokens. Only supported token right now is '${RANDOM}', which will be replaced with some randomly generated string."
"ldapAttributeValueHelp": "Value of the LDAP attribute, which will be added to the new user during registration. You can either hardcode any value like 'foo' but you can also use some special tokens. Only supported token right now is '${RANDOM}', which will be replaced with some randomly generated string.",
"enableAdUserHelp": "Create a random value for 'unicodePwd' and set the 'userAccountControl' attribute to 512 immediately after the user is registered, so that new users are enabled by default. This setting applies only to Active Directory."
}
3 changes: 2 additions & 1 deletion js/apps/admin-ui/public/resources/en/user-federation.json
Original file line number Diff line number Diff line change
Expand Up @@ -174,5 +174,6 @@
"providerType": "Provider Type",
"parentId": "Parent ID",
"kerberosPrincipal": "Kerberos Principal",
"kerberosKeyTab": "Kerberos Key Tab"
"kerberosKeyTab": "Kerberos Key Tab",
"enableAdUser": "Force enable AD user upon creation"
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,34 @@ export const LdapSettingsAdvanced = ({
)}
></Controller>
</FormGroup>

<FormGroup
hasNoPaddingTop
label={t("enableAdUser")}
labelIcon={
<HelpItem
helpText={t("user-federation-help:enableAdUserHelp")}
fieldLabelId="user-federation:enableAdUser"
/>
}
fieldId="kc-enable-ad-user"
>
<Controller
name="config.enableAdUser"
defaultValue={["false"]}
control={form.control}
render={({ field }) => (
<Switch
id="kc-enable-ad-user"
data-testid="enable-ad-user"
label={t("common:on")}
labelOff={t("common:off")}
=> field.onChange([`${value}`])}
isChecked={field.value[0] === "true"}
aria-label={t("enableAdUser")}
/>
)}
/>
</FormGroup>
<FormGroup
label={t("validatePasswordPolicy")}
labelIcon={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ public boolean isActiveDirectory() {
return vendor != null && vendor.equals(LDAPConstants.VENDOR_ACTIVE_DIRECTORY);
}

public boolean isEnableAdUser() {
String enableAdUser = config.getFirst(LDAPConstants.ENABLED_AD_USER_ON_REGISTRATION);
return Boolean.parseBoolean(enableAdUser);
}

public boolean isValidatePasswordPolicy() {
String validatePPolicy = config.getFirst(LDAPConstants.VALIDATE_PASSWORD_POLICY);
return Boolean.parseBoolean(validatePPolicy);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ public class LDAPConstants {
public static final String EMPTY_MEMBER_ATTRIBUTE_VALUE = "cn=empty-membership-placeholder";

public static final String ENABLED = "enabled";
public static final String ENABLED_AD_USER_ON_REGISTRATION = "enableAdUser";


public static final String CUSTOM_ATTRIBUTE_CREATE_DATE = "createDate";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ ldapErrorCantEnableStartTlsAndConnectionPooling=Can not enable both StartTLS and
ldapErrorCantEnableUnsyncedAndImportOff=Can not disable Importing users when LDAP provider mode is UNSYNCED
ldapErrorMissingGroupsPathGroup=Groups path group does not exist - please create the group on specified path first
ldapErrorValidatePasswordPolicyAvailableForWritableOnly=Validate Password Policy is applicable only with WRITABLE edit mode
ldapErrorEnableAdUserAvalaibleForWritableOnly=Force Enable AD user is applicable only with WRITABLE edit mode
ldapErrorEnableAdUserAvalaibleForAdOnly=Force Enable AD user is applicable only for vendor Active Directory

clientRedirectURIsFragmentError=Redirect URIs must not contain an URI fragment
clientRootURLFragmentError=Root URL must not contain an URL fragment
Expand Down
0