def authenticate(self, environ, start_response): """ Implements the authentication logic. :param environ: WSGI environment instance. :type environ: dict :param start_response: WSGI start response callable. :type start_response: callable :returns: True on success, False on failure :rtype: bool """ user, passwd = decode_basic_auth(self.logger, environ.get('HTTP_AUTHORIZATION')) # If there is no user or password then log and don't even bother # keystone with a request. Fail early. if user is None or passwd is None: self.logger.info('Authentication can not continue due to mising ' 'user/pass. Rejecting.') self.logger.debug('User: {}, Pass: {}'.format(user, passwd)) self.logger.debug('Environ: {}'.format(environ)) return False headers = {'Content-Type': 'application/json'} body = {'auth': {'identity': {}}} ident = body['auth']['identity'] ident['methods'] = ['password'] ident['password'] = { 'user': { 'name': user, 'password': passwd, 'domain': { 'name': self.domain } } } try: response = requests.post(self.url, data=json.dumps(body), headers=headers) except requests.exceptions.BaseHTTPError as error: self.logger.error( 'Could not reach {}. Denying access. {}: {}'.format( self.url, type(error), error)) return False subject_token_name = 'X-Subject-Token' if subject_token_name in response.headers: token = response.headers[subject_token_name] start_response('200 OK', [('content-type', 'application/json'), (subject_token_name, token)]) return True # Forbid by default return False
def test_decode_basic_auth(self): """ Verify decoding returns a filled tuple given the proper header no matter the case of basic. """ basic = list('basic') for x in range(0, 5): self.assertEquals( ('a', 'a'), decode_basic_auth(None, '{0} YTph'.format(''.join(basic)))) # Update the next letter to be capitalized basic[x] = basic[x].capitalize()
def authenticate(self, environ, start_response): """ Implements the authentication logic. :param environ: WSGI environment instance. :type environ: dict :param start_response: WSGI start response callable. :type start_response: callable :returns: True on success, False on failure :rtype: bool """ user, passwd = decode_basic_auth(self.logger, environ.get('HTTP_AUTHORIZATION')) if user is not None and passwd is not None: if user in self._data.keys(): self.logger.debug('User %s found in datastore.', user) if self.check_authentication(user, passwd): return True # Authentication is good # Forbid by default return False
def test_decode_basic_auth_with_bad_data(self): """ Verify decoding returns no user with bad base64 data in the header. """ self.assertEquals((None, None), decode_basic_auth(None, 'basic BADDATA'))