I am using rest_framework_simplejwt
to authenticate my users but, in some views i need to ignore it, because these are public views. i want to check the token into view flow. The expected behaviour is:
In public view
Actually rest_framework_simplejwt
checks token and raise 401
if token is invalid or expired...
I tried disabling authentication_classes
within APIView like this:
class SpecificProductApi(APIView):
def get_authenticators(self):
if self.request.method == 'GET':
self.authentication_classes = []
return super(SpecificProductApi, self).get_authenticators()
but if i disable it before enter GET APIView
method, i can't do if reques.user.is_authenticated:
because I disabled the token :(
Exists a way to enable entering to api http method and check users manually into view? thanks
And these are all provided by drf(django rest framework) and other than these like oauth, oauth2 based authentication are provided by the efforts of the community with help of other python packages. And they can be easily used in the production environment.
Simple JWT provides a JSON Web Token authentication backend for the Django REST Framework. It aims to cover the most common use cases of JWTs by offering a conservative set of default features. It also aims to be easily extensible in case a desired feature is not present.
After verifying the credentials, the server issues two JSON Web Tokens to the user. One of them is an Access Token and the other is a Refresh Token. The frontend of your application then stores the tokens securely and sends the Access Token in the Authorization header of all requests it then sends to the server.
I get it done by adding authentication_classes = []
from rest_framework import permissions
class SpecificProductApi(APIView):
permission_classes = [permissions.AllowAny]
authentication_classes = []
You could simply use authentication_classes = []
in the view, but this always bypasses the JWT authentication, even when a valid Authorization-header with the token is present. You'd better extend the JWTAuthentication-class as follows (similar to the comment of Jhon Edwin Sanz Gonzalez):
from rest_framework_simplejwt.authentication import JWTAuthentication
from rest_framework_simplejwt.exceptions import InvalidToken
class JWTAuthenticationSafe(JWTAuthentication):
def authenticate(self, request):
try:
return super().authenticate(request=request)
except InvalidToken:
return None
Then use authentication_classes = [JWTAuthenticationSafe]
in your view.
Have a very similar problem. To create public endpoints you are forced to override the authenticators, or else you will return 401/403 on expired/missing token.
However, a public endpoint does not mean that it should not have authentication. Rather it should have one response for no-auth / expired-auth and another for valid auth.
I don't know if this is the "correct" way, but this is what I came up with facing the same problem.
Override the authenticators as you have done, and add an additional method to validate the authenticators in your view.
For example:
class SomeApiView(APIView):
def get_authenticators(self):
# Override standard view authenticators.
# Public endpoint, no auth is enforced.
return []
def get_auth(self):
# Return a generator of all authenticators.
return (auth() for auth in self.authentication_classes)
def get_auth_detail(self, request):
# Evaluate each authenticator and return the first valid authentication.
for auth in self.get_auth():
# You probably need try / except here to catch authenticators
# that are invalid (403/401) in the case of multiple authentication
# classes--such as token auth, session auth, etc...
auth_detail = auth.authenticate(request)
if auth_detail:
return auth_detail
return None, None
def post(self, request):
# Returns a tuple of (User, JWT), can be (None, None)
user, jwt = self.get_auth_detail(request)
# Do your magic based on user value.
if user:
# User is authenticated.
else:
# User is anon / not-authenticated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With