Adafruit_CircuitPython_HTTP.../adafruit_httpserver/authentication.py
2025-05-16 16:11:43 +00:00

80 lines
2 KiB
Python

# SPDX-FileCopyrightText: Copyright (c) 2023 Michał Pokusa
#
# SPDX-License-Identifier: MIT
"""
`adafruit_httpserver.authentication`
====================================================
* Author(s): Michał Pokusa
"""
try:
from typing import List, Union
except ImportError:
pass
from binascii import b2a_base64
from .exceptions import AuthenticationError
from .request import Request
class Basic:
"""Represents HTTP Basic Authentication."""
def __init__(self, username: str, password: str) -> None:
self._value = b2a_base64(f"{username}:{password}".encode()).decode().strip()
def __str__(self) -> str:
return f"Basic {self._value}"
class Token:
"""Represents HTTP Token Authentication."""
prefix = "Token"
def __init__(self, token: str) -> None:
self._value = token
def __str__(self) -> str:
return f"{self.prefix} {self._value}"
class Bearer(Token):
"""Represents HTTP Bearer Token Authentication."""
prefix = "Bearer"
def check_authentication(request: Request, auths: List[Union[Basic, Token, Bearer]]) -> bool:
"""
Returns ``True`` if request is authorized by any of the authentications, ``False`` otherwise.
Example::
check_authentication(request, [Basic("username", "password")])
"""
auth_header = request.headers.get_directive("Authorization")
if auth_header is None:
return False
return any(auth_header == str(auth) for auth in auths)
def require_authentication(request: Request, auths: List[Union[Basic, Token, Bearer]]) -> None:
"""
Checks if the request is authorized and raises ``AuthenticationError`` if not.
If the error is not caught, the server will return ``401 Unauthorized``.
Example::
require_authentication(request, [Basic("username", "password")])
"""
if not check_authentication(request, auths):
raise AuthenticationError(
"Request is not authenticated by any of the provided authentications"
)