LoginSignup
0
0

More than 3 years have passed since last update.

Django Rest Authでjwt token generatorをsimplejwtに変えてみた。

Last updated at Posted at 2020-09-12

djangorestframework-jwtを使わない理由

理由としては大きく2つがありました。

  • 理由1:もうサポートしてない。(2017年が最後のrelease.)
    • securityに問題が発生する。(CVE-2018-0114など。)
  • 理由2:refresh_tokenとaccess_tokenを同時に得られない。
    • これがきっかけ

Django-simplejwtは access_tokenとrefresh_tokenを同時得られる。

djangorestframework-jwt → djangorestframework-simplejwt

まず、djangorestframework-simplejwtからinstallする。

pip install djangorestframework-simplejwt

django-rest-authのdirectory構造。このファイルのうち直すファイルはutils.py

├── __init__.py
├── __init__.pyc
├── __pycache__
│   ├── __init__.cpython-38.pyc
│   ├── admin.cpython-38.pyc
│   ├── app_settings.cpython-38.pyc
│   ├── models.cpython-38.pyc
│   ├── serializers.cpython-38.pyc
│   ├── social_serializers.cpython-38.pyc
│   ├── urls.cpython-38.pyc
│   ├── utils.cpython-38.pyc
│   └── views.cpython-38.pyc
├── admin.py
├── admin.pyc
├── app_settings.py
├── app_settings.pyc
├── locale
│   ├── cs
│   │   └── LC_MESSAGES
│   │       ├── django.mo
│   │       └── django.po
│   ├── de
│   │   └── LC_MESSAGES
│   │       ├── django.mo
│   │       └── django.po
│   ├── es
│   │   └── LC_MESSAGES
│   │       ├── django.mo
│   │       └── django.po
│   ├── ko
│   │   └── LC_MESSAGES
│   │       ├── django.mo
│   │       └── django.po
│   ├── pl
│   │   └── LC_MESSAGES
│   │       ├── django.mo
│   │       └── django.po
│   ├── ru
│   │   └── LC_MESSAGES
│   │       ├── django.mo
│   │       └── django.po
│   ├── tr
│   │   └── LC_MESSAGES
│   │       └── django.po
│   ├── zh_Hans
│   │   └── LC_MESSAGES
│   │       ├── django.mo
│   │       └── django.po
│   └── zh_Hant
│       └── LC_MESSAGES
│           ├── django.mo
│           └── django.po
├── models.py
├── models.pyc
├── registration
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── __pycache__
│   │   ├── __init__.cpython-38.pyc
│   │   ├── app_settings.cpython-38.pyc
│   │   ├── serializers.cpython-38.pyc
│   │   ├── urls.cpython-38.pyc
│   │   └── views.cpython-38.pyc
│   ├── app_settings.py
│   ├── app_settings.pyc
│   ├── serializers.py
│   ├── serializers.pyc
│   ├── urls.py
│   ├── urls.pyc
│   ├── views.py
│   └── views.pyc
├── serializers.py
├── serializers.pyc
├── social_serializers.py
├── social_serializers.pyc
├── tests
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── __pycache__
│   │   ├── __init__.cpython-38.pyc
│   │   ├── django_urls.cpython-38.pyc
│   │   ├── mixins.cpython-38.pyc
│   │   ├── settings.cpython-38.pyc
│   │   ├── test_api.cpython-38.pyc
│   │   ├── test_social.cpython-38.pyc
│   │   └── urls.cpython-38.pyc
│   ├── django_urls.py
│   ├── django_urls.pyc
│   ├── mixins.py
│   ├── mixins.pyc
│   ├── requirements.pip
│   ├── settings.py
│   ├── settings.pyc
│   ├── test_api.py
│   ├── test_api.pyc
│   ├── test_base.pyc
│   ├── test_social.py
│   ├── test_social.pyc
│   ├── urls.py
│   └── urls.pyc
├── urls.py
├── urls.pyc
├── utils.py #<ーーこれ
├── utils.pyc
├── views.py
└── views.pyc

utils.pyの中を見ると、jwt_encodeって書いてある関数があってその中は次のようになっていてこのコードを下のコードに変える。

(https://django-rest-framework-simplejwt.readthedocs.io/en/latest/creating_tokens_manually.html)

def jwt_encode(user):
    try:
        from rest_framework_jwt.settings import api_settings 
    except ImportError:
        raise ImportError("rest_framework_simplejwt needs to be installed")

    jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
    jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

    payload = jwt_payload_handler(user)
    return jwt_encode_handler(payload)

def jwt_encode(user):
    try:
        # from rest_framework_jwt.settings import api_settings <-- old version.
        from rest_framework_simplejwt.tokens import RefreshToken
    except ImportError:
        raise ImportError("rest_framework_simplejwt needs to be installed")

    # jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
    # jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

    # payload = jwt_payload_handler(user)
    refresh = RefreshToken.for_user(user)
    payload = {'refresh' : str(refresh), 'access': str(refresh.access_token)}
    return payload

その後、serializers.pyのコードも下のように直す。

class JWTSerializer(serializers.Serializer):
    """
    Serializer for JWT authentication.
    """
    token = serializers.CharField()
    user = serializers.SerializerMethodField()

    def get_user(self, obj):
        """
        Required to allow using custom USER_DETAILS_SERIALIZER in
        JWTSerializer. Defining it here to avoid circular imports
        """
        rest_auth_serializers = getattr(settings, 'REST_AUTH_SERIALIZERS', {})
        JWTUserDetailsSerializer = import_callable(
            rest_auth_serializers.get('USER_DETAILS_SERIALIZER', UserDetailsSerializer)
        )
        user_data = JWTUserDetailsSerializer(obj['user'], context=self.context).data
        return user_data

class JWTSerializer(serializers.Serializer):
    """
    Serializer for JWT authentication.
    """
    token = serializers.JSONField()
    user = serializers.SerializerMethodField()

    def get_user(self, obj):
        """
        Required to allow using custom USER_DETAILS_SERIALIZER in
        JWTSerializer. Defining it here to avoid circular imports
        """
        rest_auth_serializers = getattr(settings, 'REST_AUTH_SERIALIZERS', {})
        JWTUserDetailsSerializer = import_callable(
            rest_auth_serializers.get('USER_DETAILS_SERIALIZER', UserDetailsSerializer)
        )
        user_data = JWTUserDetailsSerializer(obj['user'], context=self.context).data
        return user_data

Before & After

Before

{
  "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyLCJ1c2VybmFtZSI6InVzZXIiLCJleHAiOjE1OTk5MzQ0NDYsImVtYWlsIjoiIn0.ddZRKpU76x66dkJVh0SEP3FZL1HHLv8XJqvaf8OEd5o",
  "user": {
    "pk": 2,
    "username": "user",
    "email": "",
    "first_name": "",
    "last_name": ""
  }
}

After

{
  "token": {
    "refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTYwMDAyMDYzMSwianRpIjoiNTEwNzhlZmU4MGY2NDNiYjkyYmUyMTlkMDc5OWM1ZTIiLCJ1c2VyX2lkIjoyfQ.eGzYcmAD5e7Oi_DnN9N0j0iMswiCnBc8Qwoeltnlhos",
    "access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTk5OTM0NTMxLCJqdGkiOiI1ZTA1N2U5NThlM2I0NDgzODA4ZDkyNWFlODljMTMzYyIsInVzZXJfaWQiOjJ9.OFX7jYeco6uNK_WenOdO5jKJkN-RwMiwFZa1zhusoUA"
  },
  "user": {
    "pk": 2,
    "username": "user",
    "email": "",
    "first_name": "",
    "last_name": ""
  }
}

確認した結果、dj-rest-authって言う新しいpackageがあるらしいのでdj-rest-authを使ってください。
こちらは、simple-jwtを使ってます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0