I use django rest_framework_simplejwt package to generate JWT tokens and set them in browsable cookie with Httponly flag. At the Django side it work perfectly but at react side it does not work perfectly. I read many answers related to this question like this and this but they have not solved my problem yet. Please help me understand where I'm wrong.
DJANGO SIDE
views.py
from rest_framework_simplejwt.views import TokenObtainPairView
from django.conf import settings
from rest_framework import status
from rest_framework_simplejwt.exceptions import TokenError,\
InvalidToken
from rest_framework.response import Response
class MyTokenObtainPairView(TokenObtainPairView):
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
try:
serializer.is_valid(raise_exception=True)
except TokenError as e:
raise InvalidToken(e.args[0])
# set access token in browser with Httponly cookie.
res = Response(serializer.validated_data, status=status.HTTP_200_OK)
access_token = serializer.validated_data['access']
res.set_cookie("access_token", access_token, max_age=settings.SIMPLE_JWT.get('ACCESS_TOKEN_LIFETIME').total_seconds(),samesite='Lax',secure=False, httponly=True)
return res
authentication.py
from rest_framework_simplejwt.authentication import JWTAuthentication
from django.conf import settings
class CookieHandlerJWTAuthentication(JWTAuthentication):
def authenticate(self, request):
# If cookie contains access token, put it inside authorization header
access_token = request.COOKIES.get('access_token')
if(access_token):
request.META['HTTP_AUTHORIZATION'] = '{header_type} {access_token}'.format(
header_type=settings.SIMPLE_JWT['AUTH_HEADER_TYPES'][0], access_token=access_token)
return super().authenticate(request)
urls.py
from .views import MyTokenObtainPairView
urlpatterns = [
......
path('auth/', include('djoser.urls')),
# path('auth/', include('djoser.urls.jwt')),
path('auth/api/token/', MyTokenObtainPairView.as_view(), name='token_obtain_pair'),
]
settings.py
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_WHITELIST = (
'http://localhost:3000',
'http://127.0.0.1:8000'
)
Work perfectly(Token set in cookie with Httponly.):
REACTJS SIDE
Login.js
axios.defaults.withCredentials = true
const Login = () => {
const [ivalue, setValue] = useState({});
const { state, dispatch } = useContext(Authcontext);
.......
const loginClick = (e) => {
e.preventDefault();
setLoader(true);
axios.post('http://127.0.0.1:8000/auth/api/token/', {
username: ivalue.username,
password: ivalue.password,
})
.then((res) => {
setValue({ password: "" });
dispatch({
type: LOGIN_SUCCESS,
});
setLoader(false);
history.push("/my_profile");
})
.catch((err) => {
setLoader(false);
setOpen({ act: true, msg: "error" });
dispatch({
type: LOGIN_ERROR,
});
setError(err.response.data);
});
};
.........
};
Myprofile.js
axios.defaults.withCredentials = true
const MyProfile = () => {
const history = useHistory();
const { state, dispatch } = useContext(Authcontext);
useEffect(() => {
const auth_check = () => {
axios.get('http://127.0.0.1:8000/auth/users/me/')
.then((res) => {
dispatch({
type: AFTER_LOGIN,
payload: res.data
});
})
.catch((err) => {
history.push('/login')
});
};
auth_check();
}, []);
}
.......