vbv/server/vbv_lernwelt/files/mixins.py

76 lines
2.1 KiB
Python

from importlib import import_module
from typing import TYPE_CHECKING, Sequence, Type
from django.conf import settings
from django.contrib import auth
from rest_framework.authentication import BaseAuthentication, SessionAuthentication
from rest_framework.permissions import BasePermission, IsAuthenticated
def get_auth_header(headers):
value = headers.get("Authorization")
if not value:
return None
auth_type, auth_value = value.split()[:2]
return auth_type, auth_value
class SessionAsHeaderAuthentication(BaseAuthentication):
"""
In case we are dealing with issues like Safari not supporting SameSite=None,
And the client passes the session as Authorization header:
Authorization: Session <session_key>
Run the standard Django auth & try obtaining user.
"""
def authenticate(self, request):
auth_header = get_auth_header(request.headers)
if auth_header is None:
return None
auth_type, auth_value = auth_header
if auth_type != "Session":
return None
engine = import_module(settings.SESSION_ENGINE)
SessionStore = engine.SessionStore
session_key = auth_value
request.session = SessionStore(session_key)
user = auth.get_user(request)
return user, None
class CsrfExemptedSessionAuthentication(SessionAuthentication):
"""
DRF SessionAuthentication is enforcing CSRF, which may be problematic.
That's why we want to make sure we are exempting any kind of CSRF checks for APIs.
"""
def enforce_csrf(self, request):
return
if TYPE_CHECKING:
# This is going to be resolved in the stub library
# https://github.com/typeddjango/djangorestframework-stubs/
from rest_framework.permissions import _PermissionClass
PermissionClassesType = Sequence[_PermissionClass]
else:
PermissionClassesType = Sequence[Type[BasePermission]]
class ApiAuthMixin:
authentication_classes: Sequence[Type[BaseAuthentication]] = [
CsrfExemptedSessionAuthentication,
SessionAsHeaderAuthentication,
]
permission_classes: PermissionClassesType = (IsAuthenticated,)