feat: add OIDC browser sessions with live access enforcement
Some checks failed
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / pytest-smoke (push) Failing after 2s

Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0e747-8f27-7242-8df8-8bc44f88c929
This commit is contained in:
tegwick 2026-09-28 12:17:16 +02:00
parent fdea2f5192
commit a15fe032b0
14 changed files with 807 additions and 31 deletions

View file

@ -94,19 +94,22 @@ class OIDCVerifier:
except (httpx.HTTPError, ValueError, KeyError, TypeError, jwt.PyJWTError) as exc:
raise AccessFailure(503, "identity_unavailable") from exc
async def signing_key(self, token: str):
header = jwt.get_unverified_header(token)
if header.get("alg") != "RS256" or not isinstance(header.get("kid"), str):
raise ValueError("unsupported token")
async with self._lock:
age = time.monotonic() - self._loaded
if age >= self.key_ttl or (header["kid"] not in self._keys and age >= 1):
await self._refresh()
key = self._keys.get(header["kid"])
if key is None:
raise ValueError("unknown key")
return header, key
async def authenticate(self, token: str) -> Actor:
try:
header = jwt.get_unverified_header(token)
if header.get("alg") != "RS256" or not isinstance(header.get("kid"), str):
raise ValueError("unsupported token")
async with self._lock:
# At most one unknown-key refresh per second, to bound random-kid traffic.
age = time.monotonic() - self._loaded
if age >= self.key_ttl or (header["kid"] not in self._keys and age >= 1):
await self._refresh()
key = self._keys.get(header["kid"])
if key is None:
raise ValueError("unknown key")
header, key = await self.signing_key(token)
claims = jwt.decode(token, key, algorithms=["RS256"], issuer=self.issuer,
audience=self.audience, leeway=0,
options={"require": ["iss", "sub", "aud", "exp", "iat",