Skip to content
Snippets Groups Projects
Commit 894f3cd2 authored by Mike McKay's avatar Mike McKay
Browse files

XNAT-4387 Made auth methods fully customizable via plugins. If none are...

XNAT-4387 Made auth methods fully customizable via plugins. If none are specified, it will default to db authentication, but if any are specified, only the specified ones will show up. I also added support for an order property to control the order of the methods in the dropdown, as well as the order in which they are checked when users attempt authentication. I see this plugin-based way of configuring providers remaining as an alternative to AdminUI configuration once that is implemented.
parent 0e257475
No related branches found
No related tags found
No related merge requests found
......@@ -253,9 +253,11 @@ public class XnatProviderManager extends ProviderManager {
private XnatAuthenticationProvider findAuthenticationProvider(XnatAuthenticationProviderMatcher matcher) {
List<AuthenticationProvider> prov = getProviders();
for (AuthenticationProvider ap : prov) {
XnatAuthenticationProvider xap = (XnatAuthenticationProvider) ap;
if (matcher.matches(xap)) {
return xap;
if(XnatAuthenticationProvider.class.isAssignableFrom(ap.getClass())) {
XnatAuthenticationProvider xap = (XnatAuthenticationProvider) ap;
if (matcher.matches(xap)) {
return xap;
}
}
}
return null;
......
......@@ -110,6 +110,16 @@ public class AliasTokenAuthenticationProvider extends AbstractUserDetailsAuthent
return getName();
}
@Override
public int getOrder() {
return _order;
}
@Override
public void setOrder(int order) {
_order = order;
}
@Override
protected void additionalAuthenticationChecks(final UserDetails userDetails, final UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
if (authentication.getCredentials() == null) {
......@@ -173,4 +183,5 @@ public class AliasTokenAuthenticationProvider extends AbstractUserDetailsAuthent
private final AliasTokenService _aliasTokenService;
private final XdatUserAuthService _userAuthService;
private int _order = -1;
}
......@@ -2,6 +2,7 @@ package org.nrg.xnat.security.config;
import org.apache.commons.lang3.StringUtils;
import org.nrg.framework.utilities.BasicXnatResourceLocator;
import org.nrg.xnat.security.provider.XnatAuthenticationProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
......@@ -13,29 +14,33 @@ import java.util.*;
public class AuthenticationProviderAggregator extends ArrayList<AuthenticationProvider> {
public AuthenticationProviderAggregator(List<AuthenticationProvider> standaloneProviders, Map<String, AuthenticationProviderConfigurator> configurators) {
ArrayList<String> providerArray = new ArrayList<>();
String dbName = "Database";
String dbId = "localdb";
String dbType = "db";
providerArray.add(dbType);
HashMap<String, HashMap<String, String>> providerMap = new HashMap<>();
providerMap.put(dbType, new HashMap<String, String>());
providerMap.get(dbType).put("name", dbName);
providerMap.get(dbType).put("id", dbId);
providerMap.get(dbType).put("type", dbType);
ArrayList<HashMap<String, String>> providerList = new ArrayList<>();
// Populate map of properties
try {
String filenameEnd = "-provider.properties";
final List<Resource> resources = BasicXnatResourceLocator.getResources("classpath*:META-INF/xnat/auth/**/*" + filenameEnd);
for (final Resource resource : resources) {
String filename = resource.getFilename();
String id = filename.substring(0, (filename.length() - filenameEnd.length()));
providerMap.put(id, new HashMap<String, String>());
providerArray.add(id);
final Properties provider = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<Object, Object> providerProperty : provider.entrySet()) {
providerMap.get(id).put(providerProperty.getKey().toString(), providerProperty.getValue().toString());
if(resources==null || resources.isEmpty()){
String dbName = "Database";
String dbId = "localdb";
String dbType = "db";
HashMap<String, String> dbProv = new HashMap<String, String>();
dbProv.put("name", dbName);
dbProv.put("id", dbId);
dbProv.put("type", dbType);
providerList.add(dbProv);
}
else {
for (final Resource resource : resources) {
String filename = resource.getFilename();
String id = filename.substring(0, (filename.length() - filenameEnd.length()));
HashMap<String, String> newProv = new HashMap<String, String>();
final Properties provider = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<Object, Object> providerProperty : provider.entrySet()) {
newProv.put(providerProperty.getKey().toString(), providerProperty.getValue().toString());
}
providerList.add(newProv);
}
}
} catch (Exception e) {
......@@ -43,10 +48,10 @@ public class AuthenticationProviderAggregator extends ArrayList<AuthenticationPr
}
// Create providers
for (String prov : providerArray) {
String name = providerMap.get(prov).get("name");
String id = providerMap.get(prov).get("id");
String type = providerMap.get(prov).get("type");
for (HashMap<String, String> prov : providerList) {
String name = prov.get("name");
String id = prov.get("id");
String type = prov.get("type");
assert !StringUtils.isBlank(name) : "You must provide a name for all authentication provider configurations";
assert !StringUtils.isBlank(id) : "You must provide an ID for all authentication provider configurations";
......@@ -54,13 +59,37 @@ public class AuthenticationProviderAggregator extends ArrayList<AuthenticationPr
if (configurators.containsKey(type)) {
AuthenticationProviderConfigurator configurator = configurators.get(type);
addAll(configurator.getAuthenticationProviders(id, name, providerMap.get(prov)));
addAll(configurator.getAuthenticationProviders(id, name, prov));
}
}
if (standaloneProviders != null) {
addAll(standaloneProviders);
}
Collections.sort(this, new Comparator<AuthenticationProvider>(){
public int compare(AuthenticationProvider o1, AuthenticationProvider o2){
if(XnatAuthenticationProvider.class.isAssignableFrom(o1.getClass())){
if(XnatAuthenticationProvider.class.isAssignableFrom(o2.getClass())){
if(((XnatAuthenticationProvider)o1).getOrder() == ((XnatAuthenticationProvider)o2).getOrder())
return 0;
return ((XnatAuthenticationProvider)o1).getOrder() < ((XnatAuthenticationProvider)o2).getOrder() ? -1 : 1;
}
else{
return 1;
}
}
else{
if(XnatAuthenticationProvider.class.isAssignableFrom(o2.getClass())){
return -1;
}
else{
return 0;
}
}
}
});
}
private static final Logger _log = LoggerFactory.getLogger(AuthenticationProviderAggregator.class);
......
......@@ -11,6 +11,7 @@
package org.nrg.xnat.security.config;
import org.nrg.xdat.preferences.SiteConfigPreferences;
import org.nrg.xnat.security.provider.XnatAuthenticationProvider;
import org.nrg.xnat.security.provider.XnatDatabaseAuthenticationProvider;
import org.nrg.xnat.security.userdetailsservices.XnatDatabaseUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -51,7 +52,15 @@ public class DatabaseAuthenticationProviderConfigurator extends AbstractAuthenti
@Override
public List<AuthenticationProvider> getAuthenticationProviders(String id, String name, Map<String, String> properties) {
return getAuthenticationProviders(id, name);
List<AuthenticationProvider> provs = getAuthenticationProviders(id, name);
for(AuthenticationProvider prov : provs){
if(XnatAuthenticationProvider.class.isAssignableFrom(prov.getClass())){
if (properties.get("order") != null) {
((XnatAuthenticationProvider)prov).setOrder(Integer.parseInt(properties.get("order")));
}
}
}
return provs;
}
private final XnatDatabaseUserDetailsService _userDetailsService;
......
......@@ -49,6 +49,9 @@ public class LdapAuthenticationProviderConfigurator extends AbstractAuthenticati
ldapAuthProvider.setUserDetailsContextMapper(new XnatLdapUserDetailsMapper(id, properties, _userAuthService, _preferences));
ldapAuthProvider.setName(name);
ldapAuthProvider.setProviderId(id);
if (properties.get("order") != null) {
ldapAuthProvider.setOrder(Integer.parseInt(properties.get("order")));
}
return Arrays.asList(new AuthenticationProvider[] { ldapAuthProvider });
} catch (Exception exception) {
_log.error("Something went wrong when configuring the LDAP authentication provider", exception);
......
......@@ -40,4 +40,13 @@ public interface XnatAuthenticationProvider extends AuthenticationProvider {
* @return The authentication method for this provider.
*/
String getAuthMethod();
/**
* Indicates the order associated with this provider. This is used to determine the order in which the providers
* show up in the login dropdown and the order in which they are checked when a login is attempted.
* @return The order for this provider.
*/
int getOrder();
void setOrder(int order);
}
......@@ -74,6 +74,16 @@ public class XnatDatabaseAuthenticationProvider extends DaoAuthenticationProvide
return XdatUserAuthService.LOCALDB;
}
@Override
public int getOrder() {
return _order;
}
@Override
public void setOrder(int order) {
_order = order;
}
@Override
protected void additionalAuthenticationChecks(final UserDetails userDetails, final UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
if (!UserI.class.isAssignableFrom(userDetails.getClass())) {
......@@ -143,4 +153,5 @@ public class XnatDatabaseAuthenticationProvider extends DaoAuthenticationProvide
}
private final boolean _requireEmailVerification;
private int _order = -1;
}
......@@ -94,6 +94,16 @@ public class XnatLdapAuthenticationProvider extends LdapAuthenticationProvider i
return XdatUserAuthService.LDAP;
}
@Override
public int getOrder() {
return _order;
}
@Override
public void setOrder(int order) {
_order = order;
}
/**
* Indicates whether the provider should be visible to and selectable by users. <b>false</b> usually indicates an
* internal authentication provider, e.g. token authentication.
......@@ -109,4 +119,5 @@ public class XnatLdapAuthenticationProvider extends LdapAuthenticationProvider i
private String _displayName = "";
private String _providerId = "";
private int _order = -1;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment