fix: use Directus 11 'id' claim instead of 'sub' for JWT user_id

Directus 11.x JWT payload uses 'id' (not 'sub') for the user UUID.
Our validate_session_jwt required 'sub' → MissingRequiredClaimError on
every request → persistent 401 on all cloud endpoints.
This commit is contained in:
pyr0ball 2026-03-27 08:34:06 -07:00
parent ee1e72992b
commit f26020cf7f

View file

@ -100,11 +100,13 @@ def _extract_session_token(header_value: str) -> str:
def validate_session_jwt(token: str) -> str: def validate_session_jwt(token: str) -> str:
"""Validate a cf_session JWT and return the Directus user_id (sub claim). """Validate a cf_session JWT and return the Directus user_id.
Uses HMAC-SHA256 verification against DIRECTUS_JWT_SECRET (same secret Uses HMAC-SHA256 verification against DIRECTUS_JWT_SECRET (same secret
cf-directus uses to sign session tokens). Returns user_id on success, cf-directus uses to sign session tokens). Returns user_id on success,
raises HTTPException(401) on failure. raises HTTPException(401) on failure.
Directus 11+ uses 'id' (not 'sub') for the user UUID in its JWT payload.
""" """
try: try:
import jwt as pyjwt import jwt as pyjwt
@ -112,9 +114,9 @@ def validate_session_jwt(token: str) -> str:
token, token,
DIRECTUS_JWT_SECRET, DIRECTUS_JWT_SECRET,
algorithms=["HS256"], algorithms=["HS256"],
options={"require": ["sub", "exp"]}, options={"require": ["id", "exp"]},
) )
return payload["sub"] return payload["id"]
except Exception as exc: except Exception as exc:
log.debug("JWT validation failed: %s", exc) log.debug("JWT validation failed: %s", exc)
raise HTTPException(status_code=401, detail="Session invalid or expired") raise HTTPException(status_code=401, detail="Session invalid or expired")