71 lines
1.9 KiB
Python
71 lines
1.9 KiB
Python
"""
|
|
Signierte, serverseitig invalidierbare Session-Cookies.
|
|
|
|
Kein separates Session-Store noetig: Das Cookie traegt user_id,
|
|
session_version (fuer harte Invalidierung, z.B. bei Passwortwechsel) und
|
|
zwei Zeitstempel (Login-Zeit fuer den absoluten Timeout, Last-Seen fuer den
|
|
gleitenden Idle-Timeout). Signatur ueber einen vom KEK getrennten Secret
|
|
(Schluesseltrennung, Konzept 6.2).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import time
|
|
from dataclasses import dataclass
|
|
|
|
from itsdangerous import BadSignature, URLSafeSerializer
|
|
|
|
from app.config import settings
|
|
|
|
_serializer = URLSafeSerializer(settings.session_secret.hex(), salt="jumphost-session")
|
|
|
|
SESSION_COOKIE_NAME = "jh_session"
|
|
|
|
|
|
@dataclass
|
|
class SessionPayload:
|
|
user_id: int
|
|
session_version: int
|
|
login_ts: float
|
|
last_seen_ts: float
|
|
|
|
|
|
def create_session_token(user_id: int, session_version: int) -> str:
|
|
now = time.time()
|
|
payload = {"uid": user_id, "sv": session_version, "iat": now, "seen": now}
|
|
return _serializer.dumps(payload)
|
|
|
|
|
|
def refresh_session_token(payload: SessionPayload) -> str:
|
|
data = {
|
|
"uid": payload.user_id,
|
|
"sv": payload.session_version,
|
|
"iat": payload.login_ts,
|
|
"seen": time.time(),
|
|
}
|
|
return _serializer.dumps(data)
|
|
|
|
|
|
def decode_session_token(token: str) -> SessionPayload | None:
|
|
try:
|
|
data = _serializer.loads(token)
|
|
except BadSignature:
|
|
return None
|
|
try:
|
|
return SessionPayload(
|
|
user_id=int(data["uid"]),
|
|
session_version=int(data["sv"]),
|
|
login_ts=float(data["iat"]),
|
|
last_seen_ts=float(data["seen"]),
|
|
)
|
|
except (KeyError, TypeError, ValueError):
|
|
return None
|
|
|
|
|
|
def is_expired(payload: SessionPayload) -> bool:
|
|
now = time.time()
|
|
if now - payload.last_seen_ts > settings.session_idle_timeout_s:
|
|
return True
|
|
if now - payload.login_ts > settings.session_absolute_timeout_s:
|
|
return True
|
|
return False
|