I've been using djangorestframework-simplejwt
for a while and now I want to store the JWT in the cookies (instead of localstorage or front-end states) so that every request that the client makes, contains the token.
So did some research on it and the most relevant result I found was this stackoverflow question, in which the author is using djangorestframework-jwt
package which has a pre-configured setting for cookies called JWT_AUTH_COOKIE
. So figured switching to that package but then ended up finding out that the package is pretty much dead.
Although there is a fork for the djangorestframework-jwt
that is recommended to use instead, I was wondering is there anyway to set the JWTs in HttpOnly cookies with the djagnorestframework_simplejwt
itself?
With httponly cookie flag and CSRF protection follow this code.
Both side very useful in mobile app and webapp..
urls.py:
...
path('login/',LoginView.as_view(),name = "login"),
...
view.py:
from rest_framework_simplejwt.tokens import RefreshToken
from django.middleware import csrf
def get_tokens_for_user(user):
refresh = RefreshToken.for_user(user)
return {
'refresh': str(refresh),
'access': str(refresh.access_token),
}
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)
email_template = render_to_string('login_success.html',{"username":user.username})
login = EmailMultiAlternatives(
"Successfully Login",
"Successfully Login",
settings.EMAIL_HOST_USER,
[user.email],
)
login.attach_alternative(email_template, 'text/html')
login.send()
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)
authenticate.py:
from rest_framework_simplejwt.authentication import JWTAuthentication
from django.conf import settings
from rest_framework.authentication import CSRFCheck
from rest_framework import exceptions
def enforce_csrf(request):
"""
Enforce CSRF validation.
"""
check = CSRFCheck()
# populates request.META['CSRF_COOKIE'], which is used in process_view()
check.process_request(request)
reason = check.process_view(request, None, (), {})
if reason:
# CSRF failed, bail with explicit error message
raise exceptions.PermissionDenied('CSRF Failed: %s' % reason)
class CustomAuthentication(JWTAuthentication):
def authenticate(self, request):
header = self.get_header(request)
if header is None:
raw_token = request.COOKIES.get(settings.SIMPLE_JWT['AUTH_COOKIE']) or None
else:
raw_token = self.get_raw_token(header)
if raw_token is None:
return None
validated_token = self.get_validated_token(raw_token)
enforce_csrf(request)
return self.get_user(validated_token), validated_token
settings.py:
....
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'authentication.authenticate.CustomAuthentication',
),
}
SIMPLE_JWT = {
.....
'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.
}
By using middleware.py:
How to authenticate by using middleware
Must :
withCredentials is True from both side..
Any doubt please comment..