from .models import ApiToken class ApiTokenAuthMiddleware: """Authenticates requests carrying `Authorization: Bearer ` 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)