4

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?

forest
  • 1,312
  • 3
  • 20
  • 47

0 Answers0