fix(security): F10 (Astra P1) — Token-Scopes sind Obergrenze, kein Ersatz fuer User-Rechte
Vorher: require_permission machte bei passendem Token-Scope ein early-return — die User-Rechte wurden NIE geprueft. Ein Token mit mail:write erlaubte mail:write selbst dann, wenn der Benutzer die Berechtigung nie hatte oder sie entzogen bekam (Astra-Repro isoliert bestaetigt). Fix: Nach bestandenem Scope-Check in den normalen User-Rechte-Check fallen. Effektives Recht = User-Rechte UND Token-Scope. Rechteentzug wirkt sofort auf bestehende Tokens. System-Admin-Bypass unveraendert. Tests: tests/test_s1_security_guards.py 7/7 (neue Suite): Scope-ohne-User-Recht 403, beide-present pass, Scope-fehlt-User-hat 403 insufficient_scope, Deny-Revocation wirkt, Session-Pfad unveraendert, *:*-Scope umgeht nicht, Admin-Bypass bleibt. ruff clean.
This commit is contained in:
+5
-1
@@ -311,6 +311,10 @@ def require_permission(permission: str):
|
||||
current_user: dict[str, Any] = Depends(get_current_user),
|
||||
) -> dict[str, Any]:
|
||||
# API token scope enforcement (Problem 2 fix)
|
||||
# F10 (Astra): token scopes are an UPPER BOUND, not a replacement —
|
||||
# the user's own permissions must ALSO grant the permission. A token
|
||||
# can never grant more than its owner has; revoking the user's
|
||||
# permission takes effect on existing tokens.
|
||||
token_scopes = current_user.get("_token_scopes")
|
||||
if token_scopes is not None:
|
||||
from app.core.permissions import _permission_matches_any
|
||||
@@ -322,7 +326,7 @@ def require_permission(permission: str):
|
||||
"code": "insufficient_scope",
|
||||
},
|
||||
)
|
||||
return current_user
|
||||
# fall through: the normal user-permission check applies too
|
||||
|
||||
if current_user.get("is_system_admin"):
|
||||
return current_user
|
||||
|
||||
Reference in New Issue
Block a user