Django-Rest-Framework(DRF)로JWT 기반 Authentication 세팅하기(with simplejwt) — 초기 환경 세팅(1)

Chanjong Park
Chan’s Programming Diary
8 min readApr 12, 2021

앞서 포스팅했던 소셜 로그인 구현에서 생각보다 많은 개발자 분들이 봐주신 덕분에 상위노출도 되어 기뻤지만, 이전 코드를 다시 보니 많이 부족하단 생각이 들었다. 특히 JWT 부분에서 이해력이 부족해 제대로 활용하지 못한 부분이 제일 아쉬웠다.

그래서 이번 포스팅을 작성하면서 DRF 환경에서 어떻게 JWT를 적용해서 인증을 하는지, 어떠한 패키지들을 사용하는지 최근에 공부한 내용들을 정리하고 최종적으로 소셜 로그인에 적용할 수 있도록 하는 것이 목표이다.

DRF에서의 인증 (Built-in Token, JWT)

간단하게 짚고 넘어가자면 DRF에서 사용하는 인증 방법은 크게 세가지로, Session, Token, JWT이다. 각각 모두 장단점이 있는데, 스택오버플로우에 마침 이 둘을 비교하는 글이 있었다.

차이점을 정리하자면 Built-in Token은 하나의 토큰으로 모든 세션을 관리하고, time stamp가 없기 때문에 따로 Custom을 하거나 DB에서 직접 삭제하지 않는 이상 영구적이다.

그에 비해 JWT(Json Web Token)는 세션 하나에 토큰 하나가 발급되며, time stamp가 있어 영구적이지 않고 언젠가 만료된다.

또한 JWT에서는 로그인 시 access token, refresh token이 같이 발급되며 access token이 만료되면 refresh token을 통해 새로운 access token을 요청할 수 있다.(그래서 보통 access token보다 refresh token의 만료기간이 훨씬 길다)

초기환경 세팅

JWT 기반 인증을 해야하기 때문에 simplejwt 패키지를 설치해준다.

pip install djangorestframework
pip install djangorestframework-simplejwt
pip install django-allauth
pip install dj-rest-auth

django에서 대표적으로 jwt 패키지는 djangorestframework-jwt, djangorestframework-simplejwt가 있지만 전자는 업데이트가 더이상 진행되지 않아서 후자를 사용하는 것을 추천한다.

dj-rest-auth는 DRF에서 소셜 로그인 및 유저 관리 패키지에 대해서 알아본 사람이면 한번쯤 들어봤을 django-rest-auth에서 따로 fork된 패키지이다. django-rest-auth가 업데이트를 더이상 하지 않자 dj-rest-auth에서 개발을 진행하고 있다.

settings.py

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
#myapp
'accounts',
#django-rest-auth
'rest_framework',
'rest_framework_simplejwt.token_blacklist',
'dj_rest_auth',
'dj_rest_auth.registration',
#django-allauth
'allauth',
'allauth.account',
'allauth.socialaccount',
]AUTH_USER_MODEL = 'accounts.User'SITE_ID = 1

소셜 로그인과 같이 진행한 프로젝트에서 가져왔기 때문에, 필요치 않은 App도 있을 수 있다.

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

DEFAULT_PERMISSION_CLASSES는 API에 접근 시에 인증된 유저, 즉 헤더에 access token을 포함하여 유효한 유저만이 접근이 가능하는 것을 Default로 설정해준다.

공개해야 하는 몇몇 API들에게만 따로 설정을 해주되, 이렇게 기본으로 설정해주면 일일이 function에서 decorator든 class에서 permission_classes 변수든 설정할 필요가 없다.

ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_VERIFICATION = 'none'
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'REST_USE_JWT = Truefrom datetime import timedeltaSIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(hours=2),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
'ROTATE_REFRESH_TOKENS': False,
'BLACKLIST_AFTER_ROTATION': True,
}

그리고 마지막으로 User 모델 설정과 JWT 설정을 해준다. 필자는 User에서 username 필드를 사용하지 않고 email로 사용할 것이기 때문에 저렇게 설정을 했다. 또한 추가적으로 email 인증을 해야지 계정을 활성화시키는 방법이있는데, 여기서는 사용하지 않도록 한다. 여기를 참고해서 추가적으로 원하는 방법으로 설정할 수 있다.

SIMPLE_JWT에서는 access token, refresh token의 만료기간을 설정할 수 는데, timedelta 함수로 seconds, hours, minutes, days 단위로 설정할 수 있다. 또한 ROTATE_REFRESH_TOKENS는 Token 재발급 관련 설정이고, BLACKLIST_AFTER_ROTATION은 차후에 Blacklist 관련 설명할 때 다시 언급하겠다.

urls.py

from django.contrib import admin
from django.urls import path
from django.urls import include
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('dj_rest_auth.urls')),
path('accounts/', include('dj_rest_auth.registration.urls'))
path('accounts/', include('allauth.urls')),
path('accounts/', include('accounts.urls')),
]

user 관련해서 나는 accounts란 이름으로만들었다.

models.py

유저는 저번 포스팅과 마찬가지로 아래 링크를 참고해서 진행했다.

그리고 마이그레이션을 진행해준다.

python manage.py makemigrations
python manage.py migrate --run-syncdb
migrations 직후의 테이블이다. 필자는 MySQL을 사용했다.

여기까지 진행되었으면 실습 환경은 갖춰졌다. 다음 포스트에서 각각의 패키지 공식 문서를 참고하면서 자세히 알아보자.

--

--