65 lines
3.2 KiB
Python
65 lines
3.2 KiB
Python
"""Regression coverage for opt-in persistent sessions and explicit logout."""
|
|
from django.contrib.auth import get_user_model
|
|
from django.test import TestCase
|
|
from rest_framework.test import APIClient
|
|
from rest_framework_simplejwt.tokens import RefreshToken
|
|
|
|
from .models import PersistentLoginSession
|
|
|
|
|
|
class PersistentLoginTests(TestCase):
|
|
def setUp(self):
|
|
self.user = get_user_model().objects.create_user(username='persistent-user', password='correct-secret-123')
|
|
self.client = APIClient()
|
|
|
|
def login(self):
|
|
response = self.client.post('/api/auth/login/', {
|
|
'username': 'persistent-user', 'password': 'correct-secret-123',
|
|
}, format='json')
|
|
self.assertEqual(response.status_code, 200, response.data)
|
|
return response.data
|
|
|
|
def test_refresh_is_persistent_without_an_expiration_date(self):
|
|
tokens = self.login()
|
|
session = PersistentLoginSession.objects.get(token_hash__isnull=False)
|
|
self.assertIsNone(session.revoked_at)
|
|
self.assertFalse(hasattr(session, 'expires_at'))
|
|
self.assertNotIn('.', tokens['refresh']) # opaque, not a time-limited JWT
|
|
for _ in range(3):
|
|
response = self.client.post('/api/auth/refresh/', {'refresh': tokens['refresh']}, format='json')
|
|
self.assertEqual(response.status_code, 200)
|
|
self.assertIn('access', response.data)
|
|
|
|
def test_logout_revokes_refresh_and_access(self):
|
|
tokens = self.login()
|
|
authenticated = APIClient()
|
|
authenticated.credentials(HTTP_AUTHORIZATION=f"Bearer {tokens['access']}")
|
|
self.assertEqual(authenticated.get('/api/auth/me/').status_code, 200)
|
|
self.assertEqual(self.client.post('/api/auth/logout/', {'refresh': tokens['refresh']}, format='json').status_code, 204)
|
|
self.assertEqual(self.client.post('/api/auth/refresh/', {'refresh': tokens['refresh']}, format='json').status_code, 401)
|
|
self.assertEqual(authenticated.get('/api/auth/me/').status_code, 401)
|
|
|
|
def test_password_change_invalidates_existing_session(self):
|
|
tokens = self.login()
|
|
self.user.set_password('different-secret-456')
|
|
self.user.save(update_fields=['password'])
|
|
self.assertEqual(self.client.post('/api/auth/refresh/', {'refresh': tokens['refresh']}, format='json').status_code, 401)
|
|
authenticated = APIClient()
|
|
authenticated.credentials(HTTP_AUTHORIZATION=f"Bearer {tokens['access']}")
|
|
self.assertEqual(authenticated.get('/api/auth/me/').status_code, 401)
|
|
|
|
def test_legacy_refresh_can_upgrade(self):
|
|
old_refresh = str(RefreshToken.for_user(self.user))
|
|
response = self.client.post('/api/auth/refresh/', {'refresh': old_refresh}, format='json')
|
|
self.assertEqual(response.status_code, 200, response.data)
|
|
self.assertIn('access', response.data)
|
|
self.assertIn('refresh', response.data)
|
|
self.assertNotIn('.', response.data['refresh'])
|
|
|
|
def test_invalid_credentials_never_create_a_session(self):
|
|
response = self.client.post('/api/auth/login/', {
|
|
'username': 'persistent-user', 'password': 'wrong',
|
|
}, format='json')
|
|
self.assertIn(response.status_code, (400, 401))
|
|
self.assertFalse(PersistentLoginSession.objects.exists())
|