mirror of
https://github.com/narrrl/holy-flavor-rater.git
synced 2026-11-03 16:41:27 +01:00
73 lines
2.5 KiB
Python
73 lines
2.5 KiB
Python
"""httpOnly-cookie JWT auth.
|
|
|
|
Reads `access_token` from a cookie set by the login/refresh endpoints. Falls
|
|
back to the Authorization header for backwards compatibility during rollout —
|
|
strip the fallback once all clients use cookies.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from django.conf import settings
|
|
from drf_spectacular.extensions import OpenApiAuthenticationExtension
|
|
from rest_framework_simplejwt.authentication import JWTAuthentication
|
|
|
|
|
|
class CookieJWTAuthentication(JWTAuthentication):
|
|
def authenticate(self, request):
|
|
raw_token = request.COOKIES.get(settings.JWT_AUTH_COOKIE_ACCESS)
|
|
if raw_token is None:
|
|
return super().authenticate(request)
|
|
validated_token = self.get_validated_token(raw_token)
|
|
return self.get_user(validated_token), validated_token
|
|
|
|
|
|
class CookieJWTScheme(OpenApiAuthenticationExtension):
|
|
"""Make drf-spectacular treat CookieJWTAuthentication like the SimpleJWT scheme."""
|
|
|
|
target_class = "api.utils.cookie_auth.CookieJWTAuthentication"
|
|
name = "cookieAuth"
|
|
|
|
def get_security_definition(self, auto_schema): # type: ignore[no-untyped-def]
|
|
return {
|
|
"type": "apiKey",
|
|
"in": "cookie",
|
|
"name": settings.JWT_AUTH_COOKIE_ACCESS,
|
|
}
|
|
|
|
|
|
def set_jwt_cookies(response, access: str | None, refresh: str | None) -> None:
|
|
"""Attach access/refresh tokens to the response as httpOnly cookies."""
|
|
from datetime import timedelta
|
|
|
|
secure = settings.JWT_AUTH_COOKIE_SECURE
|
|
samesite = settings.JWT_AUTH_COOKIE_SAMESITE
|
|
path = settings.JWT_AUTH_COOKIE_PATH
|
|
|
|
if access:
|
|
access_lifetime: timedelta = settings.SIMPLE_JWT["ACCESS_TOKEN_LIFETIME"]
|
|
response.set_cookie(
|
|
settings.JWT_AUTH_COOKIE_ACCESS,
|
|
access,
|
|
max_age=int(access_lifetime.total_seconds()),
|
|
httponly=True,
|
|
secure=secure,
|
|
samesite=samesite,
|
|
path=path,
|
|
)
|
|
if refresh:
|
|
refresh_lifetime: timedelta = settings.SIMPLE_JWT["REFRESH_TOKEN_LIFETIME"]
|
|
response.set_cookie(
|
|
settings.JWT_AUTH_COOKIE_REFRESH,
|
|
refresh,
|
|
max_age=int(refresh_lifetime.total_seconds()),
|
|
httponly=True,
|
|
secure=secure,
|
|
samesite=samesite,
|
|
path=path,
|
|
)
|
|
|
|
|
|
def clear_jwt_cookies(response) -> None:
|
|
response.delete_cookie(settings.JWT_AUTH_COOKIE_ACCESS, path=settings.JWT_AUTH_COOKIE_PATH)
|
|
response.delete_cookie(settings.JWT_AUTH_COOKIE_REFRESH, path=settings.JWT_AUTH_COOKIE_PATH)
|