from typing import Optional from django.http import HttpRequest from ninja.security import HttpBearer, django_auth from accounts.models import ApiToken class TokenAuth(HttpBearer): """`Authorization: Bearer ` — how the Flutter app authenticates.""" def authenticate(self, request: HttpRequest, token: str) -> Optional[ApiToken]: try: api_token = ApiToken.objects.select_related("user").get(key=token) except ApiToken.DoesNotExist: return None if not api_token.user.is_active: return None api_token.touch() # Downstream views read request.user, same as with session auth. request.user = api_token.user return api_token # Bearer first: a request carrying a token never reaches the cookie auth, which # would reject it for a missing CSRF token. AUTH = [TokenAuth(), django_auth]