<commit_before>from django.contrib.auth import get_user_model
from django.core.cache import cache
from django.utils.deprecation import MiddlewareMixin
from asymmetric_jwt_auth import AUTH_METHOD
import asymmetric_jwt_auth.token as token
import logging

logger = logging.getLogger(__name__)


class JWTAuthMiddleware(MiddlewareMixin):
    """Django middleware class for authenticating users using JWT Authentication headers"""

    def create_nonce_key(self, username, iat):
        """
        Create and return the cache key for storing nonces

        :param username: Username as a string.
        :param iat: Unix timestamp float or integer of when the nonce was used.
        :return: Cache key string.
        """
        return '%s-nonces-%s-%s' % (
            self.__class__.__name__,
            username,
            iat,
        )


    def log_used_nonce(self, username, iat, nonce):
        """
        Log a nonce as being used, and therefore henceforth invalid.

        :param username: Username as a string.
        :param iat: Unix timestamp float or integer of when the nonce was used.
        :param nonce: Nonce value.
        """
        # TODO: Figure out some way to do this in a thread-safe manner. It'd be better to use
        # a Redis Set or something, but we don't necessarily want to be tightly coupled to
        # Redis either since not everyone uses it.
        key = self.create_nonce_key(username, iat)
        used = cache.get(key, [])
        used.append(nonce)
        cache.set(key, set(used), token.TIMESTAMP_TOLERANCE * 2)


    def validate_nonce(self, username, iat, nonce):
        """
        Confirm that the given nonce hasn't already been used.

        :param username: Username as a string.
        :param iat: Unix timestamp float or integer of when the nonce was used.
        :param nonce: Nonce value.
        :return: True if nonce is valid, False if it is invalid.
        """
        key = self.create_nonce_key(username, iat)
        used = cache.get(key, [])
        return nonce not in used


    def process_request(self, request):
        """
        Process a Django request and authenticate users.

        If a JWT authentication header is detected and it is determined to be valid, the user is set as
        ``request.user`` and CSRF protection is disabled (``request._dont_enforce_csrf_checks = True``) on
        the request.

        :param request: Django Request instance
        """
        if 'HTTP_AUTHORIZATION' not in request.META:
            return

        method, claim = request.META['HTTP_AUTHORIZATION'].split(' ', 1)
        if method.upper() != AUTH_METHOD:
            return

        username = token.get_claimed_username(claim)
        if not username:
            return

        User = get_user_model()
        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            return
<commit_msg>Fix exception thrown when processing a request with a malformed Authorization header<commit_after>from django.contrib.auth import get_user_model
from django.core.cache import cache
from django.utils.deprecation import MiddlewareMixin
from asymmetric_jwt_auth import AUTH_METHOD
import asymmetric_jwt_auth.token as token
import logging

logger = logging.getLogger(__name__)


class JWTAuthMiddleware(MiddlewareMixin):
    """Django middleware class for authenticating users using JWT Authentication headers"""

    def create_nonce_key(self, username, iat):
        """
        Create and return the cache key for storing nonces

        :param username: Username as a string.
        :param iat: Unix timestamp float or integer of when the nonce was used.
        :return: Cache key string.
        """
        return '%s-nonces-%s-%s' % (
            self.__class__.__name__,
            username,
            iat,
        )


    def log_used_nonce(self, username, iat, nonce):
        """
        Log a nonce as being used, and therefore henceforth invalid.

        :param username: Username as a string.
        :param iat: Unix timestamp float or integer of when the nonce was used.
        :param nonce: Nonce value.
        """
        # TODO: Figure out some way to do this in a thread-safe manner. It'd be better to use
        # a Redis Set or something, but we don't necessarily want to be tightly coupled to
        # Redis either since not everyone uses it.
        key = self.create_nonce_key(username, iat)
        used = cache.get(key, [])
        used.append(nonce)
        cache.set(key, set(used), token.TIMESTAMP_TOLERANCE * 2)


    def validate_nonce(self, username, iat, nonce):
        """
        Confirm that the given nonce hasn't already been used.

        :param username: Username as a string.
        :param iat: Unix timestamp float or integer of when the nonce was used.
        :param nonce: Nonce value.
        :return: True if nonce is valid, False if it is invalid.
        """
        key = self.create_nonce_key(username, iat)
        used = cache.get(key, [])
        return nonce not in used


    def process_request(self, request):
        """
        Process a Django request and authenticate users.

        If a JWT authentication header is detected and it is determined to be valid, the user is set as
        ``request.user`` and CSRF protection is disabled (``request._dont_enforce_csrf_checks = True``) on
        the request.

        :param request: Django Request instance
        """
        if 'HTTP_AUTHORIZATION' not in request.META:
            return

        try:
            method, claim = request.META['HTTP_AUTHORIZATION'].split(' ', 1)
        except ValueError:
            return

        if method.upper() != AUTH_METHOD:
            return

        username = token.get_claimed_username(claim)
        if not username:
            return

        User = get_user_model()
        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            return

{'fraction_non_alphanumeric': 0.0747538795261138, 'fraction_numerical': 0.0006674453529117303, 'mean_word_length': 2.339275766016713, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1066392', 'n_tokens_mistral': 1675, 'n_tokens_neox': 1610, 'n_words': 605}