Coverage for src\baobab_web_api_caller\auth\basic_authentication_strategy.py: 93%
21 statements
« prev ^ index » next coverage.py v7.10.3, created at 2026-03-21 12:10 +0100
« prev ^ index » next coverage.py v7.10.3, created at 2026-03-21 12:10 +0100
1"""Stratégie Basic auth (Authorization: Basic <base64(user:pass)>)."""
3from __future__ import annotations
5import base64
6from dataclasses import dataclass
8from baobab_web_api_caller.auth.authentication_strategy import AuthenticationStrategy
9from baobab_web_api_caller.core.baobab_request import BaobabRequest
10from baobab_web_api_caller.exceptions.configuration_exception import ConfigurationException
13@dataclass(frozen=True, slots=True)
14class BasicAuthenticationStrategy(AuthenticationStrategy):
15 """Applique l'authentification HTTP Basic.
17 Notes de sécurité:
18 - Cette stratégie ne réalise pas de chiffrement. En production, l'usage doit se faire sur TLS.
19 - Les identifiants ne doivent pas être loggés.
21 :param username: Nom d'utilisateur.
22 :type username: str
23 :param password: Mot de passe.
24 :type password: str
25 :raises ConfigurationException: Si les paramètres sont invalides.
26 """
28 username: str
29 password: str
31 def __post_init__(self) -> None:
32 if not isinstance(self.username, str) or self.username.strip() == "":
33 raise ConfigurationException("username must be a non-empty string")
34 if not isinstance(self.password, str): 34 ↛ 35line 34 didn't jump to line 35 because the condition on line 34 was never true
35 raise ConfigurationException("password must be a string")
36 if ":" in self.username:
37 raise ConfigurationException("username must not contain ':'")
39 def apply(self, request: BaobabRequest) -> BaobabRequest:
40 """Ajoute/écrase ``Authorization`` avec l'en-tête Basic."""
42 raw = f"{self.username}:{self.password}".encode("utf-8")
43 token = base64.b64encode(raw).decode("ascii")
44 return request.with_header("Authorization", f"Basic {token}")