Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'str' object has no attribute 'decode' on djangorestframework_simplejwt

I was trying to follow this quick start from djangorestframework-simplejwt documentation with link https://django-rest-framework-simplejwt.readthedocs.io/en/latest/getting_started.html

But I have problem when try to obtain token, and always return this error 'str' object has no attribute 'decode'

enter image description here

Edited: This my code on urls.py

from django.contrib import admin
from django.urls import path
from rest_framework_simplejwt import views as jwt_views
from core.views import HelloView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/token/', jwt_views.TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', jwt_views.TokenRefreshView.as_view(), name='token_refresh'),
    path('hello/', HelloView.as_view(), name='hello'),
]

settings.py

...
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
]
...
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
}
...

views.py

from django.shortcuts import render

# Create your views here.
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated


class HelloView(APIView):
    permission_classes = (IsAuthenticated,)

    def get(self, request):
        content = {'message': 'Hello, World!'}
        return Response(content)
like image 925
Mas Dimas Avatar asked Apr 14 '21 10:04

Mas Dimas


4 Answers

Downgrading PyJWT did the job for me.

To achieve that, change the corresponding line in your requirements.txt to

PyJWT==v1.7.1

or install the specified package with:

pip install pyjwt==v1.7.1
like image 96
btzs Avatar answered Nov 10 '22 01:11

btzs


for me let downgrade jwt to version 1.7.1

to do that update corresponding line requirement.txt or if not PyJWT line than add this line

PyJWT==v1.7.1
like image 20
ketan Avatar answered Nov 10 '22 00:11

ketan


Remove .decode('utf-8') in "/venv/lib/python3.9/site-packages/rest_framework_jwt/utils.py" like

# /venv/lib/python3.9/site-packages/rest_framework_jwt/utils.py
def jwt_encode_handler(payload):
key = api_settings.JWT_PRIVATE_KEY or jwt_get_secret_key(payload)
return jwt.encode(
    payload,
    key,
    api_settings.JWT_ALGORITHM
)#.decode('utf-8') ==> delete this

jwt2.3.0-utils-encode_handler

As you installed simple-jwt, jwt has been upgraded to version-2.3.0 from 1.7.1(maybe). and by this,

jwt2.3.0-api_jwt-encode

"-> str:" has been added at the method "encode", and this means "encode" returns "str".

so we don't need .decode('utf-8') anymore in utils.py in rest_framework_jwt.

and if you run server again you may encounter the problem below.

except jwt.ExpiredSignature: rest_framework.request.WrappedAttributeError: module 'jwt' has no attribute 'ExpiredSignature'

you can fix this as below,

# /venv/lib/python3.9/site-packages/rest_framework_jwt/authentication.py
try:
    payload = jwt_decode_handler(jwt_value)
except jwt.ExpiredSignatureError: # ExpiredSignature => no more exists
    msg = _('Signature has expired.')
    raise exceptions.AuthenticationFailed(msg)
except jwt.DecodeError:
    msg = _('Error decoding signature.')
    raise exceptions.AuthenticationFailed(msg)

jwt2.3.0-authentication-except

this problem has occured because the jwt-version has been upgraded to 2.3.0, and ExpiredSignature doesn't exist anymore.

But we recommend you to downgrade jwt version to 1.7.1 as we don't know all the changes made by upgrade.

jwt2.3.0-init.py

jwt1.7.1-init.py

like image 42
hss Avatar answered Nov 10 '22 00:11

hss


I had PyJWT-2.3.0 installed and I was not even guessing if this issue could be related to the version.

The above answers helped me to crack this. So I am just writing the same thing with some extra log details.

pip install PyJWT==1.7.1

(venv) ip-192-168-1-36:django_proj rishi$ pip install PyJWT==1.7.1
Collecting PyJWT==1.7.1
  Using cached PyJWT-1.7.1-py2.py3-none-any.whl (18 kB)
Installing collected packages: PyJWT
  Attempting uninstall: PyJWT
    Found existing installation: PyJWT 2.3.0
    Uninstalling PyJWT-2.3.0:
      Successfully uninstalled PyJWT-2.3.0
Successfully installed PyJWT-1.7.1

Finally my problem got resolved. Thanks to the previous answers to help me on this.

like image 27
hygull Avatar answered Nov 09 '22 23:11

hygull