diff --git a/config/auth_conf.xml.sample b/config/auth_conf.xml.sample index 639c6b633b3..37994a6b67b 100644 --- a/config/auth_conf.xml.sample +++ b/config/auth_conf.xml.sample @@ -1,5 +1,35 @@ + + + + + + + + + + localdb diff --git a/lib/galaxy/auth/__init__.py b/lib/galaxy/auth/__init__.py index 7dbb843b37f..1a07dfe4763 100644 --- a/lib/galaxy/auth/__init__.py +++ b/lib/galaxy/auth/__init__.py @@ -18,31 +18,6 @@ from galaxy.util import plugin_config import logging log = logging.getLogger(__name__) -# -# -# ldap -# '[login]'.endswith('@students.latrobe.edu.au') -# -# True -# ldap://STUDENTS.ltu.edu.au -# [(&(objectClass=user)(mail={login})) -# dc=STUDENTS,dc=ltu,dc=edu,dc=au -# -# jsmith -# mysecret -# sAMAccountName,mail] -# {sAMAccountName}@STUDENTS.ltu.edu.au -# {password} -# {sAMAccountName} -# {mail} -# -# -# -# ... -# - class AuthManager(object): @@ -85,14 +60,14 @@ class AuthManager(object): authenticators.append(authenticator) self.authenticators = authenticators - def check_registration_allowed(self, login, password): + def check_registration_allowed(self, email, username, password): """Checks if the provided email/username is allowed to register.""" message = '' status = 'done' - for provider, options in self.active_authenticators(login, password): + for provider, options in self.active_authenticators(email, username, password): allow_reg = _get_tri_state(options, 'allow-register', True) if allow_reg is None: # i.e. challenge - auth_result, msg = provider.authenticate(login, password, options) + auth_result, msg = provider.authenticate(email, username, password, options) if auth_result is True: break if auth_result is None: @@ -112,11 +87,17 @@ class AuthManager(object): Checks the username/email & password using auth providers in order. If a match is found, returns the 'auto-register' option for that provider. """ - for provider, options in self.active_authenticators(login, password): + if '@' in login: + email = login + username = None + else: + email = None + username = login + for provider, options in self.active_authenticators(email, username, password): if provider is None: log.debug( "Unable to find module: %s" % options ) else: - auth_result, auto_email, auto_username = provider.authenticate(login, password, options) + auth_result, auto_email, auto_username = provider.authenticate(email, username, password, options) auto_email = str(auto_email).lower() auto_username = str(auto_username).lower() if auth_result is True: @@ -139,7 +120,7 @@ class AuthManager(object): def check_password(self, user, password): """Checks the username/email and password using auth providers.""" - for provider, options in self.active_authenticators(user, password): + for provider, options in self.active_authenticators(user.email, user.username, password): if provider is None: log.debug( "Unable to find module: %s" % options ) else: @@ -154,7 +135,7 @@ class AuthManager(object): """Checks that auth provider allows password changes and current_password matches. """ - for provider, options in self.active_authenticators(user, current_password): + for provider, options in self.active_authenticators(user.email, user.username, current_password): if provider is None: log.debug( "Unable to find module: %s" % options ) else: @@ -168,7 +149,7 @@ class AuthManager(object): return (False, 'Password change not supported') return (False, 'Invalid current password') - def active_authenticators(self, login, password): + def active_authenticators(self, email, username, password): """Yields AuthProvider instances for the provided configfile that match the filters. """ @@ -176,7 +157,7 @@ class AuthManager(object): for authenticator in self.authenticators: filter_template = authenticator.filter_template if filter_template: - filter_str = filter_template.format(login=login, password=password) + filter_str = filter_template.format(email=email, username=username, password=password) passed_filter = eval(filter_str, {"__builtins__": None}, {'str': str}) if not passed_filter: continue # skip to next diff --git a/lib/galaxy/auth/providers/__init__.py b/lib/galaxy/auth/providers/__init__.py index fd200c01db4..054bb45fd49 100644 --- a/lib/galaxy/auth/providers/__init__.py +++ b/lib/galaxy/auth/providers/__init__.py @@ -16,15 +16,17 @@ class AuthProvider(object): """ Short string providing labelling this plugin """ @abc.abstractmethod - def authenticate(self, login, password, options): + def authenticate(self, email, username, password, options): """ - Check that the username and password are correct. + Check that the user credentials are correct. NOTE: Used within auto-registration to check it is ok to register this user. - :param login: the user's email address or username - :type login: str + :param email: the user's email address + :type email: str + :param username: the user's username + :type username: str :param password: the plain text password they typed :type password: str :param options: options provided in auth_config_file @@ -44,8 +46,8 @@ class AuthProvider(object): NOTE: used on normal login to check authentication and update user details if required. - :param username: the user's email address or username - :type username: str + :param user: the user to authenticate + :type user: galaxy.model.User :param password: the plain text password they typed :type password: str :param options: options provided in auth_config_file diff --git a/lib/galaxy/auth/providers/alwaysreject.py b/lib/galaxy/auth/providers/alwaysreject.py index a2c27b6293a..13fe895c7a3 100644 --- a/lib/galaxy/auth/providers/alwaysreject.py +++ b/lib/galaxy/auth/providers/alwaysreject.py @@ -16,7 +16,7 @@ class AlwaysReject(AuthProvider): """ plugin_type = 'alwaysreject' - def authenticate(self, login, password, options): + def authenticate(self, email, username, password, options): """ See abstract method documentation. """ diff --git a/lib/galaxy/auth/providers/ldap_ad.py b/lib/galaxy/auth/providers/ldap_ad.py index ef2dddb83b8..1a631abea2b 100644 --- a/lib/galaxy/auth/providers/ldap_ad.py +++ b/lib/galaxy/auth/providers/ldap_ad.py @@ -30,26 +30,35 @@ class LDAP(AuthProvider): """ plugin_type = 'ldap' - def authenticate(self, login, password, options): + def authenticate(self, email, username, password, options): """ See abstract method documentation. """ - log.debug("Login: %s" % login) - log.debug("Options: %s" % options) + log.debug("LDAP authenticate: email is %s" % email) + log.debug("LDAP authenticate: username is %s" % username) + log.debug("LDAP authenticate: options are %s" % options) failure_mode = False # reject but continue if options.get('continue-on-failure', 'False') == 'False': failure_mode = None # reject and do not continue + if _get_bool(options, 'login-use-username', False): + if username is None: + log.debug('LDAP authenticate: username must be used to login, cannot be None') + return (failure_mode, '', '') + else: + if email is None: + log.debug('LDAP authenticate: email must be used to login, cannot be None') + return (failure_mode, '', '') + try: import ldap except: - log.debug( - "Login: %s, LDAP: False (could not load ldap module)" % (login)) - return (failure_mode, '') + log.debug('LDAP authenticate: could not load ldap module') + return (failure_mode, '', '') # do LDAP search (if required) - params = {'login': login, 'password': password} + params = {'email': email, 'username': username, 'password': password} if 'search-fields' in options: try: # setup connection @@ -74,8 +83,8 @@ class LDAP(AuthProvider): # parse results _, suser = l.result(result, 60) dn, attrs = suser[0] - log.debug(("LDAP dn: %s" % dn)) - log.debug(("LDAP Search attributes: %s" % attrs)) + log.debug(("LDAP authenticate: dn is %s" % dn)) + log.debug(("LDAP authenticate: search attributes are %s" % attrs)) if hasattr(attrs, 'has_key'): for attr in attributes: if attr in attrs: @@ -84,7 +93,7 @@ class LDAP(AuthProvider): params[attr] = "" params['dn'] = dn except Exception: - log.exception('LDAP Search Exception for login: %s' % login) + log.exception('LDAP authenticate: search exception') return (failure_mode, '', '') # end search @@ -97,10 +106,10 @@ class LDAP(AuthProvider): l.simple_bind_s(_get_subs( options, 'bind-user', params), _get_subs(options, 'bind-password', params)) except Exception: - log.exception('LDAP Authentication Exception for login %s' % login) + log.exception('LDAP authenticate: bind exception') return (failure_mode, '', '') - log.debug("Login: %s, LDAP: True" % (login)) + log.debug('LDAP authentication successful') return (True, _get_subs(options, 'auto-register-email', params), _get_subs(options, 'auto-register-username', params)) @@ -109,11 +118,7 @@ class LDAP(AuthProvider): """ See abstract method documentation. """ - - if _get_bool(options, 'login-use-username', False): - return self.authenticate(user.username, password, options)[0] - else: - return self.authenticate(user.email, password, options)[0] + return self.authenticate(user.email, user.username, password, options)[0] class ActiveDirectory(LDAP): diff --git a/lib/galaxy/auth/providers/localdb.py b/lib/galaxy/auth/providers/localdb.py index 718889acad0..71508a01e4e 100644 --- a/lib/galaxy/auth/providers/localdb.py +++ b/lib/galaxy/auth/providers/localdb.py @@ -13,7 +13,7 @@ class LocalDB(AuthProvider): """Authenticate users against the local Galaxy database (as per usual).""" plugin_type = 'localdb' - def authenticate(self, login, password, options): + def authenticate(self, email, username, password, options): """ See abstract method documentation. """ diff --git a/lib/galaxy/webapps/galaxy/controllers/user.py b/lib/galaxy/webapps/galaxy/controllers/user.py index bea04c02c2e..efc6b518d61 100644 --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -678,7 +678,7 @@ class User( BaseUIController, UsesFormDefinitionsMixin, CreatesUsersMixin, Creat status = 'error' else: # check user is allowed to register - message, status = trans.app.auth_manager.check_registration_allowed(email, password) + message, status = trans.app.auth_manager.check_registration_allowed(email, username, password) if message == '': if not refresh_frames: if trans.webapp.name == 'galaxy':