I'm not sure if this is an issue or just because of the implementation, but I was using middleware to log user_id against records being edited, and I couldn't get request.user at the middleware level (and so of course request.user.is_authorized() returned False).
The middleware was the last one on the list, and authorization was working (I would get a 403 requesting assets without my token header). I tried putting 'rest_framework_jwt.authentication.JSONWebTokenAuthentication'
at the top of DEFAULT_AUTHENTICATION_CLASSES
, and also making it the only item in the tuple; neither worked.
I've managed to work around my issue by accessing the header and using the tools directly in the app to retrieve the user; essentially I copied chunks of your code into my middleware, but I thought you should know :)
If you're interested, here's the middleware:
from django.db.models import signals
from django.utils.functional import curry
from django.utils import timezone
from threading import local
import jwt
from rest_framework.authentication import get_authorization_header
from rest_framework_jwt.settings import api_settings
from django.conf import settings
try:
from django.contrib.auth import get_user_model
except ImportError: # Django < 1.5
from django.contrib.auth.models import User
else:
User = get_user_model()
_user = local()
class AuditMiddleware(object):
def process_request(self, request):
if not request.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
if hasattr(request, 'user') and request.user.is_authenticated():
user = request.user
else:
user = self.get_user_from_auth_header(request)
if user is not None:
request.user = user
_user.value = user
mark_whodid = curry(self.mark_whodid, _user.value)
signals.pre_save.connect(mark_whodid, dispatch_uid = (self.__class__, request,), weak = False)
def process_response(self, request, response):
signals.pre_save.disconnect(dispatch_uid = (self.__class__, request,))
return response
def mark_whodid(self, user, sender, instance, **kwargs):
# user logging here
def get_user_from_auth_header(self, request):
try:
auth_keyword, token = get_authorization_header(request).split()
jwt_header, claims, signature = token.split('.')
try:
payload = api_settings.JWT_DECODE_HANDLER(token)
try:
user_id = api_settings.JWT_PAYLOAD_GET_USER_ID_HANDLER(payload)
if user_id:
user = User.objects.get(pk=user_id, is_active=True)
return user
else:
msg = 'Invalid payload'
return None
except User.DoesNotExist:
msg = 'Invalid signature'
return None
except jwt.ExpiredSignature:
msg = 'Signature has expired.'
return None
except jwt.DecodeError:
msg = 'Error decoding signature.'
return None
except ValueError:
return None