def fetch_user_nickname(self, username, password=None, req=None): """Given a username and a password, returns the right nickname belonging to that user (username could be an email). """ if self.nickname_attribute_name: data = self.__extract_attribute(req) nickname = data.get(self.nickname_attribute_name) if nickname: if isinstance(nickname, str): return nickname.strip().lower() else: raise InvenioWebAccessExternalAuthError("The nickname provided in the assertion is invalid: %s" % (repr(nickname))) return None
def fetch_user_groups_membership(self, username, password=None, req=None): """Given a username and a password, returns a dictionary of groups and their description to which the user is subscribed. Raise InvenioWebAccessExternalAuthError in case of troubles. """ if self.groups_attribute_name: data = self.__extract_attribute(req) groups = data.get(self.groups_attribute_name) if groups: if isinstance(groups, str): groups = [group.strip() for group in groups.split(self.groups_separator)] return dict(zip(groups, groups)) else: raise InvenioWebAccessExternalAuthError("The groups provided in the assertion are invalid: %s" % (repr(groups))) return {}
def __extract_attribute(self, req): """ Load from the request the given assertion, extract all the attribute to properly login the user, and verify that the data are actually both well formed and signed correctly. """ from invenio.webinterface_handler import wash_urlargd args = wash_urlargd( req.form, { 'assertion': (str, ''), 'robot': (str, ''), 'digest': (str, ''), 'login_method': (str, '') }) assertion = args['assertion'] digest = args['digest'] robot = args['robot'] login_method = args['login_method'] shared_key = load_robot_keys().get(login_method, {}).get(robot) if shared_key is None: raise InvenioWebAccessExternalAuthError( "A key does not exist for robot: %s, login_method: %s" % (robot, login_method)) if not self.verify(shared_key, assertion, digest): raise InvenioWebAccessExternalAuthError( "The provided assertion does not validate against the digest %s for robot %s" % (repr(digest), repr(robot))) if self.use_zlib: try: ## Workaround to Perl implementation that does not add ## any padding to the base64 encoding. needed_pad = (4 - len(assertion) % 4) % 4 assertion += needed_pad * '=' assertion = decompress(base64.urlsafe_b64decode(assertion)) except: raise InvenioWebAccessExternalAuthError( "The provided assertion is corrupted") data = json_unicode_to_utf8(json.loads(assertion)) if not isinstance(data, dict): raise InvenioWebAccessExternalAuthError( "The provided assertion is invalid") timeout = data[self.timeout_attribute_name] if timeout < time.time(): raise InvenioWebAccessExternalAuthError( "The provided assertion is expired") userip = data.get(self.userip_attribute_name) if not self.check_user_ip or (normalize_ip( userip, self.check_user_ip) == normalize_ip( req.remote_ip, self.check_user_ip)): return data else: raise InvenioWebAccessExternalAuthError( "The provided assertion has been issued for a different IP address (%s instead of %s)" % (userip, req.remote_ip))
def auth_user(self, username, password, req=None): """Authenticate user-supplied USERNAME and PASSWORD. Return None if authentication failed, or the email address of the person if the authentication was successful. In order to do this you may perhaps have to keep a translation table between usernames and email addresses. Raise InvenioWebAccessExternalAuthError in case of external troubles. """ data = self.__extract_attribute(req) email = data.get(self.email_attribute_name) if email: if isinstance(email, str): return email.strip().lower() else: raise InvenioWebAccessExternalAuthError("The email provided in the assertion is invalid: %s" % (repr(email))) else: return None