Skip to content

Instantly share code, notes, and snippets.

@AndrewJHart
Created April 13, 2016 18:47
Show Gist options
  • Save AndrewJHart/9bb9eaea2523cd2144cf959f48a14194 to your computer and use it in GitHub Desktop.
Save AndrewJHart/9bb9eaea2523cd2144cf959f48a14194 to your computer and use it in GitHub Desktop.
JWT authentication middleware for django rest framework that populates the request.user object
from django.utils.functional import SimpleLazyObject
from django.contrib.auth.models import AnonymousUser
from rest_framework.request import Request
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
def get_user_jwt(request):
"""
Replacement for django session auth get_user & auth.get_user for
JSON Web Token authentication. Inspects the token for the user_id,
attempts to get that user from the DB & assigns the user on the
request object. Otherwise it defaults to AnonymousUser.
This will work with existing decorators like LoginRequired, whereas
the standard restframework_jwt auth only works at the view level
forcing all authenticated users to appear as AnonymousUser ;)
Returns: instance of user object or AnonymousUser object
"""
user = None
try:
user_jwt = JSONWebTokenAuthentication().authenticate(Request(request))
if user_jwt is not None:
# store the first part from the tuple (user, obj)
user = user_jwt[0]
except:
pass
return user or AnonymousUser()
class JWTAuthenticationMiddleware(object):
""" Middleware for authenticating JSON Web Tokens in Authorize Header """
def process_request(self, request):
request.user = SimpleLazyObject(lambda : get_user_jwt(request))
@AndrewJHart
Copy link
Author

This hasn't been thoroughly tested yet but so far it works great. We had no use for sessions or the built in authentication middleware for django as this was built to be a microservice for authentication. Unfortunately if you just use the django rest framework-jwt package the authentication occurs at the view level meaning request.user.is_authenticated() will always return False. We have a few internal non-api views that needed @login_required. We have a stripped down version of django that is very performant that we are using for microservices with built-in authorization using JSON Web Tokens.

Any questions or improvements please drop a line - thanks.

@zulrang
Copy link

zulrang commented Dec 5, 2017

I see this is a little dated. Is this still the best way to handle this, or did you come up with a better solution?

@diegojancic
Copy link

This works in older version of Django. For newer version, use:
from django.utils.deprecation import MiddlewareMixin

and then...:
class JWTAuthenticationMiddleware(MiddlewareMixin):

Source: https://stackoverflow.com/a/42233213

@ngunhaSO
Copy link

ngunhaSO commented Oct 2, 2018

Sorry, I am new to Django, but once I put this inplace, I am no longer able to access the admin page. It throws "'AnonymousUser' object is not callable". Can you suggest a way to solve this? Thanks

@AndrewJHart
Copy link
Author

Yeah this is dated, follow @diegojancic advice for newer versions. This was last used on probably django 1.9 maybe? Its been a while - I've been living in universal javascript for a while now. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment