mirror of
https://github.com/suitenumerique/people
synced 2026-04-25 17:15:13 +02:00
Used https://github.com/openfun/joanie as boilerplate, ran a few transformations with ChapGPT and adapted models and endpoints to fit to my current vision of the project.
63 lines
2.6 KiB
Python
63 lines
2.6 KiB
Python
"""Authentication for the People core app."""
|
|
from django.conf import settings
|
|
from django.contrib.auth import get_user_model
|
|
from django.utils.functional import SimpleLazyObject
|
|
from django.utils.module_loading import import_string
|
|
from django.utils.translation import get_supported_language_variant
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from drf_spectacular.authentication import SessionScheme, TokenScheme
|
|
from drf_spectacular.plumbing import build_bearer_security_scheme_object
|
|
from rest_framework import authentication
|
|
from rest_framework_simplejwt.authentication import JWTAuthentication
|
|
from rest_framework_simplejwt.exceptions import InvalidToken
|
|
|
|
|
|
class DelegatedJWTAuthentication(JWTAuthentication):
|
|
"""Override JWTAuthentication to create missing users on the fly."""
|
|
|
|
def get_user(self, validated_token):
|
|
"""
|
|
Return the user related to the given validated token, creating or updating it if necessary.
|
|
"""
|
|
get_user = import_string(settings.JWT_USER_GETTER)
|
|
return SimpleLazyObject(lambda: get_user(validated_token))
|
|
|
|
|
|
class OpenApiJWTAuthenticationExtension(TokenScheme):
|
|
"""Extension for specifying JWT authentication schemes."""
|
|
|
|
target_class = "core.authentication.DelegatedJWTAuthentication"
|
|
name = "DelegatedJWTAuthentication"
|
|
|
|
def get_security_definition(self, auto_schema):
|
|
"""Return the security definition for JWT authentication."""
|
|
return build_bearer_security_scheme_object(
|
|
header_name="Authorization",
|
|
token_prefix="Bearer", # noqa S106
|
|
)
|
|
|
|
|
|
class SessionAuthenticationWithAuthenticateHeader(authentication.SessionAuthentication):
|
|
"""
|
|
This class is needed, because REST Framework's default SessionAuthentication does
|
|
never return 401's, because they cannot fill the WWW-Authenticate header with a
|
|
valid value in the 401 response. As a result, we cannot distinguish calls that are
|
|
not unauthorized (401 unauthorized) and calls for which the user does not have
|
|
permission (403 forbidden).
|
|
See https://github.com/encode/django-rest-framework/issues/5968
|
|
|
|
We do set authenticate_header function in SessionAuthentication, so that a value
|
|
for the WWW-Authenticate header can be retrieved and the response code is
|
|
automatically set to 401 in case of unauthenticated requests.
|
|
"""
|
|
|
|
def authenticate_header(self, request):
|
|
return "Session"
|
|
|
|
|
|
class OpenApiSessionAuthenticationExtension(SessionScheme):
|
|
"""Extension for specifying session authentication schemes."""
|
|
|
|
target_class = "core.api.authentication.SessionAuthenticationWithAuthenticateHeader"
|