diora-web/accounts/middleware.py
mrwnslz 77d662a9cb
All checks were successful
Build and push Docker image / build (push) Successful in 18s
Test / test (push) Successful in 1m36s
API-Token: Anfragen mit Bearer-Token brauchen kein CSRF-Token
Native Clients (diora desktop) haben kein CSRF-Cookie; ein Browser hängt den
Authorization-Header nie von selbst an, daher ist das sicher. Nötig z. B. für
den M3U-Import, der nicht csrf_exempt ist.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 19:33:18 +02:00

30 lines
1.5 KiB
Python

from .models import ApiToken
class ApiTokenAuthMiddleware:
"""Authenticates requests carrying `Authorization: Bearer <token>` as the
owning user, for local/native clients that can't hold a Django session.
Must run after AuthenticationMiddleware. Leaves request.user untouched
(AnonymousUser) on missing/invalid tokens — existing view-level auth
checks (`_require_auth`, `login_required`, `is_authenticated`) already
handle that case with a 401/redirect, so there's nothing to do here."""
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if not request.user.is_authenticated:
auth = request.META.get('HTTP_AUTHORIZATION', '')
if auth.startswith('Bearer '):
token = auth[len('Bearer '):].strip()
if token:
api_token = ApiToken.objects.select_related('user').filter(token=token).first()
if api_token is not None:
request.user = api_token.user
# Browsers never attach this header on their own, so a
# token request can't be a cross-site forgery; native
# clients have no CSRF cookie to send. (CsrfViewMiddleware
# checks this flag in process_view, which runs after us.)
request._dont_enforce_csrf_checks = True
return self.get_response(request)