KeykoYume
KeykoYume

Reputation: 2645

Django Rest Framework JWT Auth

I have an issue posting/getting any requests after JWT login. (I am using the djangorestframework-jwt library) The user succesfully logs in, the app returns the json token but when I use this token for the next requests I get

{
    "detail": "Authentication credentials were not provided."
}

settings.py

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}

JWT_AUTH = {
    'JWT_ALLOW_REFRESH': True,
    'JWT_EXPIRATION_DELTA': datetime.timedelta(hours=1),
    'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
}

Login View

def post(self, request, format=None):

    if not request.data:
        return Response({'Error': "Please provide username/password"},  status=status.HTTP_400_BAD_REQUEST)

    username = request.data['username']
    password = request.data['password']

    try:
        user = User.objects.get(email=username, password=password)
    except User.DoesNotExist:
        return Response({'Error': "Invalid username/password"}, status=status.HTTP_400_BAD_REQUEST)

    if user:
        payload = {
            'id': user.id,
            'email': user.email,
            'first_name': user.first_name
        }

        jwt_token = jwt.encode(payload, "SECRET_KEY")  # to be changed

        return Response({'token': jwt_token}, status=status.HTTP_200_OK)

and then every other view contains

 authentication_class = (JSONWebTokenAuthentication,)
 permission_classes = (IsAuthenticated,)

I have tested both with postman and curl but I get the same error. Not sure if there is an error with the header format or if there is smth else I'm missing. Any help would be greatly appreciated!

enter image description here

EDIT: I have changed my settings to

'DEFAULT_AUTHENTICATION_CLASSES': (
    'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    'rest_framework.authentication.SessionAuthentication',
    'rest_framework.authentication.BasicAuthentication',
),

but now I get that

{
    "detail": "Error decoding signature."
}

EDIT: I think the issue is that jwt_token = jwt.encode(payload, 'SECRET_KEY') might return a token that is not recognised...if i use the token generated by obtain_jwt_token then i can query any endpoint. Could anyone explain this?

EDIT: so I changed to jwt_token = jwt_encode_handler(payload) and the settings file contains the JWT_SECRET_KEY (when i verify the token i receive after login on jwt, it is indeed the right token with the right payload and secret) but it's still not recognised "detail": "Invalid signature."

Upvotes: 1

Views: 2569

Answers (2)

KeykoYume
KeykoYume

Reputation: 2645

I managed to solve my problem. When authenticating a user I was checking against a custom user table that I had created earlier, which was different from the django's auth_user table. I changed django's settings to use my custom users table and then using the token from the authentication worked for the other requests as well.

AUTH_USER_MODEL = 'main.User'

Upvotes: 1

a_k_v
a_k_v

Reputation: 1608

The problem is you encode the JWT by using "SECRET KEY" and decode using another key. The default secret key used by jwt is settings.SECRET_KEY. But when you create a custom jwt token you uses a string as secret "SECRET_KEY". But you use default jwt verification which automatically uses settings.SECRET_KEY. So add 'JWT_SECRET_KEY': settings.SECRET_KEY, in to your JWT settings and use this key for encode and decode. Ex:

jwt_token = jwt.encode(payload, settings.SECRET_KEY)

or you can override the jwt verification and create your own.

Upvotes: -1

Related Questions