class FASWhoPlugin(object): def __init__(self, url, session_cookie='tg-visit'): self.url = url self.fas = FasProxyClient(url) self.session_cookie = session_cookie self._session_cache = {} self._metadata_plugins = [] for entry in pkg_resources.iter_entry_points( 'fas.repoze.who.metadata_plugins'): self._metadata_plugins.append(entry.load()) def keep_alive(self, session_id): log.info(_('Keep alive cache miss')) try: linfo = self.fas.get_user_info({'session_id': session_id}) except AuthError, e: log.warning(e) return None try: del linfo[1]['password'] except KeyError: # Just make sure the password isn't in the info we return pass return linfo
class FASWhoPlugin(object): def __init__(self, url, insecure=False, session_cookie='tg-visit', ssl_cookie=True, httponly=True): self.url = url self.insecure = insecure self.fas = FasProxyClient(url, insecure=insecure) self.session_cookie = session_cookie self.ssl_cookie = ssl_cookie self.httponly = httponly self._session_cache = {} self._metadata_plugins = [] for entry in pkg_resources.iter_entry_points( 'fas.repoze.who.metadata_plugins'): self._metadata_plugins.append(entry.load()) def _retrieve_user_info(self, environ, auth_params=None): ''' Retrieve information from fas and cache the results. We need to retrieve the user fresh every time because we need to know that the password hasn't changed or the session_id hasn't been invalidated by the user logging out. ''' if not auth_params: return None user_data = self.fas.get_user_info(auth_params) if not user_data: self.forget(environ, None) return None if isinstance(user_data, tuple): user_data = list(user_data) # Set session_id in here so it can be found by other plugins user_data[1]['session_id'] = user_data[0] # we don't define permissions since we don't have any peruser data # though other services may wish to add another metadata plugin to do # so if not 'permissions' in user_data[1]: user_data[1]['permissions'] = set() # we keep the approved_memberships list because there is also an # unapproved_membership field. The groups field is for repoze.who # group checking and may include other types of groups besides # memberships in the future (such as special fedora community groups) groups = set() for g in user_data[1]['approved_memberships']: groups.add(g['name']) user_data[1]['groups'] = groups # If we have information on the user, cache it for later fas_cache.set_value(user_data[1]['username'], user_data, expiretime=FAS_CACHE_TIMEOUT) return user_data def identify(self, environ): '''Extract information to identify a user Retrieve either a username and password or a session_id that can be passed on to FAS to authenticate the user. ''' log.info('in identify()') # friendlyform compat if not 'repoze.who.logins' in environ: environ['repoze.who.logins'] = 0 req = webob.Request(environ, charset='utf-8') cookie = req.cookies.get(self.session_cookie) # This is compatible with TG1 and it gives us a way to authenticate # a user without making two requests query = req.GET form = Munch(req.POST) form.update(query) if form.get('login', None) == 'Login' and \ 'user_name' in form and \ 'password' in form: identity = { 'login': form['user_name'], 'password': form['password'] } keys = ('login', 'password', 'user_name') for k in keys: if k in req.GET: del (req.GET[k]) if k in req.POST: del (req.POST[k]) return identity if cookie is None: return None log.info('Request identify for cookie %(cookie)s' % {'cookie': to_bytes(cookie)}) try: user_data = self._retrieve_user_info( environ, auth_params={'session_id': cookie}) except Exception as e: # pylint:disable-msg=W0703 # For any exceptions, returning None means we failed to identify log.warning(e) return None if not user_data: return None # Preauthenticated identity = { 'repoze.who.userid': user_data[1]['username'], 'login': user_data[1]['username'], 'password': user_data[1]['password'] } return identity def remember(self, environ, identity): log.info('In remember()') result = [] user_data = fas_cache.get_value(identity['login']) try: session_id = user_data[0] except Exception: return None set_cookie = ['%s=%s; Path=/;' % (self.session_cookie, session_id)] if self.ssl_cookie: set_cookie.append('Secure') if self.httponly: set_cookie.append('HttpOnly') set_cookie = '; '.join(set_cookie) result.append(('Set-Cookie', set_cookie)) return result def forget(self, environ, identity): log.info('In forget()') # return a expires Set-Cookie header user_data = fas_cache.get_value(identity['login']) try: session_id = user_data[0] except Exception: return None log.info('Forgetting login data for cookie %(s_id)s' % {'s_id': to_bytes(session_id)}) self.fas.logout(session_id) result = [] fas_cache.remove_value(key=identity['login']) expired = '%s=\'\'; Path=/; Expires=Sun, 10-May-1971 11:59:00 GMT'\ % self.session_cookie result.append(('Set-Cookie', expired)) return result # IAuthenticatorPlugin def authenticate(self, environ, identity): log.info('In authenticate()') def set_error(msg): log.info(msg) err = 1 environ['FAS_AUTH_ERROR'] = err # HTTPForbidden ? err_app = HTTPFound(err_goto + '?' + 'came_from=' + quote_plus(came_from)) environ['repoze.who.application'] = err_app err_goto = '/login' default_came_from = '/' if 'SCRIPT_NAME' in environ: sn = environ['SCRIPT_NAME'] err_goto = sn + err_goto default_came_from = sn + default_came_from query = parse_dict_querystring(environ) form = parse_formvars(environ) form.update(query) came_from = form.get('came_from', default_came_from) try: auth_params = { 'username': identity['login'], 'password': identity['password'] } except KeyError: try: auth_params = {'session_id': identity['session_id']} except: # On error we return None which means that auth failed set_error('Parameters for authenticating not found') return None try: user_data = self._retrieve_user_info(environ, auth_params) except AuthError as e: set_error('Authentication failed: %s' % exception_to_bytes(e)) log.warning(e) return None except Exception as e: set_error('Unknown auth failure: %s' % exception_to_bytes(e)) return None if user_data: try: del user_data[1]['password'] environ['CSRF_AUTH_SESSION_ID'] = user_data[0] return user_data[1]['username'] except ValueError: set_error('user information from fas not in expected format!') return None except Exception: pass set_error('An unknown error happened when trying to log you in.' ' Please try again.') return None def add_metadata(self, environ, identity): log.info('In add_metadata') if identity.get('error'): log.info('Error exists in session, no need to set metadata') return 'error' plugin_user_info = {} for plugin in self._metadata_plugins: plugin(plugin_user_info) identity.update(plugin_user_info) del plugin_user_info user = identity.get('repoze.who.userid') (session_id, user_info) = fas_cache.get_value(key=user, expiretime=FAS_CACHE_TIMEOUT) #### FIXME: Deprecate this line!!! # If we make a new version of fas.who middleware, get rid of saving # user information directly into identity. Instead, save it into # user, as is done below identity.update(user_info) identity['userdata'] = user_info identity['user'] = Munch() identity['user'].created = user_info['creation'] identity['user'].display_name = user_info['human_name'] identity['user'].email_address = user_info['email'] identity['user'].groups = user_info['groups'] identity['user'].password = None identity['user'].permissions = user_info['permissions'] identity['user'].user_id = user_info['id'] identity['user'].user_name = user_info['username'] identity['groups'] = user_info['groups'] identity['permissions'] = user_info['permissions'] if 'repoze.what.credentials' not in environ: environ['repoze.what.credentials'] = {} environ['repoze.what.credentials']['groups'] = user_info['groups'] permissions = user_info['permissions'] environ['repoze.what.credentials']['permissions'] = permissions # Adding the userid: userid = identity['repoze.who.userid'] environ['repoze.what.credentials']['repoze.what.userid'] = userid def __repr__(self): return '<%s %s>' % (self.__class__.__name__, id(self))
class FASWhoPlugin(object): def __init__(self, url, insecure=False, session_cookie='tg-visit', ssl_cookie=True, httponly=True): self.url = url self.insecure = insecure self.fas = FasProxyClient(url, insecure=insecure) self.session_cookie = session_cookie self.ssl_cookie = ssl_cookie self.httponly = httponly self._session_cache = {} self._metadata_plugins = [] for entry in pkg_resources.iter_entry_points( 'fas.repoze.who.metadata_plugins'): self._metadata_plugins.append(entry.load()) def _retrieve_user_info(self, environ, auth_params=None): ''' Retrieve information from fas and cache the results. We need to retrieve the user fresh every time because we need to know that the password hasn't changed or the session_id hasn't been invalidated by the user logging out. ''' if not auth_params: return None user_data = self.fas.get_user_info(auth_params) if not user_data: self.forget(environ, None) return None if isinstance(user_data, tuple): user_data = list(user_data) # Set session_id in here so it can be found by other plugins user_data[1]['session_id'] = user_data[0] # we don't define permissions since we don't have any peruser data # though other services may wish to add another metadata plugin to do # so if not 'permissions' in user_data[1]: user_data[1]['permissions'] = set() # we keep the approved_memberships list because there is also an # unapproved_membership field. The groups field is for repoze.who # group checking and may include other types of groups besides # memberships in the future (such as special fedora community groups) groups = set() for g in user_data[1]['approved_memberships']: groups.add(g['name']) user_data[1]['groups'] = groups # If we have information on the user, cache it for later fas_cache.set_value(user_data[1]['username'], user_data, expiretime=FAS_CACHE_TIMEOUT) return user_data def identify(self, environ): '''Extract information to identify a user Retrieve either a username and password or a session_id that can be passed on to FAS to authenticate the user. ''' log.info('in identify()') # friendlyform compat if not 'repoze.who.logins' in environ: environ['repoze.who.logins'] = 0 req = webob.Request(environ, charset='utf-8') cookie = req.cookies.get(self.session_cookie) # This is compatible with TG1 and it gives us a way to authenticate # a user without making two requests query = req.GET form = Munch(req.POST) form.update(query) if form.get('login', None) == 'Login' and \ 'user_name' in form and \ 'password' in form: identity = { 'login': form['user_name'], 'password': form['password'] } keys = ('login', 'password', 'user_name') for k in keys: if k in req.GET: del(req.GET[k]) if k in req.POST: del(req.POST[k]) return identity if cookie is None: return None log.info('Request identify for cookie %(cookie)s' % {'cookie': to_bytes(cookie)}) try: user_data = self._retrieve_user_info( environ, auth_params={'session_id': cookie}) except Exception as e: # pylint:disable-msg=W0703 # For any exceptions, returning None means we failed to identify log.warning(e) return None if not user_data: return None # Preauthenticated identity = {'repoze.who.userid': user_data[1]['username'], 'login': user_data[1]['username'], 'password': user_data[1]['password']} return identity def remember(self, environ, identity): log.info('In remember()') result = [] user_data = fas_cache.get_value(identity['login']) try: session_id = user_data[0] except Exception: return None set_cookie = ['%s=%s; Path=/;' % (self.session_cookie, session_id)] if self.ssl_cookie: set_cookie.append('Secure') if self.httponly: set_cookie.append('HttpOnly') set_cookie = '; '.join(set_cookie) result.append(('Set-Cookie', set_cookie)) return result def forget(self, environ, identity): log.info('In forget()') # return a expires Set-Cookie header user_data = fas_cache.get_value(identity['login']) try: session_id = user_data[0] except Exception: return None log.info('Forgetting login data for cookie %(s_id)s' % {'s_id': to_bytes(session_id)}) self.fas.logout(session_id) result = [] fas_cache.remove_value(key=identity['login']) expired = '%s=\'\'; Path=/; Expires=Sun, 10-May-1971 11:59:00 GMT'\ % self.session_cookie result.append(('Set-Cookie', expired)) return result # IAuthenticatorPlugin def authenticate(self, environ, identity): log.info('In authenticate()') def set_error(msg): log.info(msg) err = 1 environ['FAS_AUTH_ERROR'] = err # HTTPForbidden ? err_app = HTTPFound(err_goto + '?' + 'came_from=' + quote_plus(came_from)) environ['repoze.who.application'] = err_app err_goto = '/login' default_came_from = '/' if 'SCRIPT_NAME' in environ: sn = environ['SCRIPT_NAME'] err_goto = sn + err_goto default_came_from = sn + default_came_from query = parse_dict_querystring(environ) form = parse_formvars(environ) form.update(query) came_from = form.get('came_from', default_came_from) try: auth_params = {'username': identity['login'], 'password': identity['password']} except KeyError: try: auth_params = {'session_id': identity['session_id']} except: # On error we return None which means that auth failed set_error('Parameters for authenticating not found') return None try: user_data = self._retrieve_user_info(environ, auth_params) except AuthError as e: set_error('Authentication failed: %s' % exception_to_bytes(e)) log.warning(e) return None except Exception as e: set_error('Unknown auth failure: %s' % exception_to_bytes(e)) return None if user_data: try: del user_data[1]['password'] environ['CSRF_AUTH_SESSION_ID'] = user_data[0] return user_data[1]['username'] except ValueError: set_error('user information from fas not in expected format!') return None except Exception: pass set_error('An unknown error happened when trying to log you in.' ' Please try again.') return None def add_metadata(self, environ, identity): log.info('In add_metadata') if identity.get('error'): log.info('Error exists in session, no need to set metadata') return 'error' plugin_user_info = {} for plugin in self._metadata_plugins: plugin(plugin_user_info) identity.update(plugin_user_info) del plugin_user_info user = identity.get('repoze.who.userid') (session_id, user_info) = fas_cache.get_value( key=user, expiretime=FAS_CACHE_TIMEOUT) #### FIXME: Deprecate this line!!! # If we make a new version of fas.who middleware, get rid of saving # user information directly into identity. Instead, save it into # user, as is done below identity.update(user_info) identity['userdata'] = user_info identity['user'] = Munch() identity['user'].created = user_info['creation'] identity['user'].display_name = user_info['human_name'] identity['user'].email_address = user_info['email'] identity['user'].groups = user_info['groups'] identity['user'].password = None identity['user'].permissions = user_info['permissions'] identity['user'].user_id = user_info['id'] identity['user'].user_name = user_info['username'] identity['groups'] = user_info['groups'] identity['permissions'] = user_info['permissions'] if 'repoze.what.credentials' not in environ: environ['repoze.what.credentials'] = {} environ['repoze.what.credentials']['groups'] = user_info['groups'] permissions = user_info['permissions'] environ['repoze.what.credentials']['permissions'] = permissions # Adding the userid: userid = identity['repoze.who.userid'] environ['repoze.what.credentials']['repoze.what.userid'] = userid def __repr__(self): return '<%s %s>' % (self.__class__.__name__, id(self))
class FASWhoPlugin(object): def __init__(self, url, insecure=False, session_cookie='tg-visit', ssl_cookie=True, httponly=True): self.url = url self.insecure = insecure self.fas = FasProxyClient(url, insecure=insecure) self.session_cookie = session_cookie self.ssl_cookie = ssl_cookie self.httponly = httponly self._session_cache = {} self._metadata_plugins = [] for entry in pkg_resources.iter_entry_points( 'fas.repoze.who.metadata_plugins'): self._metadata_plugins.append(entry.load()) def _retrieve_user_info(self, environ, auth_params=None): ''' Retrieve information from fas and cache the results. We need to retrieve the user fresh every time because we need to know that the password hasn't changed or the session_id hasn't been invalidated by the user logging out. ''' if not auth_params: return None user_data = self.fas.get_user_info(auth_params) if not user_data: self.forget(environ, None) return None if isinstance(user_data, tuple): user_data = list(user_data) # Set session_id in here so it can be found by other plugins user_data[1]['session_id'] = user_data[0] # we don't define permissions since we don't have any peruser data # though other services may wish to add another metadata plugin to do # so if not user_data[1].has_key('permissions'): user_data[1]['permissions'] = set() # we keep the approved_memberships list because there is also an # unapproved_membership field. The groups field is for repoze.who # group checking and may include other types of groups besides # memberships in the future (such as special fedora community groups) groups = set() for g in user_data[1]['approved_memberships']: groups.add(g['name']) user_data[1]['groups'] = groups # If we have information on the user, cache it for later fas_cache.set_value(user_data[1]['username'], user_data, expiretime=FAS_CACHE_TIMEOUT) return user_data def identify(self, environ): '''Extract information to identify a user Retrieve either a username and password or a session_id that can be passed on to FAS to authenticate the user. ''' log.info(b_('in identify()')) # friendlyform compat if not 'repoze.who.logins' in environ: environ['repoze.who.logins'] = 0 req = webob.Request(environ, charset='utf-8') cookie = req.cookies.get(self.session_cookie) # This is compatible with TG1 and it gives us a way to authenticate # a user without making two requests query = req.GET form = Bunch(req.POST) form.update(query) if form.get('login', None) == 'Login' and \ 'user_name' in form and \ 'password' in form: identity = {'login': form['user_name'], 'password': form['password']} keys = ('login', 'password', 'user_name') for k in keys: if k in req.GET: del(req.GET[k]) if k in req.POST: del(req.POST[k]) return identity if cookie is None: return None log.info(b_('Request identify for cookie %(cookie)s') % {'cookie': to_bytes(cookie)}) try: user_data = self._retrieve_user_info(environ, auth_params={'session_id': cookie}) except Exception, e: # pylint:disable-msg=W0703 # For any exceptions, returning None means we failed to identify log.warning(e) return None if not user_data: return None # Preauthenticated identity = {'repoze.who.userid': user_data[1]['username'], 'login': user_data[1]['username'], 'password': user_data[1]['password']} return identity
class FASWhoPlugin(object): def __init__(self, url, insecure=False, session_cookie='tg-visit', ssl_cookie=True, httponly=True): self.url = url self.insecure = insecure self.fas = FasProxyClient(url, insecure=insecure) self.session_cookie = session_cookie self.ssl_cookie = ssl_cookie self.httponly = httponly self._session_cache = {} self._metadata_plugins = [] for entry in pkg_resources.iter_entry_points( 'fas.repoze.who.metadata_plugins'): self._metadata_plugins.append(entry.load()) def _retrieve_user_info(self, environ, auth_params=None): ''' Retrieve information from fas and cache the results. We need to retrieve the user fresh every time because we need to know that the password hasn't changed or the session_id hasn't been invalidated by the user logging out. ''' if not auth_params: return None user_data = self.fas.get_user_info(auth_params) if not user_data: self.forget(environ, None) return None if isinstance(user_data, tuple): user_data = list(user_data) # Set session_id in here so it can be found by other plugins user_data[1]['session_id'] = user_data[0] # we don't define permissions since we don't have any peruser data # though other services may wish to add another metadata plugin to do # so if not user_data[1].has_key('permissions'): user_data[1]['permissions'] = set() # we keep the approved_memberships list because there is also an # unapproved_membership field. The groups field is for repoze.who # group checking and may include other types of groups besides # memberships in the future (such as special fedora community groups) groups = set() for g in user_data[1]['approved_memberships']: groups.add(g['name']) user_data[1]['groups'] = groups # If we have information on the user, cache it for later fas_cache.set_value(user_data[1]['username'], user_data, expiretime=FAS_CACHE_TIMEOUT) return user_data def identify(self, environ): '''Extract information to identify a user Retrieve either a username and password or a session_id that can be passed on to FAS to authenticate the user. ''' log.info('in identify()') # friendlyform compat if not 'repoze.who.logins' in environ: environ['repoze.who.logins'] = 0 req = webob.Request(environ, charset='utf-8') cookie = req.cookies.get(self.session_cookie) # This is compatible with TG1 and it gives us a way to authenticate # a user without making two requests query = req.GET form = Bunch(req.POST) form.update(query) if form.get('login', None) == 'Login' and \ 'user_name' in form and \ 'password' in form: identity = { 'login': form['user_name'], 'password': form['password'] } keys = ('login', 'password', 'user_name') for k in keys: if k in req.GET: del (req.GET[k]) if k in req.POST: del (req.POST[k]) return identity if cookie is None: return None log.info('Request identify for cookie %(cookie)s' % {'cookie': to_bytes(cookie)}) try: user_data = self._retrieve_user_info( environ, auth_params={'session_id': cookie}) except Exception, e: # pylint:disable-msg=W0703 # For any exceptions, returning None means we failed to identify log.warning(e) return None if not user_data: return None # Preauthenticated identity = { 'repoze.who.userid': user_data[1]['username'], 'login': user_data[1]['username'], 'password': user_data[1]['password'] } return identity