fix: token_version NULL handling — normalize None→0 in JWT comparison
Direct DB inserts (e.g. install wizard, manual MySQL) may leave token_version as NULL. JWT payload had tv:null which failed the strict != comparison against DB value 0. Normalize both sides with `or 0` for defensive coding. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -216,8 +216,10 @@ async def _verify_token(token: str, request: Request) -> Optional[Admin]:
|
||||
# Primary check: token_version must match exactly.
|
||||
# Changed on password change, TOTP disable, or token reuse detection.
|
||||
# This invalidates ALL access tokens immediately — no grace window.
|
||||
token_tv = payload.get("tv", -1)
|
||||
if token_tv != admin.token_version:
|
||||
# Normalize None → 0 for safety (DB may have NULL from direct inserts)
|
||||
token_tv = payload.get("tv") or 0
|
||||
admin_tv = admin.token_version or 0
|
||||
if token_tv != admin_tv:
|
||||
logger.debug(f"Token invalidated: token_version mismatch (token={token_tv}, db={admin.token_version})")
|
||||
return None
|
||||
|
||||
@@ -271,8 +273,9 @@ async def get_optional_admin(
|
||||
return None
|
||||
|
||||
# Primary check: token_version must match exactly
|
||||
token_tv = payload.get("tv", -1)
|
||||
if token_tv != admin.token_version:
|
||||
token_tv = payload.get("tv") or 0
|
||||
admin_tv = admin.token_version or 0
|
||||
if token_tv != admin_tv:
|
||||
return None
|
||||
|
||||
# Secondary check: updated_at timestamp (defense in depth)
|
||||
|
||||
@@ -424,7 +424,7 @@ class AuthService:
|
||||
"iat": now,
|
||||
"exp": now + datetime.timedelta(minutes=JWT_ACCESS_TOKEN_EXPIRE_MINUTES),
|
||||
"updated": int(admin.updated_at.timestamp()) if admin.updated_at else 0,
|
||||
"tv": admin.token_version,
|
||||
"tv": admin.token_version or 0,
|
||||
}
|
||||
return jwt.encode(payload, settings.SECRET_KEY, algorithm="HS256")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user