Skip to content

Commit

Permalink
bug-1910092: Add Vary: Auth-Token header for requests with a token.
Browse files Browse the repository at this point in the history
  • Loading branch information
smarnach committed Sep 12, 2024
1 parent 5cc5457 commit 89a81f5
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 14 deletions.
2 changes: 2 additions & 0 deletions tecken/tests/test_tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def test_client_homepage_with_valid_token(client):
assert response.status_code == 200
assert "sign_in_url" not in response.json()["user"]
assert response.json()["user"]["email"] == user.email
assert response.headers.get("Vary").lower() == "auth-token"
user.refresh_from_db()
assert user.last_login

Expand All @@ -72,6 +73,7 @@ def test_client_homepage_with_valid_token(client):
assert response.status_code == 200
assert "sign_in_url" not in response.json()["user"]
assert response.json()["user"]["email"] == user.email
assert response.headers.get("Vary").lower() == "auth-token"
user.refresh_from_db()
assert user.last_login

Expand Down
28 changes: 14 additions & 14 deletions tecken/tokens/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from django.conf import settings
from django.contrib.auth.signals import user_logged_in
from django.core.exceptions import MiddlewareNotUsed, PermissionDenied
from django.utils.cache import patch_vary_headers

from .models import Token

Expand All @@ -21,16 +22,23 @@ def has_perm(all, codename, obj=None):


class APITokenAuthenticationMiddleware:
def __init__(self, get_response=None):
def __init__(self, get_response):
if not settings.ENABLE_TOKENS_AUTHENTICATION: # pragma: no cover
logger.warning("API Token authentication disabled")
raise MiddlewareNotUsed
self.get_response = get_response

def __call__(self, request):
response = self.process_request(request)
if not response:
response = self.get_response(request)
key = request.headers.get("Auth-Token")
if key:
try:
self.authenticate(request, key)
except PermissionDenied:
self.force_full_request_body_read(request)
raise
response = self.get_response(request)
if key:
patch_vary_headers(response, ["Auth-Token"])
return response

def force_full_request_body_read(self, request):
Expand All @@ -56,28 +64,20 @@ def force_full_request_body_read(self, request):
except Exception as exc:
logging.info("force_full_request_body_read: exception thrown: %r", exc)

def process_request(self, request):
key = request.META.get("HTTP_AUTH_TOKEN")
if not key:
return

def authenticate(self, request, key):
# Auth tokens allow for a "comment" which is anything after the first "-";
# peel it off and ignore it
if "-" in key:
key = key.split("-", 1)[0]
key = key.partition("-")[0]

try:
token = Token.objects.select_related("user").get(key=key)
if token.is_expired:
self.force_full_request_body_read(request)
raise PermissionDenied("API Token found but expired")
except Token.DoesNotExist as exc:
self.force_full_request_body_read(request)
raise PermissionDenied("API Token not matched") from exc

user = token.user
if not user.is_active:
self.force_full_request_body_read(request)
raise PermissionDenied("API Token matched but user not active")

# Overwrite the has_perm method so that it's restricted to only
Expand Down

0 comments on commit 89a81f5

Please sign in to comment.