def get_username_and_password_from_request(request): """Returns tuple of (username, password). Tuple values may be null.""" from corehq.apps.hqwebapp.utils import decode_password if 'HTTP_AUTHORIZATION' not in request.META: return None, None @sensitive_variables() def _decode(string): try: return string.decode('utf-8') except UnicodeDecodeError: # https://sentry.io/dimagi/commcarehq/issues/391378081/ return string.decode('latin1') auth = request.META['HTTP_AUTHORIZATION'].split() username = password = None if auth[0].lower() == DIGEST: try: digest = parse_digest_credentials( request.META['HTTP_AUTHORIZATION']) username = digest.username.lower() except UnicodeDecodeError: pass elif auth[0].lower() == BASIC: username, password = _decode(base64.b64decode(auth[1])).split(':', 1) username = username.lower() # decode password submitted from mobile app login password = decode_password(password) return username, password
def authenticate(self, request): if not 'HTTP_AUTHORIZATION' in request.META: return False if not python_digest.is_digest_credential(request.META['HTTP_AUTHORIZATION']): return False digest_response = python_digest.parse_digest_credentials( request.META['HTTP_AUTHORIZATION']) if not digest_response: _l.debug('authentication failure: supplied digest credentials could not be ' \ 'parsed: "%s".' % request.META['HTTP_AUTHORIZATION']) return False if not digest_response.realm == self.realm: _l.debug('authentication failure: supplied realm "%s" does not match ' \ 'configured realm "%s".' % ( digest_response.realm, self.realm)) return False if not python_digest.validate_nonce(digest_response.nonce, self.secret_key): _l.debug('authentication failure: nonce validation failed.') return False partial_digest = self._account_storage.get_partial_digest(digest_response.username) if not partial_digest: _l.debug('authentication failure: no partial digest available for user "%s".' \ % digest_response.username) return False calculated_request_digest = python_digest.calculate_request_digest( method=request.method, digest_response=digest_response, partial_digest=partial_digest) if not calculated_request_digest == digest_response.response: _l.debug('authentication failure: supplied request digest does not match ' \ 'calculated request digest.') return False if not python_digest.validate_uri(digest_response.uri, request.path): _l.debug('authentication failure: digest authentication uri value "%s" does not ' \ 'match value "%s" from HTTP request line.' % (digest_response.uri, request.path)) return False user = self._account_storage.get_user(digest_response.username) if not self._update_existing_nonce(user, digest_response.nonce, digest_response.nc): if (python_digest.get_nonce_timestamp(digest_response.nonce) + self.timeout < time.time()): _l.debug('authentication failure: attempt to establish a new session with ' \ 'a stale nonce.') return False if not self._store_nonce(user, digest_response.nonce, digest_response.nc): _l.debug('authentication failure: attempt to establish a previously used ' \ 'or nonce count.') return False request.user = user return True
def hello_with_digest_auth(request): auth = request.META.get('HTTP_AUTHORIZATION', None) if auth is None: return _digest_unauthenticated(request) try: method, data = auth.split(' ', 1) if 'digest' != method.lower(): return _digest_unauthenticated(request) except: raise return _digest_unauthenticated(request) digest_response = python_digest.parse_digest_credentials(auth) expected = python_digest.calculate_request_digest( request.method, python_digest.calculate_partial_digest(digest_response.username, 'DEV', '12345'), digest_response) if digest_response.response != expected: return _digest_unauthenticated(request) return HttpResponse('Hello World')
def get_username_and_password_from_request(request): """Returns tuple of (username, password). Tuple values may be null.""" from corehq.apps.hqwebapp.utils import decode_password if 'HTTP_AUTHORIZATION' not in request.META: return None, None @sensitive_variables() def _decode(string): try: return string.decode('utf-8') except UnicodeDecodeError: # https://sentry.io/dimagi/commcarehq/issues/391378081/ return string.decode('latin1') auth = request.META['HTTP_AUTHORIZATION'].split() username = password = None if auth[0].lower() == DIGEST: try: digest = parse_digest_credentials(request.META['HTTP_AUTHORIZATION']) username = digest.username.lower() except UnicodeDecodeError: pass elif auth[0].lower() == BASIC: username, password = _decode(base64.b64decode(auth[1])).split(':', 1) username = username.lower() # decode password submitted from mobile app login password = decode_password(password, username) return username, password
def wrapper(request, *args, **kwargs): authenticator = HttpDigestAuthenticator() if not authenticator.authenticate(request): return authenticator.build_challenge_response() response = f(request, *args, **kwargs) if hasattr(response, 'status_code') and response.status_code in [401, 403]: return authenticator.build_challenge_response() if 200 <= response.status_code < 300: digest = python_digest.parse_digest_credentials( request.META['HTTP_AUTHORIZATION']) nc = "%08d" % digest.nc partial_digest = authenticator._account_storage.get_partial_digest( digest.username) parameters = { "username": request.user.username, "ha1": partial_digest, "nonce": digest.nonce, "cnonce": digest.cnonce, "method": digest.algorithm, "uri": digest.uri, "nc": nc, } rspauth = calc_rspauth(parameters) info = 'rspauth="%s",cnonce="%s",nc=%s,qop=%s' % ( rspauth, digest.cnonce, nc, digest.qop) response["Authentication-Info"] = info return response
def wrapper(request, *args, **kwargs): authenticator = HttpDigestAuthenticator() if not authenticator.authenticate(request): return authenticator.build_challenge_response() response = f(request, *args, **kwargs) if hasattr(response, 'status_code') and response.status_code in [401, 403]: return authenticator.build_challenge_response() if 200 <= response.status_code < 300: digest = python_digest.parse_digest_credentials( request.META['HTTP_AUTHORIZATION']) nc = "%08d" % digest.nc partial_digest = authenticator._account_storage.get_partial_digest(digest.username) parameters = { "username": request.user.username, "ha1": partial_digest, "nonce": digest.nonce, "cnonce": digest.cnonce, "method":digest.algorithm, "uri": digest.uri, "nc": nc, } rspauth = calc_rspauth(parameters) info = 'rspauth="%s",cnonce="%s",nc=%s,qop=%s' % (rspauth, digest.cnonce, nc, digest.qop) response["Authentication-Info"] = info return response
def is_authenticated(self, request, **kwargs): """ Finds the user and checks their API key. Should return either ``True`` if allowed, ``False`` if not or an ``HttpResponse`` if you need something custom. """ if not request.META.get('HTTP_AUTHORIZATION'): return self._unauthorized() try: (auth_type, data) = request.META['HTTP_AUTHORIZATION'].split(' ', 1) if auth_type != 'Digest': return self._unauthorized() except: return self._unauthorized() digest_response = python_digest.parse_digest_credentials(request.META['HTTP_AUTHORIZATION']) if not python_digest.validate_nonce(digest_response.nonce, self.secret_key): return self._unauthorized() try: user = self.check_credentials(request=request, digest_response=digest_response.response, username=digest_response.username) except Unauthorized: return self._unauthorized() request.user = user return True
def _get_username_from_request(request): auth_header = (request.META.get('HTTP_AUTHORIZATION') or '').lower() username = None if auth_header.startswith('digest '): digest = parse_digest_credentials(request.META['HTTP_AUTHORIZATION']) username = digest.username elif auth_header.startswith('basic '): try: username = b64decode(request.META['HTTP_AUTHORIZATION'].split()[1]).split(':')[0] except IndexError: pass return username
def _get_username_from_request(request): auth_header = (request.META.get('HTTP_AUTHORIZATION') or '').lower() username = None if auth_header.startswith('digest '): digest = parse_digest_credentials(request.META['HTTP_AUTHORIZATION']) username = digest.username elif auth_header.startswith('basic '): try: username = b64decode( request.META['HTTP_AUTHORIZATION'].split()[1]).split(':')[0] except IndexError: pass return username
def is_authenticated(self, request, **kwargs): """ Finds the user and checks their API key. Should return either ``True`` if allowed, ``False`` if not or an ``HttpResponse`` if you need something custom. """ if not request.META.get('HTTP_AUTHORIZATION'): return self._unauthorized() try: (auth_type, data) = request.META['HTTP_AUTHORIZATION'].split(' ', 1) if auth_type.lower() != 'digest': return self._unauthorized() except: return self._unauthorized() digest_response = python_digest.parse_digest_credentials( request.META['HTTP_AUTHORIZATION']) # FIXME: Should the nonce be per-user? if not python_digest.validate_nonce( digest_response.nonce, getattr(settings, 'SECRET_KEY', '')): return self._unauthorized() user = self.get_user(digest_response.username) api_key = self.get_key(user) if user is False or api_key is False: return self._unauthorized() expected = python_digest.calculate_request_digest( request.method, python_digest.calculate_partial_digest(digest_response.username, self.realm, api_key), digest_response) if not digest_response.response == expected: return self._unauthorized() if not self.check_active(user): return False request.user = user return True
def is_authenticated(self, request, **kwargs): """ Finds the user and checks their API key. Should return either ``True`` if allowed, ``False`` if not or an ``HttpResponse`` if you need something custom. """ if not request.META.get('HTTP_AUTHORIZATION'): return self._unauthorized() try: (auth_type, data) = request.META['HTTP_AUTHORIZATION'].split( ' ', 1) if auth_type.lower() != 'digest': return self._unauthorized() except: return self._unauthorized() digest_response = python_digest.parse_digest_credentials( request.META['HTTP_AUTHORIZATION']) # FIXME: Should the nonce be per-user? if not python_digest.validate_nonce( digest_response.nonce, getattr(settings, 'SECRET_KEY', '')): return self._unauthorized() user = self.get_user(digest_response.username) api_key = self.get_key(user) if user is False or api_key is False: return self._unauthorized() expected = python_digest.calculate_request_digest( request.method, python_digest.calculate_partial_digest(digest_response.username, self.realm, api_key), digest_response) if not digest_response.response == expected: return self._unauthorized() if not self.check_active(user): return False request.user = user return True
def is_authenticated(self, request, **kwargs): """ Finds the user and checks their API key. Should return either ``True`` if allowed, ``False`` if not or an ``HttpResponse`` if you need something custom. """ try: self.get_authorization_data(request) except ValueError: return self._unauthorized() digest_response = python_digest.parse_digest_credentials(request.META["HTTP_AUTHORIZATION"]) # FIXME: Should the nonce be per-user? if not python_digest.validate_nonce(digest_response.nonce, settings.SECRET_KEY): return self._unauthorized() user = self.get_user(digest_response.username) api_key = self.get_key(user) if user is False or api_key is False: return self._unauthorized() expected = python_digest.calculate_request_digest( request.method, python_digest.calculate_partial_digest(digest_response.username, self.realm, api_key), digest_response, ) if not digest_response.response == expected: return self._unauthorized() if not self.check_active(user): return False request.user = user return True
def authenticate(self, request): if not 'HTTP_AUTHORIZATION' in request.META: return False if not python_digest.is_digest_credential(request.META['HTTP_AUTHORIZATION']): return False try: unicode(request.META['HTTP_AUTHORIZATION'], 'utf-8') except UnicodeDecodeError: return False digest_response = python_digest.parse_digest_credentials( request.META['HTTP_AUTHORIZATION']) if not digest_response: _l.debug('authentication failure: supplied digest credentials could not be ' \ 'parsed: "%s".' % request.META['HTTP_AUTHORIZATION']) return False if not digest_response.realm == self.realm: _l.debug('authentication failure: supplied realm "%s" does not match ' \ 'configured realm "%s".' % ( digest_response.realm, self.realm)) return False if not python_digest.validate_nonce(digest_response.nonce, self.secret_key): _l.debug('authentication failure: nonce validation failed.') return False partial_digest = self._account_storage.get_partial_digest(digest_response.username) if not partial_digest: _l.debug('authentication failure: no partial digest available for user "%s".' \ % digest_response.username) return False calculated_request_digest = python_digest.calculate_request_digest( method=request.method, digest_response=digest_response, partial_digest=partial_digest) if not calculated_request_digest == digest_response.response: _l.debug('authentication failure: supplied request digest does not match ' \ 'calculated request digest.') if self.failure_callback: self.failure_callback(request, digest_response.username) return False if not python_digest.validate_uri(digest_response.uri, request.path): _l.debug('authentication failure: digest authentication uri value "%s" does not ' \ 'match value "%s" from HTTP request line.' % (digest_response.uri, request.path)) return False user = self._account_storage.get_user(digest_response.username) if not self._update_existing_nonce(user, digest_response.nonce, digest_response.nc): if (python_digest.get_nonce_timestamp(digest_response.nonce) + self.timeout < time.time()): _l.debug('authentication failure: attempt to establish a new session with ' \ 'a stale nonce.') return False if not self._store_nonce(user, digest_response.nonce, digest_response.nc): _l.debug('authentication failure: attempt to establish a previously used ' \ 'or nonce count.') return False request.user = user return True
def authenticate(self, request): """ Base authentication method, all checks here """ if not request.headers.get('authorization'): return False if not python_digest.is_digest_credential( request.headers.get('authorization')): return False digest_response = python_digest.parse_digest_credentials( request.headers.get('authorization')) if not digest_response: log.debug('authentication failure: supplied digest credentials' ' could not be parsed: "%s".' % request.headers.get('authorization')) return False if not digest_response.username: return False if not digest_response.realm == self.realm: log.debug('authentication failure: supplied realm "%s"' 'does not match configured realm "%s".' % (digest_response.realm, self.realm)) return False if not python_digest.validate_nonce( digest_response.nonce, self.secret_key): log.debug('authentication failure: nonce validation failed.') return False partial_digest = self._account_storage.get_partial_digest( digest_response.username) if not partial_digest: log.debug('authentication failure: no partial digest available' ' for user "%s".' % digest_response.username) return False calculated_request_digest = python_digest.calculate_request_digest( method=request.method, digest_response=digest_response, partial_digest=partial_digest) if not calculated_request_digest == digest_response.response: log.debug('authentication failure: supplied request digest' 'does not match calculated request digest.') return False if not python_digest.validate_uri( digest_response.uri, urllib.parse.unquote(request.path)): log.debug('authentication failure: digest authentication uri value' '"%s" does not match value "%s" from HTTP' 'request line.' % (digest_response.uri, request.path)) return False if not self._account_storage.is_admin(digest_response.username): log.debug('authentication failure: user not in operator admin.') return False if hasattr(request,'session') and request.session.data.nonce != digest_response.nonce: if (int(python_digest.get_nonce_timestamp(digest_response.nonce)) + self.timeout < time.time()): log.debug('authentication failure: attempt to establish' ' a new session with a stale nonce.') return False if not self._store_nonce(digest_response.nonce, request): log.debug('authentication failure: attempt to establish' ' a previously used or nonce count.') return False request.user = self._account_storage.get_by_login( digest_response.username) return True
def checkUserId(self, requestedUid=None, anonymous=False): if ('Authorization' not in self.__req.headers): self.__setAuthenticate() raise AuthError('User#auth need user Authentification', 401, 20) #XXX check header validity http_authorization_header = self.__req.headers['Authorization'] digest_response = python_digest.parse_digest_credentials( http_authorization_header) if digest_response is None: self.__setAuthenticate() raise AuthError('User#Auth need digest authentification', 401, 21) if digest_response.uri != self.__req.path_qs: self.__setAuthenticate() raise AuthError('User#Auth invalid uri', 403, 22) if (anonymous is True and digest_response.username.lower() != "anonymous") or \ (anonymous is False and digest_response.username.lower() == "anonymous"): self.__setAuthenticate() raise AuthError('User#Auth forbidden', 403, 23) if python_digest.validate_nonce( digest_response.nonce, self.__cfg.get('nonce_secret') ) is not True: self.__setAuthenticate(True) raise AuthError('User#auth invalid nonce', 401, 24) #fetch user obj = users.Factory.get(digest_response.username) if not obj: self.__setAuthenticate() raise AuthError('User#auth unknown user', 404, 25) if obj.activate == 0: self.__setAuthenticate() raise AuthError('User#auth unactivated user', 403, 26) expected_request_digest = python_digest \ .calculate_request_digest( self.__req.method, obj.digest, digest_response) #nonce lifetime delta = time.time( ) - python_digest.get_nonce_timestamp(digest_response.nonce) if delta > self.__cfg.get('nonce_ttl'): self.__setAuthenticate(True) raise AuthError('User#auth nonce expired', 401, 27) #grab session sessId = hashlib.sha1( digest_response.nonce.encode('utf-8')).hexdigest() prevRequest = storage.Memcache().get(sessId, 'session') #if not, check memcache status if not prevRequest: try: storage.Memcache().checkAlive() self.__setAuthenticate(True) raise AuthError('User#auth nonce expired', 401, 28) except storage.MemcacheError: raise AuthError('Service unavailable', 503, 2) #Check nc: if not prevRequest or prevRequest['nc'] >= digest_response.nc: self.__setAuthenticate(True) raise AuthError('User#auth invalid nonce count', 401, 29) #check opaque if prevRequest['opaque'] != digest_response.opaque: self.__setAuthenticate(True) raise AuthError('User#auth invalid opaque', 401, 30) #check digest response if expected_request_digest != digest_response.response: self.__setAuthenticate() raise AuthError('User#auth invalid credentials', 401, 31) #store nonce count self.__storeSession(sessId, digest_response.opaque, digest_response.nc) if anonymous is False: self.__resp.headers['X-Lxxl-User-Token'] = str(obj.getToken()) self.__resp.headers['X-Lxxl-User-id'] = str(obj.uid) self.__resp.headers['X-Lxxl-User-Relation'] = "1" return True