Skip to content

Authentication

pysepal_api.auth

Auth providers for pysepal-api.

Three providers implement httpx.Auth:

  • ApiKeyAuth → HTTP Basic with empty user + sandbox key as password.
  • CookieAuthSEPAL-SESSIONID cookie for Solara/session-header flows.
  • NoAuth → explicitly disable pysepal-api auth (tests / mock servers).

detect_auth() resolves the sandbox credential from /var/run/sepal-api-key: mode="sandbox_file", or the default "auto", which means the same since that file is the only source. mode="none" disables auth.

SANDBOX_KEY_PATH module-attribute

SANDBOX_KEY_PATH = '/var/run/sepal-api-key'

AuthMode module-attribute

AuthMode = Literal['auto', 'sandbox_file', 'none']

ApiKeyAuth

ApiKeyAuth(api_key: str)

HTTP Basic auth with empty username + sandbox API key as password.

Source code in src/pysepal_api/auth.py
45
46
47
48
49
50
def __init__(self, api_key: str) -> None:
    if not api_key:
        raise ValueError("ApiKeyAuth requires a non-empty key")
    self._key = api_key
    token = base64.b64encode(f":{api_key}".encode()).decode()
    self._header = f"Basic {token}"

auth_flow

auth_flow(
    request: Request,
) -> Generator[httpx.Request, httpx.Response, None]
Source code in src/pysepal_api/auth.py
55
56
57
def auth_flow(self, request: httpx.Request) -> Generator[httpx.Request, httpx.Response, None]:
    request.headers["Authorization"] = self._header
    yield request

from_sandbox classmethod

from_sandbox(path: str = SANDBOX_KEY_PATH) -> 'ApiKeyAuth'
Source code in src/pysepal_api/auth.py
59
60
61
62
@classmethod
def from_sandbox(cls, path: str = SANDBOX_KEY_PATH) -> "ApiKeyAuth":
    text = Path(path).read_text().strip()
    return cls(text)

CookieAuth

CookieAuth(session_id: str)

SEPAL-SESSIONID cookie auth, used by the Solara container path.

Source code in src/pysepal_api/auth.py
68
69
70
71
def __init__(self, session_id: str) -> None:
    if not session_id:
        raise ValueError("CookieAuth requires a non-empty session id")
    self._session_id = session_id

auth_flow

auth_flow(
    request: Request,
) -> Generator[httpx.Request, httpx.Response, None]
Source code in src/pysepal_api/auth.py
76
77
78
79
80
def auth_flow(self, request: httpx.Request) -> Generator[httpx.Request, httpx.Response, None]:
    existing = request.headers.get("Cookie", "")
    cookie = f"SEPAL-SESSIONID={self._session_id}"
    request.headers["Cookie"] = f"{existing}; {cookie}" if existing else cookie
    yield request

NoAuth

Explicitly disable auth (tests, mock servers).

auth_flow

auth_flow(
    request: Request,
) -> Generator[httpx.Request, httpx.Response, None]
Source code in src/pysepal_api/auth.py
86
87
def auth_flow(self, request: httpx.Request) -> Generator[httpx.Request, httpx.Response, None]:
    yield request

detect_auth

detect_auth(
    *,
    mode: AuthMode = "auto",
    sandbox_path: str = SANDBOX_KEY_PATH
) -> httpx.Auth

Build an auth provider for the sandbox credential.

mode="none" disables auth. mode="sandbox_file" reads sandbox_path, and mode="auto" (the default) does the same — the two are separate spellings of one behaviour because there is only one credential source to find. Raises NoCredentialsError when the key file is missing or empty.

Source code in src/pysepal_api/auth.py
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
def detect_auth(
    *,
    mode: AuthMode = "auto",
    sandbox_path: str = SANDBOX_KEY_PATH,
) -> httpx.Auth:
    """Build an auth provider for the sandbox credential.

    ``mode="none"`` disables auth. ``mode="sandbox_file"`` reads
    ``sandbox_path``, and ``mode="auto"`` (the default) does the same — the
    two are separate spellings of one behaviour because there is only one
    credential source to find. Raises `NoCredentialsError` when the key file is
    missing or empty.
    """
    _validate_auth_mode(mode)
    if mode == "none":
        return NoAuth()
    return _api_key_from_file(sandbox_path)