mirror of
https://github.com/Tivix/django-rest-auth.git
synced 2025-02-22 12:50:33 +03:00
Merge pull request #28 from mjlabe/logout-blacklist-jwt-token
Refresh token not blacklisted on logout
This commit is contained in:
commit
275d1c4952
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -72,6 +72,9 @@ target/
|
|||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IDE
|
||||
.idea
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
|
|
|
@ -44,7 +44,12 @@ REST_USE_JWT = True
|
|||
JWT_AUTH_COOKIE = 'jwt-auth'
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
To run the tests within a virtualenv, run `python runtests.py` from the repository directory.
|
||||
The easiest way to run test coverage is with [`coverage`](https://pypi.org/project/coverage/),
|
||||
which runs the tests against all supported Django installs. To run the test coverage
|
||||
within a virtualenv, run `coverage run ./runtests.py` from the repository directory then run `coverage report`.
|
||||
|
||||
|
||||
### Documentation
|
||||
|
|
|
@ -94,6 +94,8 @@ INSTALLED_APPS = [
|
|||
|
||||
'dj_rest_auth',
|
||||
'dj_rest_auth.registration',
|
||||
|
||||
'rest_framework_simplejwt.token_blacklist'
|
||||
]
|
||||
|
||||
SECRET_KEY = "38dh*skf8sjfhs287dh&^hd8&3hdg*j2&sd"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import json
|
||||
|
||||
from allauth.account import app_settings as account_app_settings
|
||||
from dj_rest_auth.registration.app_settings import register_permission_classes
|
||||
from dj_rest_auth.registration.views import RegisterView
|
||||
from django.conf import settings
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core import mail
|
||||
|
@ -9,6 +9,8 @@ from django.utils.encoding import force_text
|
|||
from rest_framework import status
|
||||
from rest_framework.test import APIRequestFactory
|
||||
|
||||
from dj_rest_auth.registration.app_settings import register_permission_classes
|
||||
from dj_rest_auth.registration.views import RegisterView
|
||||
from .mixins import CustomPermissionClass, TestsMixin
|
||||
|
||||
try:
|
||||
|
@ -555,3 +557,44 @@ class APIBasicTests(TestsMixin, TestCase):
|
|||
self.assertEqual(['jwt-auth'], list(resp.cookies.keys()))
|
||||
resp = self.get('/protected-view/')
|
||||
self.assertEquals(resp.status_code, 200)
|
||||
|
||||
@override_settings(REST_USE_JWT=True)
|
||||
def test_blacklisting_not_installed(self):
|
||||
settings.INSTALLED_APPS.remove('rest_framework_simplejwt.token_blacklist')
|
||||
payload = {
|
||||
"username": self.USERNAME,
|
||||
"password": self.PASS
|
||||
}
|
||||
get_user_model().objects.create_user(self.USERNAME, '', self.PASS)
|
||||
resp = self.post(self.login_url, data=payload, status_code=200)
|
||||
token = resp.data['refresh_token']
|
||||
resp = self.post(self.logout_url, status=200, data={'refresh': token})
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertEqual(resp.data["detail"],
|
||||
"Neither cookies or blacklist are enabled, so the token has not been deleted server side. "
|
||||
"Please make sure the token is deleted client side.")
|
||||
|
||||
@override_settings(REST_USE_JWT=True)
|
||||
def test_blacklisting(self):
|
||||
payload = {
|
||||
"username": self.USERNAME,
|
||||
"password": self.PASS
|
||||
}
|
||||
get_user_model().objects.create_user(self.USERNAME, '', self.PASS)
|
||||
resp = self.post(self.login_url, data=payload, status_code=200)
|
||||
token = resp.data['refresh_token']
|
||||
# test refresh token not included in request data
|
||||
resp = self.post(self.logout_url, status=200)
|
||||
self.assertEqual(resp.status_code, 401)
|
||||
# test token is invalid or expired
|
||||
resp = self.post(self.logout_url, status=200, data={'refresh': '1'})
|
||||
self.assertEqual(resp.status_code, 401)
|
||||
# test successful logout
|
||||
resp = self.post(self.logout_url, status=200, data={'refresh': token})
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
# test token is blacklisted
|
||||
resp = self.post(self.logout_url, status=200, data={'refresh': token})
|
||||
self.assertEqual(resp.status_code, 401)
|
||||
# test other TokenError, AttributeError, TypeError (invalid format)
|
||||
resp = self.post(self.logout_url, status=200, data=json.dumps({'refresh': token}))
|
||||
self.assertEqual(resp.status_code, 500)
|
||||
|
|
|
@ -11,6 +11,8 @@ from rest_framework.generics import GenericAPIView, RetrieveUpdateAPIView
|
|||
from rest_framework.permissions import AllowAny, IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework_simplejwt.exceptions import TokenError
|
||||
from rest_framework_simplejwt.tokens import RefreshToken
|
||||
|
||||
from .app_settings import (JWTSerializer, LoginSerializer,
|
||||
PasswordChangeSerializer,
|
||||
|
@ -132,15 +134,48 @@ class LogoutView(APIView):
|
|||
request.user.auth_token.delete()
|
||||
except (AttributeError, ObjectDoesNotExist):
|
||||
pass
|
||||
|
||||
if getattr(settings, 'REST_SESSION_LOGIN', True):
|
||||
django_logout(request)
|
||||
|
||||
response = Response({"detail": _("Successfully logged out.")},
|
||||
status=status.HTTP_200_OK)
|
||||
|
||||
if getattr(settings, 'REST_USE_JWT', False):
|
||||
cookie_name = getattr(settings, 'JWT_AUTH_COOKIE', None)
|
||||
if cookie_name:
|
||||
response.delete_cookie(cookie_name)
|
||||
|
||||
elif 'rest_framework_simplejwt.token_blacklist' in settings.INSTALLED_APPS:
|
||||
# add refresh token to blacklist
|
||||
try:
|
||||
token = RefreshToken(request.data['refresh'])
|
||||
token.blacklist()
|
||||
|
||||
except KeyError:
|
||||
response = Response({"detail": _("Refresh token was not included in request data.")},
|
||||
status=status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
except (TokenError, AttributeError, TypeError) as error:
|
||||
if hasattr(error, 'args'):
|
||||
if 'Token is blacklisted' in error.args or 'Token is invalid or expired' in error.args:
|
||||
response = Response({"detail": _(error.args[0])},
|
||||
status=status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
else:
|
||||
response = Response({"detail": _("An error has occurred.")},
|
||||
status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
else:
|
||||
response = Response({"detail": _("An error has occurred.")},
|
||||
status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
else:
|
||||
response = Response({
|
||||
"detail": _("Neither cookies or blacklist are enabled, so the token has not been deleted server "
|
||||
"side. Please make sure the token is deleted client side."
|
||||
)}, status=status.HTTP_200_OK)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user