Django-rest-API Authorization with react

Viewed 51

I work with react and Django-rest-framework, so I have an API for generate access token and

refresh token and store that access token in cookies with httponly set to true for security

but I am trying this:

when a user logs in the log in API return the access token and store in cookies I need to request the server if this user is authorized but when I do that with Credentials set to true

the request send the cookies with request but not generate authorized header for the API

here the API test on postman

here user authorization and it works fine manually

but when I need to request for authorization from browser I can't read httponly cookies

Is there any way to handle this on server side

I configure the setting ti use crosheader for authorization header

Here is how I request in react application

home component

import React, { useEffect, useState } from "react";
import axios from "axios";
import {withCookies} from 'react-cookie';

export const Home = () => {
  const [message, setMessage] = useState("Unauthenticated");
  useEffect(() => {

  (async () => {

  const response = await axios.get("user")//,{headers:{"Authorization":`Bearer`}}
  .then(() => {
        setMessage("hello user")
  })
  .catch((response) => {
    console.log(response.headers);
    
  });
  
  
  
})()
}, []);

return (
  <main>
    <h3 className="center">{message}</h3>
  </main>
);
};

and here axios default setting in react app

import axios from "axios";

axios.defaults.baseURL = "http://127.0.0.1:8000/api/";
axios.defaults.withCredentials = true;

when I request that from browser I get 401 error like this

LoginApiView endpoint

class LoginAPIView(APIView):

   @staticmethod
   def post(request):
       email = request.data['email']
       password = request.data['password']

       user = User.objects.filter(email = email).first()

       if user is None:
           raise exceptions.AuthenticationFailed('Invalid Credentials')

       if not user.check_password(password):
           raise exceptions.AuthenticationFailed('Invalid Credentials')

       access_token = create_access_token(user.id)
       refresh_token = create_refresh_token(user.id)

       UserToken.objects.create(
        user_id = user.id,
        token = refresh_token,
        expired_at = datetime.datetime.utcnow() + datetime.timedelta(days=7)
    )
       responce = Response()
       responce.set_cookie(key = 'access_token', value = access_token, httponly=True) # secure= True
       responce.set_cookie(key = 'refresh_token', value = refresh_token, httponly=True) # secure= True
    
       responce.data = {
        'access_token':access_token,
        'refresh_token':refresh_token
       }
       return responce

UserAPIView endpoint

class UserApiView(APIView):
    authentication_classes = [JWTAuthentication]

    @staticmethod
    def get(request):
        return Response(UserSerializer(request.user).data)

userAPI middleware

class JWTAuthentication(BaseAuthentication):
    def authenticate(self, request):
        auth = get_authorization_header(request).split()

        if auth and len(auth) == 2:
            token = auth[1].decode('utf-8')
            id = decode_access_token(token)

            user = User.objects.get(pk=id)
            return (user, None)

        raise exceptions.AuthenticationFailed("Unauthenticated")

any help will be appreciated, Thanks

if there something unclear in my question please comment below

1 Answers

you could edit userAPI middleware this way

class JWTAuthentication(BaseAuthentication):

    def authenticate(self, request):
        if request.COOKIES['access_token']:
            id = decode_access_token(request.COOKIES['access_token'])
            user = User.objects.get(pk=id)
            return (user, None)

        raise exceptions.AuthenticationFailed("Unauthenticated")

hope it will work, just be sure you are passing the cookies in the request

Related