1

I am migrating our Django code that uses djangorestframework-jwt to the latest version of djangorestframework-simplejwt(5.2.2) in Django 4.0.8. I am having an issue while trying to verify the token.

The issue is because of the fact that our pem file for retrieving public and private keys is hosted on an Amazon S3 bucket. The framework requires passing SIGNING_KEY and VERIFYING_KEY statically or using JWK_URL for dynamically injecting these keys. Is there a way to provide these keys dynamically without using JWK_URL?

The djangorestframework-jwt framework used to provide handlers for decoding (JWT_DECODE_HANDLER) and encoding (JWT_ENCODE_HANDLER) the JWT payload. The djangorestframework-simplejwt has built-in functions to decode/encode inside the TokenBackend class. I also see that TOKEN_BACKEND_CLASS is part of REMOVED_SETTINGS in api_settings. I am having difficulty trying to write a custom backend by overriding decode() and encode() functions. How can I accomplish this?

sandpat
  • 1,478
  • 12
  • 30

1 Answers1

1

You can achieve this by overriding your serializer in the following fashion.

from rest_framework_simplejwt.serializers import TokenVerifySerializer
from rest_framework_simplejwt.exceptions import (
    InvalidToken,
    AuthenticationFailed,
    TokenBackendError,
    TokenError
)
class MyTokenVerifySerializer(TokenVerifySerializer):
    """
    Check the veracity of an access token.
    """

    def validate(self, attrs):
        token = attrs['token']
    
        payload = {}
        # Decode Token 
        try:
            payload = jwt_decode_handler(token) # Your Decode handler
        except TokenBackendError:
            raise TokenError(_("Token is invalid or expired"))

        user = self.get_user(payload=payload)

        return {'token': token, 'user': user}

    def get_user(self, payload):
        """
        Attempts to find and return a user using the given validated token.
        """
        from rest_framework_simplejwt.settings import api_settings
        from django.contrib.auth import get_user_model
        from django.utils.translation import gettext_lazy as _

        try:
            user_id = payload[api_settings.USER_ID_CLAIM]
        except KeyError:
            raise InvalidToken(_("Token contained no recognizable user identification"))

        user_model = get_user_model()
        try:
            user = user_model.objects.get(**{api_settings.USER_ID_FIELD: user_id})
        except self.user_model.DoesNotExist:
            raise AuthenticationFailed(_("User not found"), code="user_not_found")

        if not user.is_active:
            raise AuthenticationFailed(_("User is inactive"), code="user_inactive")

        return user

Hope this helps! Cheers

Aadit Shah
  • 46
  • 3
  • 1
    Thanks, mate! This is what I wanted. I added a check_exp() function call after decoding the payload to validate if the token was still valid. – sandpat Feb 16 '23 at 01:04