Merge pull request #1295 from mposolda/ldap2
Ldap fixes + added authType to UI to allow users specify LDAP auth type
This commit is contained in:
commit
eaf5034ec7
9 changed files with 57 additions and 20 deletions
|
@ -12,7 +12,6 @@ import javax.naming.directory.SearchControls;
|
|||
|
||||
import org.keycloak.models.LDAPConstants;
|
||||
import org.keycloak.models.UserFederationProvider;
|
||||
import org.keycloak.models.UserFederationProviderModel;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
|
@ -37,8 +36,12 @@ public class LDAPConfig {
|
|||
}
|
||||
|
||||
public String getAuthType() {
|
||||
// hardcoded for now
|
||||
return "simple";
|
||||
String value = config.get(LDAPConstants.AUTH_TYPE);
|
||||
if (value == null) {
|
||||
return LDAPConstants.AUTH_TYPE_SIMPLE;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public String getSecurityProtocol() {
|
||||
|
@ -70,7 +73,7 @@ public class LDAPConfig {
|
|||
String[] objectClasses = objClassesStr.split(",");
|
||||
|
||||
// Trim them
|
||||
Set<String> userObjClasses = new HashSet<String>();
|
||||
Set<String> userObjClasses = new HashSet<>();
|
||||
for (int i=0 ; i<objectClasses.length ; i++) {
|
||||
userObjClasses.add(objectClasses[i].trim());
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ public class LDAPFederationProvider implements UserFederationProvider {
|
|||
proxied = new UnsyncedLDAPUserModelDelegate(local, this);
|
||||
}
|
||||
|
||||
Set<UserFederationMapperModel> federationMappers = realm.getUserFederationMappers();
|
||||
Set<UserFederationMapperModel> federationMappers = realm.getUserFederationMappersByFederationProvider(model.getId());
|
||||
for (UserFederationMapperModel mapperModel : federationMappers) {
|
||||
LDAPFederationMapper ldapMapper = getMapper(mapperModel);
|
||||
proxied = ldapMapper.proxy(mapperModel, this, ldapObject, proxied, realm);
|
||||
|
@ -263,7 +263,7 @@ public class LDAPFederationProvider implements UserFederationProvider {
|
|||
UserModel imported = session.userStorage().addUser(realm, ldapUsername);
|
||||
imported.setEnabled(true);
|
||||
|
||||
Set<UserFederationMapperModel> federationMappers = realm.getUserFederationMappers();
|
||||
Set<UserFederationMapperModel> federationMappers = realm.getUserFederationMappersByFederationProvider(getModel().getId());
|
||||
for (UserFederationMapperModel mapperModel : federationMappers) {
|
||||
LDAPFederationMapper ldapMapper = getMapper(mapperModel);
|
||||
ldapMapper.onImportUserFromLDAP(mapperModel, this, ldapUser, imported, realm, true);
|
||||
|
@ -399,7 +399,7 @@ public class LDAPFederationProvider implements UserFederationProvider {
|
|||
if ((fedModel.getId().equals(currentUser.getFederationLink())) && (ldapUser.getUuid().equals(currentUser.getAttribute(LDAPConstants.LDAP_ID)))) {
|
||||
|
||||
// Update keycloak user
|
||||
Set<UserFederationMapperModel> federationMappers = realm.getUserFederationMappers();
|
||||
Set<UserFederationMapperModel> federationMappers = realm.getUserFederationMappersByFederationProvider(model.getId());
|
||||
for (UserFederationMapperModel mapperModel : federationMappers) {
|
||||
LDAPFederationMapper ldapMapper = getMapper(mapperModel);
|
||||
ldapMapper.onImportUserFromLDAP(mapperModel, this, ldapUser, currentUser, realm, false);
|
||||
|
|
|
@ -62,7 +62,7 @@ public class LDAPUtils {
|
|||
ldapQuery.addSearchDns(config.getUserDns());
|
||||
ldapQuery.addObjectClasses(config.getUserObjectClasses());
|
||||
|
||||
Set<UserFederationMapperModel> mapperModels = realm.getUserFederationMappers();
|
||||
Set<UserFederationMapperModel> mapperModels = realm.getUserFederationMappersByFederationProvider(ldapProvider.getModel().getId());
|
||||
ldapQuery.addMappers(mapperModels);
|
||||
|
||||
return ldapQuery;
|
||||
|
|
|
@ -108,7 +108,7 @@ public class LDAPIdentityStore implements IdentityStore {
|
|||
|
||||
@Override
|
||||
public List<LDAPObject> fetchQueryResults(LDAPIdentityQuery identityQuery) {
|
||||
List<LDAPObject> results = new ArrayList<LDAPObject>();
|
||||
List<LDAPObject> results = new ArrayList<>();
|
||||
|
||||
try {
|
||||
if (identityQuery.getSorting() != null && !identityQuery.getSorting().isEmpty()) {
|
||||
|
@ -153,7 +153,7 @@ public class LDAPIdentityStore implements IdentityStore {
|
|||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ModelException("Querying of identity type failed " + identityQuery, e);
|
||||
throw new ModelException("Querying of LDAP failed " + identityQuery, e);
|
||||
}
|
||||
|
||||
return results;
|
||||
|
@ -382,7 +382,7 @@ public class LDAPIdentityStore implements IdentityStore {
|
|||
NamingEnumeration<? extends Attribute> ldapAttributes = attributes.getAll();
|
||||
|
||||
// Exact name of attributes might be different
|
||||
List<String> uppercasedReadOnlyAttrNames = new ArrayList<String>();
|
||||
List<String> uppercasedReadOnlyAttrNames = new ArrayList<>();
|
||||
for (String readonlyAttr : readOnlyAttrNames) {
|
||||
uppercasedReadOnlyAttrNames.add(readonlyAttr.toUpperCase());
|
||||
}
|
||||
|
@ -402,11 +402,11 @@ public class LDAPIdentityStore implements IdentityStore {
|
|||
Object uuidValue = ldapAttribute.get();
|
||||
ldapObject.setUuid(this.operationManager.decodeEntryUUID(uuidValue));
|
||||
} else {
|
||||
Set<String> attrValues = new TreeSet<String>();
|
||||
Set<String> attrValues = new TreeSet<>();
|
||||
NamingEnumeration<?> enumm = ldapAttribute.getAll();
|
||||
while (enumm.hasMoreElements()) {
|
||||
String objectClass = enumm.next().toString();
|
||||
attrValues.add(objectClass);
|
||||
String attrVal = enumm.next().toString();
|
||||
attrValues.add(attrVal);
|
||||
}
|
||||
|
||||
if (ldapAttributeName.toLowerCase().equals(LDAPConstants.OBJECT_CLASS)) {
|
||||
|
|
|
@ -451,8 +451,9 @@ public class LDAPOperationManager {
|
|||
private Map<String, Object> createConnectionProperties() {
|
||||
HashMap<String, Object> env = new HashMap<String, Object>();
|
||||
|
||||
String authType = this.config.getAuthType();
|
||||
env.put(Context.INITIAL_CONTEXT_FACTORY, this.config.getFactoryName());
|
||||
env.put(Context.SECURITY_AUTHENTICATION, this.config.getAuthType());
|
||||
env.put(Context.SECURITY_AUTHENTICATION, authType);
|
||||
|
||||
String protocol = this.config.getSecurityProtocol();
|
||||
|
||||
|
@ -468,7 +469,7 @@ public class LDAPOperationManager {
|
|||
bindCredential = this.config.getBindCredential().toCharArray();
|
||||
}
|
||||
|
||||
if (bindDN != null) {
|
||||
if (!LDAPConstants.AUTH_TYPE_NONE.equals(authType)) {
|
||||
env.put(Context.SECURITY_PRINCIPAL, bindDN);
|
||||
env.put(Context.SECURITY_CREDENTIALS, bindCredential);
|
||||
}
|
||||
|
|
|
@ -541,6 +541,7 @@ module.controller('LDAPCtrl', function($scope, $location, $route, Notifications,
|
|||
instance.config.debug = false;
|
||||
instance.config.useKerberosForPasswordAuthentication = false;
|
||||
|
||||
instance.config.authType = 'simple';
|
||||
instance.config.batchSizeForSync = DEFAULT_BATCH_SIZE;
|
||||
instance.config.searchScope = "1";
|
||||
|
||||
|
@ -556,12 +557,16 @@ module.controller('LDAPCtrl', function($scope, $location, $route, Notifications,
|
|||
instance.config.debug = (instance.config.debug === 'true' || instance.config.debug === true);
|
||||
instance.config.useKerberosForPasswordAuthentication = (instance.config.useKerberosForPasswordAuthentication === 'true' || instance.config.useKerberosForPasswordAuthentication === true);
|
||||
|
||||
if (!instance.config.authType) {
|
||||
instance.config.authType = 'simple';
|
||||
}
|
||||
if (!instance.config.batchSizeForSync) {
|
||||
instance.config.batchSizeForSync = DEFAULT_BATCH_SIZE;
|
||||
}
|
||||
if (!instance.config.searchScope) {
|
||||
instance.config.searchScope = "1";
|
||||
instance.config.searchScope = '1';
|
||||
}
|
||||
|
||||
$scope.fullSyncEnabled = (instance.fullSyncPeriod && instance.fullSyncPeriod > 0);
|
||||
$scope.changedSyncEnabled = (instance.changedSyncPeriod && instance.changedSyncPeriod > 0);
|
||||
}
|
||||
|
@ -581,6 +586,11 @@ module.controller('LDAPCtrl', function($scope, $location, $route, Notifications,
|
|||
{ "id": "other", "name": "Other" }
|
||||
];
|
||||
|
||||
$scope.authTypes = [
|
||||
{ "id": "none", "name": "none" },
|
||||
{ "id": "simple", "name": "simple" }
|
||||
];
|
||||
|
||||
$scope.searchScopes = [
|
||||
{ "id": "1", "name": "One Level" },
|
||||
{ "id": "2", "name": "Subtree" }
|
||||
|
|
|
@ -119,16 +119,29 @@
|
|||
</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group clearfix">
|
||||
<label class="col-md-2 control-label" for="authType"><span class="required">*</span> Authentication Type</label>
|
||||
<div class="col-md-6">
|
||||
<div>
|
||||
<select class="form-control" id="authType"
|
||||
ng-model="instance.config.authType"
|
||||
ng-options="authType.id as authType.name for authType in authTypes"
|
||||
required>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<kc-tooltip>LDAP Authentication type. Right now just 'none' (anonymous LDAP authentication) or 'simple' (Bind credential + Bind password authentication) mechanisms are available</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group clearfix" data-ng-hide="instance.config.authType == 'none'">
|
||||
<label class="col-md-2 control-label" for="ldapBindDn"><span class="required">*</span> Bind DN</label>
|
||||
<div class="col-md-6">
|
||||
<input class="form-control" id="ldapBindDn" type="text" ng-model="instance.config.bindDn" placeholder="LDAP Bind DN" required>
|
||||
<input class="form-control" id="ldapBindDn" type="text" ng-model="instance.config.bindDn" placeholder="LDAP Bind DN" data-ng-required="instance.config.authType != 'none'">
|
||||
</div>
|
||||
<kc-tooltip>DN of LDAP admin, which will be used by Keycloak to access LDAP server</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group clearfix">
|
||||
<div class="form-group clearfix" data-ng-hide="instance.config.authType == 'none'">
|
||||
<label class="col-md-2 control-label" for="ldapBindCredential"><span class="required">*</span> Bind Credential</label>
|
||||
<div class="col-md-6">
|
||||
<input class="form-control" id="ldapBindCredential" type="password" ng-model="instance.config.bindCredential" placeholder="LDAP Bind Credentials" required>
|
||||
<input class="form-control" id="ldapBindCredential" type="password" ng-model="instance.config.bindCredential" placeholder="LDAP Bind Credentials" data-ng-required="instance.config.authType != 'none'">
|
||||
</div>
|
||||
<kc-tooltip>Password of LDAP admin</kc-tooltip>
|
||||
<div class="col-sm-4" data-ng-show="access.manageRealm">
|
||||
|
|
|
@ -23,6 +23,10 @@ public class LDAPConstants {
|
|||
public static final String BIND_DN = "bindDn";
|
||||
public static final String BIND_CREDENTIAL = "bindCredential";
|
||||
|
||||
public static final String AUTH_TYPE = "authType";
|
||||
public static final String AUTH_TYPE_NONE = "none";
|
||||
public static final String AUTH_TYPE_SIMPLE = "simple";
|
||||
|
||||
public static final String SEARCH_SCOPE = "searchScope";
|
||||
public static final String CONNECTION_POOLING = "connectionPooling";
|
||||
public static final String PAGINATION = "pagination";
|
||||
|
|
|
@ -4,6 +4,8 @@ import javax.ws.rs.core.Context;
|
|||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.ext.ExceptionMapper;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.messages.MessagesProvider;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.ModelException;
|
||||
|
@ -15,6 +17,8 @@ import org.keycloak.services.ErrorResponse;
|
|||
@Provider
|
||||
public class ModelExceptionMapper implements ExceptionMapper<ModelException> {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(ModelExceptionMapper.class);
|
||||
|
||||
@Context
|
||||
private KeycloakSession session;
|
||||
|
||||
|
@ -22,6 +26,8 @@ public class ModelExceptionMapper implements ExceptionMapper<ModelException> {
|
|||
public Response toResponse(ModelException ex) {
|
||||
String message = session.getProvider(MessagesProvider.class, "admin")
|
||||
.getMessage(ex.getMessage(), ex.getParameters());
|
||||
|
||||
logger.error(message, ex);
|
||||
return ErrorResponse.error(message, Response.Status.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue