I have applied JWT authentication with HttpOnly cookies using a custom middleware. Now, the middleware checks for the presence of access
and refresh
tokens as HttpOnly cookies in every request. Everything works well.
But, it retuns 'KeyError': 'access'
if I request for a page that does not require authentication, say, the homepage or bloglist or blogdetail page. How do I remove this need for access
token in these views with permissions
set to AllowAny
and also in some views where only the GET
method permission is set to AllowAny
?
My view:
class TagView(viewsets.ModelViewSet):
queryset = Tag.objects.all()
serializer_class = TagSerializer
def get_permissions(self):
if self.request.method == 'PUT':
self.permission_classes = [permissions.IsAuthenticated,]
elif self.request.method == 'GET':
self.permission_classes = [permissions.AllowAny,]
elif self.request.method == 'POST':
self.permission_classes = [permissions.IsAuthenticated,]
return super(TagView, self).get_permissions()
If request method is GET
, the middleware should pass the request even if no access
cookie is found.
Now, it checks for the access
cookie in every request. I added a line to skip asking for tokens if the request method is GET
and if there is no cookie in the request, to mark it as AllowAny
view, but I think it is unsafe.
My middleware:
class AuthorizationHeaderMiddleware:
def __init__(self, get_response=None):
self.get_response = get_response
def process_view(self, request, view_func, view_args, view_kwargs):
pass
def __call__(self, request):
if request.path == '/api/auth/login/':
return self.get_response(request)
# for AllowAny views, I am doing this, but I think it is unsafe
elif request.method == 'GET' and request.COOKIES == {}: # no cookies present
return self.get_response(request)
else:
try:
access_token = request.COOKIES['access']
key = settings.SECRET_KEY
jwt.decode(access_token, key, algorithms=["HS256"])
request.META['HTTP_AUTHORIZATION'] = f'Bearer {access_token}'
return self.get_response(request)
except jwt.ExpiredSignatureError:
refresh_cookie = request.COOKIES['refresh']
data = {"refresh": refresh_cookie}
resp = requests.post('http://127.0.0.1:8000/api/auth/refresh/', data=data)
access_token_string = json.loads(resp.text)["access"]
request.META['HTTP_AUTHORIZATION'] = f'Bearer {access_token_string}'
return self.get_response(request)
How do I allow selected AllowAny
views and methods if they don't have HttpOnly JWT token cookies?