I have configured DRF to use JWT as an authentication scheme and for the most part works correctly however when a user's token & refresh token are no longer valid rather than returning a 200 as an unauthorized user for unprotected routes and displaying the website as if they are no longer logged in the backend returns a 401. I am new to the Django auth scheme / middleware setup but my assumption would be that if the default is AllowAny
then a bad token would be ignored. Is there a configuration that I am missing.
From the DRF Docs
If not specified, this setting defaults to allowing unrestricted access:
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny', ]
my settings.py
REST_FRAMEWORK = {
...
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework.authentication.BasicAuthentication",
"rest_framework_simplejwt.authentication.JWTAuthentication",
),
}
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": datetime.timedelta(minutes=15),
"REFRESH_TOKEN_LIFETIME": datetime.timedelta(days=2),
...
}
Example ViewSet
that returns 401
with bad access token
class PromoApiSet(ViewSet):
serializer_class = PromoSerializer
def get_queryset(self, *args, **kwargs):
time_now = timezone.now()
return PromoNotification.objects.filter(
end_date__gte=time_now, start_date__lte=time_now
)
# @method_decorator(cache_page(120))
def list(self, request):
promos = self.get_queryset()
serializer = self.serializer_class(promos, many=True)
promos_data = serializer.data
response_data = {"promos": promos_data}
return Response(response_data)
Invalid, malformed, or otherwise incorrect credentials will raise a 401, see the source code for the JWTAuthentication
class.
This makes sense to me, but if you want the behavior to be "silently ignore this header if there was an error" then you need to override the method and, well, ignore the errors:
class MyJWTAuth(JWTAuthentication):
def authenticate(self, request):
try:
return super().authenticate(self, request)
except (InvalidToken, AuthenticationFailed):
return None
# in your settings, use your new class
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework.authentication.BasicAuthentication",
"my.project.module.MyJWTAuth",
),
This will work, but I wouldn't recommend it in general. If you want more granular "ignoring" of specific errors then you'll need to override more functionality, or vendor the class and make modifications directly.