From 53e66ef78007c6c704578b75e8624675f1134615 Mon Sep 17 00:00:00 2001 From: Armin Ster Date: Sun, 15 Oct 2023 18:43:10 +0200 Subject: [PATCH] feat: add cookie authentication --- CHANGELOG.md | 3 +-- drf_anonymous_login/authentication.py | 6 +++++- drf_anonymous_login/views.py | 4 +++- tests/testapp/tests/test_api.py | 21 ++++++++++++++++++++- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7663742..71f9c2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Mixin for User to provide properties `is_anonymous_login` and `anonymous_login` +- Cookie authentication support ## [1.1.0] @@ -16,8 +17,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.0.0] -## [1.0.0] - ### Added - Initial setup diff --git a/drf_anonymous_login/authentication.py b/drf_anonymous_login/authentication.py index 3d28a75..4ac407e 100644 --- a/drf_anonymous_login/authentication.py +++ b/drf_anonymous_login/authentication.py @@ -7,13 +7,17 @@ AUTH_KEYWORD = "Token" AUTH_HEADER = "HTTP_X_AUTHORIZATION_ANONYMOUS" +AUTH_COOKIE = "anonymous_token" class AnonymousLoginAuthentication(authentication.BaseAuthentication): keyword = AUTH_KEYWORD def authenticate(self, request): - auth = request.META.get(AUTH_HEADER, "").split() + auth = ( + request.META.get(AUTH_HEADER, "").split() + or request.COOKIES.get(AUTH_COOKIE, "").split() + ) if not auth or auth[0].lower() != self.keyword.lower(): return None diff --git a/drf_anonymous_login/views.py b/drf_anonymous_login/views.py index 2f5a08b..f1798cf 100644 --- a/drf_anonymous_login/views.py +++ b/drf_anonymous_login/views.py @@ -43,7 +43,9 @@ def create(self, request, *args, **kwargs): "headers": self.extract_request_headers(request), } ) - return Response({"token": user.token}, status=status.HTTP_201_CREATED) + response = Response({"token": user.token}, status=status.HTTP_201_CREATED) + response.set_cookie("anonymous_token", f"Token {user.token}") + return response class AnonymousLoginAuthenticationModelViewSet(viewsets.ModelViewSet): diff --git a/tests/testapp/tests/test_api.py b/tests/testapp/tests/test_api.py index 48da10b..fa71d96 100644 --- a/tests/testapp/tests/test_api.py +++ b/tests/testapp/tests/test_api.py @@ -3,7 +3,7 @@ from django.test import TestCase from django.urls import reverse from django.utils import timezone -from rest_framework.status import HTTP_200_OK, HTTP_403_FORBIDDEN +from rest_framework.status import HTTP_200_OK, HTTP_201_CREATED, HTTP_403_FORBIDDEN from testapp.models import PrivateModel, PublicModel, User from drf_anonymous_login.authentication import AUTH_HEADER, AUTH_KEYWORD @@ -139,3 +139,22 @@ def test_user_get_no_anonymous_login(self): """ user = User.objects.create(username="user", password="password") self.assertIsNone(user.anonymous_login) + + def test_anonymous_login_with_cookie_authentication(self): + """ + Assert that cookie authentication works + :return: + """ + # create anonymous login and check if cookie is set + url = reverse("auth_anonymous-list") + response = self.client.post(url) + self.assertEqual(HTTP_201_CREATED, response.status_code) + self.assertEqual( + response.cookies["anonymous_token"].value, f"Token {response.data['token']}" + ) + + # set cookies and make sure it works + url = reverse("privatemodel-list") + self.client.cookies.load({"anonymous_token": f"Token {response.data['token']}"}) + response = self.client.get(url) + self.assertEqual(HTTP_200_OK, response.status_code)