JWT (Json Web Token) 인증 개발 경험에 대해 적어 보려고 한다.
처음에 구현 했던 방식은
djangorestframework-jwt 를 사용 했었는데
https://pypi.org/project/djangorestframework-jwt/
(아마 DRF 에서 가장 많이 사용 할 걸?)
일단 Release History 를 보면 2017년이 마지막인걸 볼 수 있고,
개발이 다 끝나고 나서 약간의 문제점은 처음 username, password 를 통해 인증 받을 때,
토큰 (access_token) 하나만 보내준다.
그리고 나서 access_token 갱신 할 때, refresh_token 을 통해서 access_token 갱신을 해 줘야되는데
여기서 refresh_token 을 가지고 있지 않아서 access_token 갱신 타이밍에 대한..
문제점? 번거로움? 이 발생해서 다른 라이브러리를 찾아보게 되었다.
(사용 방법을 정확히 몰라서 그럴 수 도 있지만..)
djangorestframework-simplejwt
https://pypi.org/project/djangorestframework-simplejwt/
Release History 2021년 10월 (글 작성 기준)
라이브러리 사용 방법은 djangorestframework-jwt 와 비슷해 보였고 (거의 같다고 볼 수 있다)
처음 인증할때, access_token, refresh_token 둘 다 보내준다.
그래서 djangorestframework-simplejwt 로 선택하게 되었다.
도큐먼트에도 방법이 자세히 나와있지만, 간단하게 방법에 대해 소개하면
pip install
pip install djangorestframework-simplejwt
django settings.py
REST_FRAMEWORK = {
...
'DEFAULT_AUTHENTICATION_CLASSES': (
...
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
...
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': datetime.timedelta(minutes=60),
'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=14),
'SIGNING_KEY': 'SECRET',
'ALGORITHM': 'HS256',
'AUTH_HEADER_TYPES': ('JWT',),
}
Document 보고 Custom 할 수 있다.
필요한 부분을 선언해서 Custom 하면 된다.
django urls.py
...
from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
TokenVerifyView,
)
...
urlpatterns = [
...
path('jwt-token-auth/', TokenObtainPairView.as_view(), name="token_obtain_pair"),
path('jwt-token-auth/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
path('jwt-token-auth/verify/', TokenVerifyView.as_view(), name='token_verify'),
....
]
Go (Gin Framework) 언어로도 인증을 구현 했지만, DRF 는 정말 간단하게 할 수 있는것 같다.
(나중에 Go 언어 후기도 남길 예정)
urls.py 에 선언해준 url
http://~~~~/jwt-token-auth/
접속하면
username, password 입력을 할 수 있고, POST 요청 할 수 있는 화면이 보인다.
username, password 입력 시
access_token, refresh_token 두개 다 받아 올 수 있다.
http://~~~~/jwt-token-auth/refresh/
url 에 접속해서
refresh token 을 넣어 POST 요청을 보내면
이런식으로 access_token 을 갱신해준다.
simple jwt 덕분에 간단하게 구현 할 수 있어서.. 좋았고, 좋은 경험!
다른 jwt 라이브러리가 star 가 많다구 해두 simple jwt 쓰시길..
추가적으로 너무 기본적인 것만 쓴 것 같아서
JWT 구현하면서 삽질?? 했던 이야기를 잠깐하면..
JWT 인증 자체를 한 가지의 서비스에서 하면 문제 될 만한 것이 사실상 별로 없다.
그런데 같은 KEY 를 공유하면서 여러 서비스 그러니까 통합 인증 같은 곳에서
JWT 토큰을 발급받고 사용하면 조금씩 문제가 있을수 있다.
내가 겪었던 문제 중 하나는 token_type 에 관한 simple jwt settings 의 기본값이다.
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
통합 인증 (JWT 토큰 발급) -> 서비스(simple jwt 사용) 로
인증을 할 때 token_type 이 맞지 않아서 문제가 생겼는데
" 뭐지.. token_type??? " 이런 생각으로 반나절은 찾아 봤던것 같다.
simple jwt 내장 함수 일부인데, 저런식으로 토큰타입을 확인을 한다.
def verify_token_type(self):
"""
Ensures that the token type claim is present and has the correct value.
"""
try:
token_type = self.payload[api_settings.TOKEN_TYPE_CLAIM]
except KeyError:
raise TokenError(_("Token has no type"))
if self.token_type != token_type:
raise TokenError(_("Token has wrong type"))
기본적으로 rest_framework_simplejwt.tokens.AccessToken 가
default 이기 때문에, 또 다른 내장 함수를 확인하면
class AccessToken(Token):
token_type = "access"
lifetime = api_settings.ACCESS_TOKEN_LIFETIME
simple jwt 에서 토큰 발급을 받을 때는
access_token 의 token_type 이 "access" 로 저장 된다.
그런데 통합인증 에서 발급받는 토큰에는 token_type 이 라는것이
존재하지 않아 발생하는 문제였던 것 이다.
(계속.. postman 에 Token has no type, Token has wrong type ..)
해결 방법은..
default 값을 UntypedToken 으로 바꾸면 해결 된다.
// settings.py
// rest_framework_simplejwt.tokens.AccessToken
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.UntypedToken',),
token_type = 'untyped'
token_type 확인을 하지 않는다.
이렇게 해서 token_type 에 관한 인증 부분은 해결 되었고..
또 다른 부분들도 이런문제가 있긴 했었는데.. 비슷한 방법으로 찾아서 해결 했다.
지금은 전부 잘 해결되어 JWT 를 잘 사용하고 있다.
끝 !
'Framework > Django' 카테고리의 다른 글
[Django] models cached_property decorator (0) | 2022.02.23 |
---|---|
[Django] models property decorator (@property) (0) | 2022.02.23 |
[Django] Ratelimit (django-ratelimit) (0) | 2022.02.17 |
[Django] auto_now , auto_now_add (0) | 2022.02.11 |
[Django] You are trying to add the field '필드명' ... (auto_now_add) (0) | 2022.02.11 |