Search code examples
djangodjango-rest-frameworksetcookiedjango-cors-headersdjango-rest-framework-simplejwt

Django Rest Framework - response.set_cookie() not setting cookie in browser but working in postman and in browsable api


I am struggling with setting jwt token in httponly cookie. I tried many solution but not working. I am working with localhost "127.0.0.1" but when I try to login the cookies sent by server not display in my frontend working at "127.0.0.1:5501" but if I try with Browsable api working at "127.0.0.1:8000" it works fine and I can check my cookies easily.

I noticed a weird thing too. If I login via my frontend "127.0.0.1:5501", cookies not set but if I try with browsable api working at "127.0.0.1:8000" and then switch to my "127.0.0.1:5501" tab I can see that cookies their too. This a very Weird thing and I don't know the reason behind this.

Please help me to resolve this issue.

Views.py

class LoginView(APIView):
    def post(self,request,format=None):
    
        data = request.data
        
        response = Response()
        username = data.get('username', None)
        password = data.get('password', None)
        user = authenticate(username=username, password=password)
        if user is not None:
            if user.is_active:
                data = get_tokens_for_user(user)
                response.set_cookie(
                                    key = settings.SIMPLE_JWT['AUTH_COOKIE'], 
                                    value = data["access"],
                                    expires = settings.SIMPLE_JWT['ACCESS_TOKEN_LIFETIME'],
                                    secure = settings.SIMPLE_JWT['AUTH_COOKIE_SECURE'],
                                    httponly = settings.SIMPLE_JWT['AUTH_COOKIE_HTTP_ONLY'],
                                    samesite = settings.SIMPLE_JWT['AUTH_COOKIE_SAMESITE']
                                        )
                csrf.get_token(request)
                response.data = {"Success" : "Login successfully","data":data}
                
                return response
            else:
                return Response({"No active" : "This account is not active!!"},status=status.HTTP_404_NOT_FOUND)
        else:
            return Response({"Invalid" : "Invalid username or password!!"},status=status.HTTP_404_NOT_FOUND)

Fetch Api request


async function login(email,password)
{
    
    let response = await fetch('http://127.0.0.1:8000/api/account/login/',{
        method: 'POST',
        headers: {
            "Accept": "application/json",
            "Content-Type": "application/json",
            
        },
        withCredentials: true,
        body: JSON.stringify({
            'username': email,
            'password': password
        })

    

    })
    return response;
}

Settings.py file

ALLOWED_HOSTS = ['127.0.0.1']
CORS_ALLOW_HEADERS = default_headers + (
    'Access-Control-Allow-Origin',
)

CORS_ALLOW_CREDENTIALS = True
CORS_ALLOWED_ORIGINS = [
    "http://127.0.0.1:5501",
]


# ////////////////custom settings/////////////source : stackoverflow/////////////////////
    'AUTH_COOKIE': 'access_token',  # Cookie name. Enables cookies if value is set.
    'AUTH_COOKIE_DOMAIN': None,     # A string like "example.com", or None for standard domain cookie.
    'AUTH_COOKIE_SECURE': False,    # Whether the auth cookies should be secure (https:// only).
    'AUTH_COOKIE_HTTP_ONLY' : True, # Http only cookie flag.It's not fetch by javascript.
    'AUTH_COOKIE_PATH': '/',        # The path of the auth cookie.
    'AUTH_COOKIE_SAMESITE': 'Lax',  # Whether to set the flag restricting cookie leaks on cross-site requests.
                                # This can be 'Lax', 'Strict', or None to disable the flag.
    


Postman demo enter image description here

Browsable api demo

enter image description here

Frontend demo enter image description here


Solution

  • If you are also struggling with this issue. Just make sure that you have above setting and follow this simple update.

    let response = await fetch('http://127.0.0.1:8000/api/account/login/',{
            method: 'POST',
            headers: {
                "Accept": "application/json",
                "Content-Type": "application/json",
                
            },
            credentials: 'include',
            body: JSON.stringify({
                'username': email,
                'password': password
            })
    
        
    
        })
    
    

    It should be credentials only.