Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How add Authenticate Middleware JWT django?

Tags:

python

django

jwt

I am trying to create a middleware to authenticate with JWT but in the view the request.user is always AnonymUser.

When I verify that the middleware changes the request.user by the User Model, it does, but upon reaching the view, for some reason the request.user is always anonymousUser

I'n using Django 1.11

# coding=utf-8
from django.utils.functional import SimpleLazyObject
from django.utils.deprecation import MiddlewareMixin
from django.contrib.auth.models import AnonymousUser, User
from django.conf import settings
from django.contrib.auth.middleware import get_user
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
import jwt
import json


class JWTAuthenticationMiddleware(MiddlewareMixin):
    def process_request(self, request):
        request.user = SimpleLazyObject(lambda: self.__class__.get_jwt_user(request))

    @staticmethod
    def get_jwt_user(request):
        user_jwt = get_user(request)
        if user_jwt.is_authenticated():
            return user_jwt
        token = request.META.get('HTTP_AUTHORIZATION', None)
        user_jwt = None
        if token is not None:
            try:
                user_jwt = jwt.decode(
                    token,
                    settings.SECRET_KEY,
                    algorithms=['HS256']
                )
                user_jwt = User.objects.get(
                    id=user_jwt['user_id']
                )
            except Exception as e:
                user_jwt = AnonymousUser
        return user_jwt





MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
     'django.middleware.security.SecurityMiddleware',
     'django.contrib.sessions.middleware.SessionMiddleware',
     'django.middleware.common.CommonMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',
     'user.middlewares.JWTAuthenticationMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
     'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
like image 712
Lopsan Osorio Avatar asked Jul 23 '17 15:07

Lopsan Osorio


2 Answers

I was trying to replicate your error, but in my case, it works just well, I think the root cause of your problem is the exception handling method. jwt.decode can raise multiples types of exceptions, including DecodeError, ExpiredSignatureError , InvalidKeyError and many more, even the dict retrieved from jwt.decode could not have a 'user_id' key.

This is a fully working code

# coding=utf-8
import jwt
import traceback

from django.utils.functional import SimpleLazyObject
from django.utils.deprecation import MiddlewareMixin
from django.contrib.auth.models import AnonymousUser, User
from django.conf import LazySettings
from django.contrib.auth.middleware import get_user

settings = LazySettings()


class JWTAuthenticationMiddleware(MiddlewareMixin):
    def process_request(self, request):
        request.user = SimpleLazyObject(lambda: self.__class__.get_jwt_user(request))

    @staticmethod
    def get_jwt_user(request):

        user_jwt = get_user(request)
        if user_jwt.is_authenticated():
            return user_jwt
        token = request.META.get('HTTP_AUTHORIZATION', None)

        user_jwt = AnonymousUser()
        if token is not None:
            try:
                user_jwt = jwt.decode(
                    token,
                    settings.WP_JWT_TOKEN,
                )
                user_jwt = User.objects.get(
                    id=user_jwt['data']['user']['id']
                )
            except Exception as e: # NoQA
                traceback.print_exc()
        return user_jwt

Just a few more considerations, is always a good practice use LazySettings instead settings Check this thread

Also this is my middleware order

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'applications.custom_authentication.middleware.JWTAuthenticationMiddleware', # This is my middleware
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Just remember to put your custom middleware after django.contrib.auth.middleware.AuthenticationMiddleware middleware

like image 68
Mauricio Collazos Avatar answered Oct 16 '22 09:10

Mauricio Collazos


Try with this middleware:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'applications.custom_authentication.middleware.JWTAuthenticationMiddleware', # This is my middleware
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
like image 39
Alejandro Maguey Avatar answered Oct 16 '22 09:10

Alejandro Maguey