0

I have a custom middleware where I am adding SimpleJWR HTTP_AUTHORIZATION to every authorized requests as I am using HttpOnly cookies. Also here I have added code to check whether an access token is valid or not. If not, then a request is sent using requests which fetches the new access token and set's it as HttpOnly cookie. So far, I'm able to get the new access token after it expires. But, the url from where I dispatched the request returns this error:

raise ContentNotRenderedError(
django.template.response.ContentNotRenderedError: The response content must be rendered before it can be accessed.

At the first request it works. It returns the response and saves the tokens as HttpOnly cookies but after the token expires and if I again make the request, instead of (what I want to happen) saving the tokens as HttpOnly cookies and returning the same response again, it is returning the error.

I think the issue is in the response statements. My middleware:

import jwt
import datetime
import requests
import json

from rest_framework.response import Response
from django.conf import settings

class AuthorizationHeaderMiddleware:
    def __init__(self, get_response=None):
        self.get_response = get_response

    def __call__(self, request):
        access_token = request.COOKIES.get('access')
        refesh_token = request.COOKIES.get('refresh')
        print(refesh_token)
        # check if the access token is valid
        # if not, send new access token to cookie
        if access_token:
            key = settings.SECRET_KEY
        try:
            decoded_access_token = jwt.decode(access_token, key, algorithms=["HS256"])
        except jwt.ExpiredSignatureError:
            # Signature has expired
            print("expired; sending for new token")
            url = 'http://127.0.0.1:8000/api/token/refresh/'
            data = {"refresh": refesh_token}
            resp = requests.post(
                url, 
                data=json.dumps(data),
                headers = {'content-type': 'application/json'}
                )
            result = resp.json()
            new_access_token = result['access']
            response = Response()
            response.set_cookie('access', new_access_token, httponly=True)
            response.set_cookie('set', 'new')
            return response

            request.META['HTTP_AUTHORIZATION'] = f'Bearer {access_token}'
        return self.get_response(request)

How is this error coming and how do I resolve it?

forest
  • 1,312
  • 3
  • 20
  • 47

1 Answers1

0

Try this:

def __call__(self, request):
    access_token = request.COOKIES.get('access')
    refesh_token = request.COOKIES.get('refresh')
    print(refesh_token)
    # check if the access token is valid
    # if not, send new access token to cookie
    if access_token is not None:
        key = settings.SECRET_KEY
    else:
        return Response({"Error" : "No token found"})
    try:
        decoded_access_token = jwt.decode(access_token, key, algorithms=["HS256"])
        request.META['HTTP_AUTHORIZATION'] = f'Bearer {access_token}'
        return self.get_response(request)
    except jwt.ExpiredSignatureError:
        # Signature has expired
        print("expired; sending for new token")
        url = 'http://127.0.0.1:8000/api/token/refresh/'
        data = {"refresh": refesh_token}
        resp = requests.post(
            url, 
            data=json.dumps(data),
            headers = {'content-type': 'application/json'}
            )
        result = resp.json()
        new_access_token = result['access']
        response = Response()
        response.set_cookie('access', new_access_token, httponly=True)
        response.set_cookie('set', 'new')
        request.META['HTTP_AUTHORIZATION'] = f'Bearer {new_access_token}'
        
        return self.get_response(request)
Pradip Kachhadiya
  • 2,067
  • 10
  • 28
  • After adding these I got these error: `if response.get('X-Frame-Options') is not None: AttributeError: 'NoneType' object has no attribute 'get'` – forest Feb 18 '21 at 16:45
  • Because if `access_token` not found in cookie at that time `access_token` return `None`.and our condition is not satisfy. so `__call__` method not return any response.I edited my ans. – Pradip Kachhadiya Feb 18 '21 at 18:49
  • Another way you can set and get httponly cookie.Check this : https://stackoverflow.com/a/66248320/14131913) and see this https://stackoverflow.com/a/63622625/14131913 or https://github.com/HarryAustin/tweeter-DrfTest-httonlycookie/blob/main/Django_Rest_Framework/middleware.py – Pradip Kachhadiya Feb 18 '21 at 19:00