feat: DEBUG_AUTH_TOKEN Bypass fuer Diagnose-Sessions auf dev
Wenn ENV `DEBUG_AUTH_TOKEN` gesetzt ist, akzeptieren require_auth + require_admin einen Header `X-Debug-Token: <secret>` oder einen Query-Param `?__debug_token=<secret>` und liefern einen Admin-Mock- User. Jeder Use wird mit logger.warning protokolliert. Default: leer = inaktiv (auch in prod, weil prod-compose das nicht durchreicht). Damit kann ein Diagnose-Tool (Playwright, curl) ohne Keycloak-Login auf admin-only-Endpoints zugreifen — fuer Browser-Console-Auswertung bei UI-Bugs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
60db39d5b3
commit
f8cfa42d9f
40
app/auth.py
40
app/auth.py
@ -22,6 +22,7 @@ Usage in main.py:
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import time
|
||||
from typing import Optional
|
||||
|
||||
@ -97,6 +98,37 @@ def _extract_token(request: Request) -> Optional[str]:
|
||||
return request.cookies.get("access_token")
|
||||
|
||||
|
||||
def _check_debug_token(request: Request) -> Optional[dict]:
|
||||
"""Dev-Bypass: wenn ENV `DEBUG_AUTH_TOKEN` gesetzt ist und der Request
|
||||
den passenden Header `X-Debug-Token` trägt, liefert die Funktion einen
|
||||
Admin-Mock-User. Sonst None.
|
||||
|
||||
Default: leeres ENV → kein Bypass möglich, in prod inaktiv. Auf dev
|
||||
erlaubt es Diagnose-Sessions ohne Keycloak-Login. Jeder Use wird
|
||||
geloggt (warning), damit Bypass-Aktivität sichtbar bleibt.
|
||||
"""
|
||||
expected = (os.environ.get("DEBUG_AUTH_TOKEN") or "").strip()
|
||||
if not expected:
|
||||
return None
|
||||
presented = (request.headers.get("x-debug-token") or "").strip()
|
||||
# Auch via Query-Param erlauben — für einmaligen Zugriff im Browser
|
||||
if not presented:
|
||||
presented = (request.query_params.get("__debug_token") or "").strip()
|
||||
if presented and presented == expected:
|
||||
client = request.client.host if request.client else "?"
|
||||
logger.warning(
|
||||
"DEBUG_AUTH_TOKEN bypass active — request from %s to %s",
|
||||
client, request.url.path,
|
||||
)
|
||||
return {
|
||||
"sub": "debug-user",
|
||||
"email": "debug@local",
|
||||
"name": "Debug-User",
|
||||
"roles": ["admin", "gwoe-admin"],
|
||||
}
|
||||
return None
|
||||
|
||||
|
||||
async def _validate_token(token: str) -> Optional[dict]:
|
||||
"""Validiere JWT gegen Keycloak-JWKS. Returns Payload oder None."""
|
||||
try:
|
||||
@ -170,6 +202,10 @@ async def get_current_user(request: Request) -> Optional[dict]:
|
||||
if not _is_auth_enabled():
|
||||
return None
|
||||
|
||||
debug_user = _check_debug_token(request)
|
||||
if debug_user:
|
||||
return debug_user
|
||||
|
||||
token = _extract_token(request)
|
||||
if not token:
|
||||
return None
|
||||
@ -186,6 +222,10 @@ async def require_auth(request: Request) -> dict:
|
||||
if not _is_auth_enabled():
|
||||
return {"sub": "anonymous", "email": "", "name": "Dev-Modus", "roles": []}
|
||||
|
||||
debug_user = _check_debug_token(request)
|
||||
if debug_user:
|
||||
return debug_user
|
||||
|
||||
token = _extract_token(request)
|
||||
if not token:
|
||||
raise HTTPException(
|
||||
|
||||
@ -26,6 +26,11 @@ services:
|
||||
- GITEA_REPO_NAME=${GITEA_REPO_NAME:-gwoe-antragspruefer}
|
||||
- GITEA_FEEDBACK_LABELS=${GITEA_FEEDBACK_LABELS:-feedback,dev}
|
||||
- APP_ENV=dev
|
||||
# Dev-Bypass für Diagnose-Sessions: wenn gesetzt, akzeptiert
|
||||
# require_auth/require_admin einen Header `X-Debug-Token: <secret>`
|
||||
# oder Query-Param `?__debug_token=<secret>` und liefert einen
|
||||
# Admin-Mock-User. NUR auf dev. Default leer = inaktiv.
|
||||
- DEBUG_AUTH_TOKEN=${DEBUG_AUTH_TOKEN:-}
|
||||
volumes:
|
||||
- ./data:/app/data
|
||||
- ./reports:/app/reports
|
||||
|
||||
Loading…
Reference in New Issue
Block a user