M41: harden trust boundaries and delivery
MobilityOps acceptance / backend (push) Failing after 47s
MobilityOps acceptance / frontend (push) Successful in 29s
MobilityOps acceptance / e2e (push) Skipped

This commit is contained in:
NuklearRabbit
2026-08-21 17:06:59 +02:00
parent a830e8a2d0
commit 24dcb3494c
38 changed files with 699 additions and 113 deletions
+4 -3
View File
@@ -38,10 +38,11 @@ _login_limiter = (
def _client_key(request: Request) -> str:
# The API sits behind the web container's reverse proxy in every documented
# deployment; honour the first hop of X-Forwarded-For when present.
# deployment. The proxy appends/overwrites the socket peer as the final hop, so an
# attacker-controlled leading value must never select a fresh limiter bucket.
forwarded = request.headers.get("x-forwarded-for", "")
if forwarded:
return forwarded.split(",")[0].strip()
return forwarded.split(",")[-1].strip()
return request.client.host if request.client else "unknown"
@@ -143,7 +144,7 @@ def _allowed_oidc_email(email: str) -> bool:
def _resolve_oidc_user(db: Session, claims: dict[str, object]) -> User:
subject = str(claims.get("sub") or "").strip()
email = str(claims.get("email") or "").strip().lower()
if not subject or not email or claims.get("email_verified") is False:
if not subject or not email or claims.get("email_verified") is not True:
raise HTTPException(status_code=401, detail="Verified OIDC email and subject are required")
if not _allowed_oidc_email(email):
raise HTTPException(status_code=403, detail="Email domain is not allowed")