I built a Django Rest Framework API with Custom JWT Authentication which stores the access and refresh token inside the Cookies , in development everything is fine all are working but in production I deployed my api on pythonanywhere then I used next js for my frontend then I got a bug wherein when I login using google or facebook it actually work but after logging in my fb account or choosing google account it will not redirect to my authenticated page which is I tried to debug for almost 4 days guys , and also when I login to google chrome not using google or facebook but my credential it will redirect however when I logged out and refresh the page it will authenticated again , I mean the cookies are not deleted permanently when I logout using google chrome but in firefox its fine. Please help me with this guys
this is my views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from djoser.social.views import ProviderAuthView
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
TokenVerifyView,
)
from .models import UserAccount
from rest_framework.decorators import api_view
@api_view(['GET'])
def user_profile(request):
user = request.user
if user.is_authenticated:
data = {
'id': user.id,
'first_name': user.first_name,
'last_name': user.last_name,
'email': user.email,
}
return Response(data, status=status.HTTP_200_OK)
else:
return Response({'detail': 'User not authenticated'}, status=status.HTTP_401_UNAUTHORIZED)
# For Social Auth
class CustomProviderAuthView(ProviderAuthView):
def post (self, request, *args, **kwargs):
response = super().post(request, *args, **kwargs)
if response.status_code == 201:
access_token = response.data.get('access')
refresh_token = response.data.get('refresh')
response.set_cookie(
'access',
access_token,
max_age=settings.AUTH_COOKIE_MAX_AGE,
path=settings.AUTH_COOKIE_PATH,
secure=settings.AUTH_COOKIE_SECURE,
httponly=settings.AUTH_COOKIE_HTTP_ONLY,
samesite=settings.AUTH_COOKIE_SAMESITE
)
response.set_cookie(
'refresh',
refresh_token,
max_age=settings.AUTH_COOKIE_MAX_AGE,
path=settings.AUTH_COOKIE_PATH,
secure=settings.AUTH_COOKIE_SECURE,
httponly=settings.AUTH_COOKIE_HTTP_ONLY,
samesite=settings.AUTH_COOKIE_SAMESITE
)
return response
class CustomTokenObtainPairView(TokenObtainPairView):
def post(self, request, *args, **kwargs ):
response = super().post(request, *args, **kwargs)
if response.status_code == 200:
access_token = response.data.get('access')
refresh_token = response.data.get('refresh')
response.set_cookie(
'access',
access_token,
max_age=settings.AUTH_COOKIE_MAX_AGE,
path=settings.AUTH_COOKIE_PATH,
secure=settings.AUTH_COOKIE_SECURE,
httponly=settings.AUTH_COOKIE_HTTP_ONLY,
samesite=settings.AUTH_COOKIE_SAMESITE
)
response.set_cookie(
'refresh',
refresh_token,
max_age=settings.AUTH_COOKIE_MAX_AGE,
path=settings.AUTH_COOKIE_PATH,
secure=settings.AUTH_COOKIE_SECURE,
httponly=settings.AUTH_COOKIE_HTTP_ONLY,
samesite=settings.AUTH_COOKIE_SAMESITE
)
return response
class CustomTokenRefreshView(TokenRefreshView):
def post(self, request, *args, **kwargs):
refresh_token = request.COOKIES.get('refresh')
if refresh_token:
request.data['refresh'] = refresh_token
response = super().post(request, *args, **kwargs)
if response.status_code == 200:
access_token = response.data.get('access')
response.set_cookie(
'access',
access_token,
max_age=settings.AUTH_COOKIE_MAX_AGE,
path=settings.AUTH_COOKIE_PATH,
secure=settings.AUTH_COOKIE_SECURE,
httponly=settings.AUTH_COOKIE_HTTP_ONLY,
samesite=settings.AUTH_COOKIE_SAMESITE,
)
return response
class CustomTokenVerifyView(TokenVerifyView):
def post(self, request, *args, **kwargs):
access_token = request.COOKIES.get('access')
if access_token:
request.data['token'] = access_token
return super().post(request, *args, **kwargs)
class LogoutView(APIView):
def post(self , request, *args, **kwargs):
response = Response(status=status.HTTP_204_NO_CONTENT)
response.delete_cookie('access')
response.delete_cookie('refresh')
return response
model.py
from django.db import models
from django.contrib.auth.models import (
BaseUserManager,
AbstractBaseUser,
PermissionsMixin
)
from django.conf import settings
class UserAccountManager(BaseUserManager):
def create_user(self, email, password=None, **kwargs):
""" **kwargs meaning kay keyword arguments
same ra ang
def create_user(self, first_name, last_name, email, password=None):
sa naay kwargs
"""
if not email:
raise ValueError("Users must have an email address")
email = self.normalize_email(email)
# Gabuhaton sa normalized is e lowecase ang after sa @
# Ex. jieclarkm@GMAIL.COM => jieclarkm@gmail.com
email = email.lower()
# So e lowercase niya tanan from first to end of characters
user = self.model(
email=email,
**kwargs
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password=None, **kwargs):
user = self.create_user(
email,
password=password,
**kwargs
)
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class UserAccount(AbstractBaseUser, PermissionsMixin):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
email = models.EmailField(
unique=True,
max_length=255,
)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
objects = UserAccountManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name']
def __str__(self):
return self.email
authentication.py
from django.conf import settings
from rest_framework_simplejwt.authentication import JWTAuthentication
class CustomJWTAuthentication(JWTAuthentication):
def authenticate(self, request):
try:
header = self.get_header(request)
if header is None:
raw_token = request.COOKIES.get(settings.AUTH_COOKIE)
else:
raw_token = self.get_raw_token(header)
if raw_token is None:
return None
validated_token = self.get_validated_token(raw_token)
return self.get_user(validated_token), validated_token
except:
return None
auth cookie configuration in settings.py
AUTH_COOKIE = 'access'
AUTH_COOKIE_MAX_AGE = 60 * 60 * 24
AUTH_COOKIE_SECURE = getenv('AUTH_COOKIE_SECURE', 'True') == 'True'
AUTH_COOKIE_HTTP_ONLY = True
AUTH_COOKIE_PATH = "/"
AUTH_COOKIE_SAMESITE = 'Lax'