authentik/passbook/api/auth.py

44 lines
1.6 KiB
Python

"""API Authentication"""
from base64 import b64decode
from typing import Any, Tuple, Union
from django.utils.translation import gettext as _
from rest_framework import HTTP_HEADER_ENCODING, exceptions
from rest_framework.authentication import BaseAuthentication, get_authorization_header
from rest_framework.request import Request
from passbook.core.models import Token, TokenIntents, User
class PassbookTokenAuthentication(BaseAuthentication):
"""Token-based authentication using HTTP Basic authentication"""
def authenticate(self, request: Request) -> Union[Tuple[User, Any], None]:
"""Token-based authentication using HTTP Basic authentication"""
auth = get_authorization_header(request).split()
if not auth or auth[0].lower() != b"basic":
return None
if len(auth) == 1:
msg = _("Invalid basic header. No credentials provided.")
raise exceptions.AuthenticationFailed(msg)
if len(auth) > 2:
msg = _(
"Invalid basic header. Credentials string should not contain spaces."
)
raise exceptions.AuthenticationFailed(msg)
header_data = b64decode(auth[1]).decode(HTTP_HEADER_ENCODING).partition(":")
tokens = Token.filter_not_expired(
token_uuid=header_data[2], intent=TokenIntents.INTENT_API
)
if not tokens.exists():
raise exceptions.AuthenticationFailed(_("Invalid token."))
return (tokens.first().user, None)
def authenticate_header(self, request: Request) -> str:
return 'Basic realm="passbook"'