pythondjangojwt

How do I use JWT token authentication for API requests with rest_framework_simplejwt without needing user identification?


I have an API endpoint for my django application where I am allowing anyone with the JWT access token (valid for 15 mins) to use the API. But it doesn't work when I do a GET request with the access token. Authentication responds with "Token contained no recognizable user identification". Since anyone should be allowed to access the API with the token, I don't need to check if it's valid for any particular user.

JWT is a requirement in the project to have stateless user authentication for other APIs.

What is the correct/standard way to avoid this? Do I need a custom class or is there any better method to implement token authentication for APIs?


Solution

  • I figured it out.

    Added two classes - Custom authentication and permission classes.

    AnonAuthentication Class. Just checks if the token is provided, if provided check if the token is valid.

    from rest_framework_simplejwt.exceptions import InvalidToken, TokenError
    from rest_framework_simplejwt.tokens import AccessToken
    from rest_framework.authentication import BaseAuthentication
    
    class AnonAuthentication(BaseAuthentication):
        def authenticate(self, request):
            auth_header = request.META.get('HTTP_AUTHORIZATION')
            if not auth_header:
                return None
    
            try:
                prefix, token = auth_header.split()
                if prefix.lower() != 'bearer':
                    return None
            except ValueError:
                return None
    
            try:
                validated_token = AccessToken(token)
                return (None, validated_token)
            except TokenError:
                raise InvalidToken('Token is invalid or expired')
    
        def authenticate_header(self, request):
            return 'Bearer realm="api"'
    

    A custom permission class only checks if the token is authorized or not.

    from rest_framework.permissions import BasePermission
    
    class IsAuthenticatedOrToken(BasePermission):
        def has_permission(self, request, view):
            return bool(request.auth)
    

    Example:

    class CustomAPIListView(generics.ListAPIView):
        queryset = CustomModel.objects.all()
        permission_classes = [IsAuthenticatedOrToken] 
        authentication_classes = [AnonAuthentication]
        ...