import secrets from django.contrib.auth import get_user_model from django.test import TestCase from .models import ApiToken, UserProfile class ApiTokenAuthTests(TestCase): """Credential auth: 'Authorization: Bearer '.""" def setUp(self): User = get_user_model() self.alice = User.objects.create_user(username='Alice', password='pw') UserProfile.objects.get_or_create(user=self.alice) self.bob = User.objects.create_user(username='Bob', password='pw') UserProfile.objects.get_or_create(user=self.bob) self.token = secrets.token_urlsafe(48) ApiToken.objects.create( user=self.alice, token=self.token, key_prefix=self.token[:8], label='test', ) def _auth(self, credential=None, username=None, token=None): if credential is None: credential = f'{username or ""} {token or ""}'.strip() return self.client.get( '/home/', HTTP_AUTHORIZATION=f'Bearer {credential}', HTTP_ACCEPT='application/json', ) def test_valid_credentials_pass(self): resp = self._auth(username='Alice', token=self.token) self.assertEqual(resp.status_code, 200) def test_wrong_username_rejected(self): # A valid token presented under another user's name must not work. resp = self._auth(username='Bob', token=self.token) self.assertEqual(resp.status_code, 401) def test_wrong_token_rejected(self): resp = self._auth(username='Alice', token='x' * 64) self.assertEqual(resp.status_code, 401) def test_revoked_token_rejected(self): ApiToken.objects.all().delete() resp = self._auth(username='Alice', token=self.token) self.assertEqual(resp.status_code, 401) def test_missing_username_rejected(self): resp = self._auth(token=self.token) self.assertEqual(resp.status_code, 401) def test_missing_credentials_rejected(self): resp = self._auth() self.assertEqual(resp.status_code, 401) def test_username_case_insensitive(self): resp = self._auth(username='aLiCe', token=self.token) self.assertEqual(resp.status_code, 200) def test_unknown_user_rejected(self): resp = self._auth(username='Nobody', token=self.token) self.assertEqual(resp.status_code, 401) def test_authenticates_as_owner(self): self.client.get( '/home/', HTTP_AUTHORIZATION=f'Bearer Alice {self.token}', HTTP_ACCEPT='application/json', ) token = ApiToken.objects.get(token=self.token) self.assertIsNotNone(token.last_used)