86 lines
3.0 KiB
Python

import logging
from allauth.mfa.adapter import get_adapter as get_mfa_adapter
from django.conf import settings
from django.contrib import auth
from django.contrib.auth.middleware import PersistentRemoteUserMiddleware
from django.contrib.auth.models import User
from django.http import HttpRequest
from django.utils.deprecation import MiddlewareMixin
from rest_framework import authentication
from rest_framework import exceptions
logger = logging.getLogger("paperless.auth")
class AutoLoginMiddleware(MiddlewareMixin):
def process_request(self, request: HttpRequest):
# Dont use auto-login with token request
if request.path.startswith("/api/token/") and request.method == "POST":
return None
try:
request.user = User.objects.get(username=settings.AUTO_LOGIN_USERNAME)
auth.login(
request=request,
user=request.user,
backend="django.contrib.auth.backends.ModelBackend",
)
except User.DoesNotExist:
pass
class AngularApiAuthenticationOverride(authentication.BaseAuthentication):
"""This class is here to provide authentication to the angular dev server
during development. This is disabled in production.
"""
def authenticate(self, request):
if (
settings.DEBUG
and "Referer" in request.headers
and request.headers["Referer"].startswith("http://localhost:4200/")
):
user = User.objects.filter(is_staff=True).first()
logger.debug(f"Auto-Login with user {user}")
return (user, None)
else:
return None
class HttpRemoteUserMiddleware(PersistentRemoteUserMiddleware):
"""This class allows authentication via HTTP_REMOTE_USER which is set for
example by certain SSO applications.
"""
header = settings.HTTP_REMOTE_USER_HEADER_NAME
def process_request(self, request: HttpRequest) -> None:
# If remote user auth is enabled only for the frontend, not the API,
# then we need dont want to authenticate the user for API requests.
if (
"/api/" in request.path
and "paperless.auth.PaperlessRemoteUserAuthentication"
not in settings.REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"]
):
return
return super().process_request(request)
class PaperlessRemoteUserAuthentication(authentication.RemoteUserAuthentication):
"""
REMOTE_USER authentication for DRF which overrides the default header.
"""
header = settings.HTTP_REMOTE_USER_HEADER_NAME
class PaperlessBasicAuthentication(authentication.BasicAuthentication):
def authenticate(self, request):
user_tuple = super().authenticate(request)
user = user_tuple[0] if user_tuple else None
mfa_adapter = get_mfa_adapter()
if user and mfa_adapter.is_mfa_enabled(user):
raise exceptions.AuthenticationFailed("MFA required")
return user_tuple