fix: close refresh token session binding bypass

Add require_session parameter to validate_token to enforce session_id
matching for refresh operations. Attacker with stolen refresh token can
no longer bypass session binding by omitting session_id from request.

Also adds backend guard against deleting builtin admin user (was only
blocked at Flask blueprint layer), and removes unused _ALL_RW variable.
This commit is contained in:
2026-08-12 20:06:05 +00:00
parent 9ae2cca801
commit c7593f8a1e
4 changed files with 70 additions and 8 deletions
+6 -4
View File
@@ -44,7 +44,6 @@ from lib.auth import (
validate_token,
)
from lib.auth_users import (
ALL_SUBSYSTEMS,
create_user,
delete_user,
get_user,
@@ -70,8 +69,6 @@ from lib.webauthn import (
logger = logging.getLogger(__name__)
_ALL_RW = {sub: "rw" for sub in ALL_SUBSYSTEMS}
def _clear_refresh_token_after_rotation(username: str) -> None:
"""Remove the user's entry from refresh_tokens after a successful refresh rotation."""
@@ -176,7 +173,12 @@ def auth_refresh(_request: Any, body: Any) -> dict[str, Any]:
raise ValueError("refresh_token is required")
session_id = body.get("session_id")
payload = validate_token(refresh_token, token_type="refresh", session_id=session_id)
if not session_id:
raise ValueError("session_id is required")
payload = validate_token(
refresh_token, token_type="refresh", session_id=session_id, require_session=True
)
if payload is None:
raise ValueError("Invalid or expired refresh token")