본문 바로가기
부트캠프TIL, WIL/AI웹개발(스파르타코딩클럽)

[AI웹개발][55일차TIL] Django 에서 Simple-JWT(Json Web Token) 토큰 인증 방식 적용하기

by 우지uz 2023. 6. 3.

Simple JWT 공식문서

 

Getting started — Simple JWT 5.2.2.post19+gaa077a4 documentation

Cryptographic Dependencies (Optional) If you are planning on encoding or decoding tokens using certain digital signature algorithms (i.e. RSA and ECDSA; visit PyJWT for other algorithms), you will need to install the cryptography library. This can be insta

django-rest-framework-simplejwt.readthedocs.io

 

인증의 종류

1. 세션 인증 다시 살펴보기.

기본적으로 브라우저에서 사용자가 **인증(Authentication)**을 수행하면 서버에서는 사용자의 정보를 저장하고, 그 응답으로 JSESSIONID 라는 키를 이용해 클라이언트(사용자) 브라우저의 쿠키에 세션의 정보를 저장하게 됩니다.

이후 클라이언트는 브라우저 쿠키에 저장된 JSESSIONID 로 저장된 세션 정보를 이용해 **인가(Authrization)**된 정보에 접근할 수 있게 됩니다.

2. 토큰 인증 방식 알아보기.

토큰인증 방식은 사용자가 인증을 수행하면 서버에서는 토큰을 생성한 뒤에 저장하지 않고(stateless) 토큰값을 사용자의 브라우저에게 응답합니다.

이 토큰 값을 사용자가 인가된 사용자만 사용할 수 있는 서비스를 요청할 때 함께 보내게 되고, 서버에서 이 토큰을 의미 있는 값(보통은 사용자 정보)으로 해석하게 됩니다. 그리고 이 값으로 사용자를 인증하게 됩니다.

토큰은 username, user_id 등 사용자를 설명할 수 있는 데이터를 포함하게 됩니다. 참고로 이렇게 사용자를 설명할 수 있는 데이터를 클레임(claim) 이라고 합니다.


3. JWT(Json Web Token) 알아보기

토큰 인증 방식의 대표주자 입니다. JWT 토큰 구조는 HEADER.PAYLOAD.VERIFY_SIGNATURE 로 이루어져 있으며,
다음은 JWT 토큰의 예시 입니다. 각 데이터는 온점(.)으로 구분됩니다.



HEADER

HEADER 는 JWT를 검증하는데 필요한 정보를 가진 데이터입니다. VERIFY_SIGNATURE 에 사용한 암호화 알고리즘과 토큰 타입, key 의 id 등의 정보를 가지고 있습니다. 난해한 문자열처럼 보이지만 암호화된 값은 아닙니다.

PAYLOAD

실질적으로 인증에 필요한 데이터를 저장합니다. 데이터 각각의 필드를 클레임(claim) 이라고 하고, 대부분의 경우 클레임에 username 또는 user_id 를 포함합니다. 인증시에 payload에 있는 username을 가져와서 사용자의 정보를 인증할 때 사용해야 하기 때문입니다.

또한 payload에서 중요하게 살펴보아야 할 정보는 **토큰 발행시간(iat)**와 토큰 만료시간(exp) 입니다. 토큰의 만료 시간이 지나면 새로운 토큰을 발급받아야 합니다.

VERIFY SIGNATURE

header 와 payload 는 암호화 되지 않고 단순히 Json → UTF-8 → Base64 형식으로 변환된 데이터 입니다. 즉 header 와 payload 의 생성 자체는 너무 쉽고 누구나 만들 수 있는 데이터이죠.

따라서 저 두개의 데이터만 있다면 토큰에 대한 진위여부 판단은 이루어질수 없게 됩니다. 그래서 JWT의 구조에서 가장 마지막에 있는 VERIFY SIGNATURE 는 토큰 자체의 진위여부를 판단하는 용도로 사용합니다.

VERIFY SIGNATURE 는 Base64UrlEncoding 된 header 와 payload 의 정보를 합친 뒤 SECRET_KEY 를 이용하여 Hash 를 생성하여 암호화 합니다.

 


 

가상환경 설정 - 매우 중요!

python3 -m venv venv
# 현재 경로에 venv 파일 생성
source venv/bin/activate
# 가상환경을 활성화

django, djangorestframework를 한꺼번에 설치하려면

pip3 install djangorestframework

django, djangorestframework, djangorestframework-simplejwt 를 한꺼번에 설치하려면

pip3 install djangorestframework-simplejwt

 


 

JWT로 인증할 것 이기 때문에 settings.py에 
REST_FRAMEWORK의
DEFAULT_AUTHENTICATION_CLASSES을 작성해 줍니다.
디폴트 인증 클래스를 가리킵니다. 디폴트는 하나여야 합니다. 

# settings.py에 디폴트 인증 방식을 기재합니다. 디폴트 인증 방식은 하나 여야 합니다. 
'DEFAULT_AUTHENTICATION_CLASSES': [
		# JWT 인증 방식 추가하기
		'rest_framework_simplejwt.authentication.JWTAuthentication',
],

simplejwt 에서 제공하는 기본 JWT(Json Web Token) 인증을 사용할 것입니다. 

 


 

따라서 인증 토큰 발급 urlpatterns 에
토큰 발급 view , 토큰 리프레쉬 view 를 추가해 줍니다.

# user/urls.py

from rest_framework_simplejwt.views import (
    TokenObtainPairView,
    TokenRefreshView,
)

urlpatterns = [
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]

DRF- simplejwt 문서에서의 방식은 위와 같고 

# user/urls.py 저는 다음과 같이, 작성하였습니다. 

from django.urls import path
from user import views
from rest_framework_simplejwt.views import TokenRefreshView


urlpatterns = [
    path('login/', views.CustomTokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]

저는 그것을 나만의 경로로 설정해주었습니다. 

views는 바꿀 수 없지만, url 경로를 login/로 바꿀 순 있습니다. 


저는 토큰 페이로드에 account, email, username을 추가할 것이기 때문에
views.py 에 커스터마이징을 해주고, serializers.py 에 필드들을 추가해줄 것입니다.

views.py에 다음과 같이 TokenObtainPairView를 상속받아
CustomTokenObtainPairView로 커스터마이징을 해주면

CustomTokenObtainPairSerializer를 실행시키는 것을 볼 수 있습니다. 

# user 앱에, views.py 에 TokenObtainPairView를 상속받아, 커스텀합니다. 
from rest_framework_simplejwt.views import TokenObtainPairView

class CustomTokenObtainPairView(TokenObtainPairView):
    serializer_class = CustomTokenObtainPairSerializer

저는 기존의 페이로드에 있는 정보들 이외에
email, account, username을 추가적으로 사용할 것이기 때문에
다음과 같이 TokenObtainPairSerializer를 상속받아

토큰 정보들을 불러와 줍니다. 

# user앱의 serializers.py에 토큰을 얻어서 로그인하는 기능에 대한 시리얼라이저를 추가해줍니다.
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer


class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        token['email'] = user.email
        token['account'] = user.account
        token['username'] = user.username
        return token

 

실제로 access Token을 https://jwt.io/ 에 입력을해서 확인해보면,
추가적인 Payload Json Data들을 확인할 수 있습니다. 

 

JWT.IO

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.

jwt.io