77 lines
2.7 KiB
Python
77 lines
2.7 KiB
Python
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 <username> <token>'."""
|
|
|
|
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)
|