I've searched everywhere and here is what I found. I will try to explain the whole process from setting the cookie as well as retreiving the cookie. I know I am late, but like me, there must be other people trying to find an answer. Please correct me if I have done something wrong.
SETTING THE COOKIE
In the django documentations under project configurations, you will find a that they use TokenObtainPairView.as_view()
to obtain the token. We will modify the TokenObtainPairView
in a separate views file, call it MyTokenObtainPairView
and import it in. See code below.
# urls.py
from django.urls import path
from .views import MyTokenObtainPairView
urlpatterns = [
path("token/", MyTokenObtainPairView.as_view(), name="token_obtain_pair"),
]
# views.py
from rest_framework_simplejwt.views import TokenObtainPairView
class MyTokenObtainPairView(TokenObtainPairView):
def post(self, request, *args, **kwargs):
response = super().post(request, *args, **kwargs)
token = response.data["access"]
response.set_cookie("pick_a_name_you_like_for_the_cookie", token, httponly=True)
return response
You can test this in postman. Assuming you did this from the root and use localhost, the endpoint should be something like: http://localhost:8000/token/
. You should run a POST request with login credentials (usually username and password). Now, if you use postman, you should see that there is a cookie called pick_a_name_you_like_for_the_cookie
-> Read more (stack)
-> Read more (Documentation) - This is more for customizing the token claims.
-
RETREIVING TOKEN
By default the simplejwt will look in the header for the access token. Therefore, you will not be able to retreive user by using user = request.user
or add permissions such as permission_classes = [IsAuthenticated]
or @permission_classes([IsAuthenticated])
. See docs.
This is because the default authentication classes are set as:
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
)
}
We will need to copy and modify the JWTAuthentication class. Create a file in the root directory called whatever you want. In this case custom_auth.py
. Copy everything from rest_framework_simplejwt/authentication.py
. You will find this file by entering the virtual environment or going directly to where pip installed rest_framework_simplejwt.
Now, assuming you've copied everything, change the following codes in custom_auth.py
from:
from .exceptions import AuthenticationFailed, InvalidToken, TokenError
from .settings import api_settings
to
from rest_framework_simplejwt.exceptions import AuthenticationFailed, InvalidToken, TokenError
from rest_framework_simplejwt.settings import api_settings
Now inside the class called JWTAuthentication
you will need to change the authentication function to something like:
class JWTAuthentication(authentication.BaseAuthentication):
"""
An authentication plugin that authenticates requests through a JSON web
token provided in a request header.
"""
www_authenticate_realm = "api"
media_type = "application/json"
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.user_model = get_user_model()
def authenticate(self, request):
cookie = request.COOKIES.get("pick_a_name_you_like_for_the_cookie")
raw_token = cookie.encode(HTTP_HEADER_ENCODING)
validated_token = self.get_validated_token(raw_token)
return self.get_user(validated_token), validated_token
...
You should add some validations etc. as to what should be done if there is no cookie etc. Probably something like:
if cookie is None:
return None
Customize the errorhandling as you would like. Finally go back to settings.py and replace:
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
)
}
with:
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"custom_auth.JWTAuthentication",
)
}
Please let me know if I leave any vulnerabilities or if I could've done something different! :)
RefreshTokenGrant
from.rest_framework_simplejwt.tokens
hasRefreshToken
, did you mean that? Or is it a custom method? – Opus