개발 기록

[Django] simple-jwt 로그아웃 Api + blacklist app 본문

Python/Django

[Django] simple-jwt 로그아웃 Api + blacklist app

수염차 2022. 4. 6. 13:08

simple-jwt에 블랙리스트라는 기능이 있어서 사용해보려고 한다

 

사용 이유

- 로그 아웃시 로컬 저장소에 저장한 토큰을 삭제하고 서버에서 블랙리스트에 넣어 무효화

- localStorage에서 액세스 토큰과 새로 고침 토큰을 모두 제거할 수 있더라도 refresh_token이 도난당했다면 다른 클라이언트가 해당 토큰을 무기한 계속 사용할 수 있다. 이를 방지하기 위해 클라이언트가 현재 refresh_token 또는 현재 사용자에게 할당된 모든 refresh_token을 무효화 가능

 

 

공식문서

https://django-rest-framework-simplejwt.readthedocs.io/en/latest/blacklist_app.html

 

Blacklist app — Simple JWT 5.1.0.post2+g3fc9110 documentation

Blacklist app Simple JWT includes an app that provides token blacklist functionality. To use this app, include it in your list of installed apps in settings.py: # Django project settings.py ... INSTALLED_APPS = ( ... 'rest_framework_simplejwt.token_blackli

django-rest-framework-simplejwt.readthedocs.io

여기는 설명이 부족해서 다른 블로그들을 보면서 흐름을 파악했다.

 

먼저 블랙리스트 기능 설정을 하고 마이그레이션을 하면 admin 페이지에 새로운 행이 생긴다 (토큰 블랙리스트)

# Django project settings.py

...

INSTALLED_APPS = (
    ...
    'rest_framework_simplejwt.token_blacklist',
    ...
)
SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(hours=2),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
    'TOKEN_USER_CLASS': 'accounts.User',
    'ROTATE_REFRESH_TOKENS': True,
    'BLACKLIST_AFTER_ROTATION': True,
}

ROTATE_REFRESH_TOKENS : True로 설정하면 TokenRefreshView 에 refresh token 이 제출되면 새 access token과 함께 새 refresh token이 반환됨

BLACKLIST_AFTER_ROTATION : True로 설정하면 Blacklist 앱이 사용 중이고 ROTATE_REFRESH_TOKENS 설정이 True로 설정된 경우 TokenRefreshView에 제출 된 refresh token이 블랙리스트에 추가됨

http://127.0.0.1:8000/admin/

Outstanding tokens - 로그인시 목록 생성

 

Blacklisted tokens - 토큰 갱신시 , 로그아웃시 기존 토큰이 저장됨  


 

로그아웃 JWT APIView 만들기

accounts/view.py

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

    def post(self, request, *args, **kwargs):
        if self.request.data.get('all'):
            token: OutstandingToken
            for token in OutstandingToken.objects.filter(user=request.user):
                _, _ = BlacklistedToken.objects.get_or_create(token=token)
            return Response({"status": "OK, goodbye, all refresh tokens blacklisted"})
        refresh_token = self.request.data.get('refresh_token')
        token = RefreshToken(token=refresh_token)
        token.blacklist()
        return Response({"status": "OK, goodbye"})

accounts/url.py

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

    path('logout/', LogoutView.as_view(), name='auth_logout')
]

로그아웃 과정

로그인 : 공식 문서 시작하기에 써있는 기본 경로 'api/token/' 으로 아이디와 비밀번호를 전송하면

access token과 refresh token이 발행된다

나는 login/으로 변경함

로그아웃

curl \
-X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjQ5MjIyMTYzLCJpYXQiOjE2NDkyMTQ5NjMsImp0aSI6IjQwZWI5NDliYWNjNjQ2Y2JhZTFjYzJhN2NmZTI1MmIxIiwidXNlcl9pZCI6MX0.Do2btkPJzwbr3A-WZt7CXcJGofyBVHSE1Cz6c7qHwaU" \
-d '{"refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTY0OTgxOTc2MywiaWF0IjoxNjQ5MjE0OTYzLCJqdGkiOiJlZjM0ODczNDMxN2Q0ZWZlYmZhYzg2YWRiMmExZjFjMiIsInVzZXJfaWQiOjF9.DEvAy54l_GfeTEmfdp-9FTDTvzainGa0P43p0BmXPIU"}' \
http://127.0.0.1:8000/user/logout/

헤더에 access token (인증이 필요하기 때문에) , 바디에 json 객체로 refresh token을 넣고 보내면 지정한 msg 출력

admin 페이지에 블랙리스트에 들어가 보면 refresh token 이 들어간 것을 볼 수 있다

가장 최근 로그인 토큰과 블랙리스트 토큰이 일치


++ refresh token으로 새로운 token 갱신

refresh token을 넣고 post를 누르면 새로운 access token과 refresh token 발행

-> 기존 refrehs token은 블랙리스트에 추가됨

 

유효하지 않거나 만료된 토큰을 넣었을 때

 

 

출처

https://appliku.com/post/how-use-jwt-authentication-django#testing-django-simplejwt-token_obtain_pair-endpoint

 

How to use JWT Authentication with Django – Appliku

 

appliku.com

https://ichi.pro/ko/jwt-logeu-aus-django-rest-peuleim-wokeu-258502600453429

 

JWT 로그 아웃 — Django Rest 프레임 워크

DRF로 제품 리뷰 백엔드 구축 — Part 10 JWT 인증을 사용할 때 클라이언트 측은 토큰을 저장하고 모든 요청에 ​​첨부합니다. 따라서 로그 아웃 할 때 가장 먼저해야 할 일은 로컬 저장소에 저장

ichi.pro

 

Comments