Bind profile cookie to auth session
This commit is contained in:
41
api/auth.py
41
api/auth.py
@@ -467,6 +467,47 @@ def _session_token_from_cookie_value(cookie_value: str) -> str | None:
|
||||
return token or None
|
||||
|
||||
|
||||
def sign_profile_cookie_value(profile_name: str, session_cookie_value: str | None) -> str:
|
||||
"""Return a profile cookie value authenticated for one WebUI session.
|
||||
|
||||
The active-profile cookie is client-controlled, so when auth is enabled it
|
||||
must not be trusted as a bare profile name. Binding the selected profile to
|
||||
the HttpOnly session token prevents a client from forging
|
||||
``hermes_profile=<other-profile>`` and bypassing profile visibility guards.
|
||||
"""
|
||||
if not session_cookie_value or not verify_session(session_cookie_value):
|
||||
raise ValueError("active auth session is required to sign profile cookie")
|
||||
token = _session_token_from_cookie_value(session_cookie_value)
|
||||
if not token:
|
||||
raise ValueError("active auth session is required to sign profile cookie")
|
||||
sig = hmac.new(
|
||||
_signing_key(),
|
||||
f"profile:{token}:{profile_name}".encode(),
|
||||
hashlib.sha256,
|
||||
).hexdigest()
|
||||
return f"{profile_name}.{sig}"
|
||||
|
||||
|
||||
def verify_profile_cookie_value(cookie_value: str, session_cookie_value: str | None) -> str | None:
|
||||
"""Verify a session-bound profile cookie and return its profile name."""
|
||||
if not cookie_value or '.' not in cookie_value:
|
||||
return None
|
||||
if not session_cookie_value or not verify_session(session_cookie_value):
|
||||
return None
|
||||
profile_name, sig = cookie_value.rsplit('.', 1)
|
||||
token = _session_token_from_cookie_value(session_cookie_value)
|
||||
if not profile_name or not token or not sig:
|
||||
return None
|
||||
expected = hmac.new(
|
||||
_signing_key(),
|
||||
f"profile:{token}:{profile_name}".encode(),
|
||||
hashlib.sha256,
|
||||
).hexdigest()
|
||||
if hmac.compare_digest(str(sig), expected):
|
||||
return profile_name
|
||||
return None
|
||||
|
||||
|
||||
def csrf_token_for_session(cookie_value: str) -> str | None:
|
||||
"""Return the CSRF token bound to an authenticated WebUI session.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user