Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d0d17c307 | ||
|
|
10980ad39b |
@@ -437,7 +437,7 @@ def delete_credential(
|
|||||||
|
|
||||||
|
|
||||||
def update_session(
|
def update_session(
|
||||||
key: bytes,
|
key: str,
|
||||||
host: str | None = None,
|
host: str | None = None,
|
||||||
ip: str | None = None,
|
ip: str | None = None,
|
||||||
user_agent: str | None = None,
|
user_agent: str | None = None,
|
||||||
@@ -461,7 +461,7 @@ def update_session(
|
|||||||
|
|
||||||
|
|
||||||
def set_session_host(
|
def set_session_host(
|
||||||
key: bytes, host: str, *, ctx: SessionContext | None = None
|
key: str, host: str, *, ctx: SessionContext | None = None
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set the host for a session (first-time binding)."""
|
"""Set the host for a session (first-time binding)."""
|
||||||
update_session(key, host=host, ctx=ctx)
|
update_session(key, host=host, ctx=ctx)
|
||||||
|
|||||||
@@ -312,7 +312,13 @@ async def websocket_remote_auth_permit(ws: WebSocket, auth=AUTH_COOKIE):
|
|||||||
|
|
||||||
# Handle authenticate request (no PoW needed - already validated during lookup)
|
# Handle authenticate request (no PoW needed - already validated during lookup)
|
||||||
if msg.get("authenticate") and request is not None:
|
if msg.get("authenticate") and request is not None:
|
||||||
ctx, secret = await authenticate_and_login(ws, auth)
|
ctx, secret = await authenticate_and_login(
|
||||||
|
ws,
|
||||||
|
auth,
|
||||||
|
session_host=request.host,
|
||||||
|
session_ip=request.ip,
|
||||||
|
session_user_agent=request.user_agent,
|
||||||
|
)
|
||||||
|
|
||||||
reset_token = None
|
reset_token = None
|
||||||
|
|
||||||
|
|||||||
@@ -69,11 +69,22 @@ async def authenticate_chat(
|
|||||||
async def authenticate_and_login(
|
async def authenticate_and_login(
|
||||||
ws: WebSocket,
|
ws: WebSocket,
|
||||||
auth: str | None = None,
|
auth: str | None = None,
|
||||||
|
*,
|
||||||
|
session_host: str | None = None,
|
||||||
|
session_ip: str | None = None,
|
||||||
|
session_user_agent: str | None = None,
|
||||||
) -> tuple[SessionContext, str]:
|
) -> tuple[SessionContext, str]:
|
||||||
"""Run WebAuthn authentication flow, create session, and return the session context.
|
"""Run WebAuthn authentication flow, create session, and return the session context.
|
||||||
|
|
||||||
If auth is provided, restrict authentication to credentials of that session's user.
|
If auth is provided, restrict authentication to credentials of that session's user.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
ws: The WebSocket connection (used for WebAuthn and origin validation)
|
||||||
|
auth: Existing session cookie for re-auth credential restriction
|
||||||
|
session_host: Override host for the new session (defaults to ws origin)
|
||||||
|
session_ip: Override IP for the new session (defaults to ws client IP)
|
||||||
|
session_user_agent: Override user-agent for the new session (defaults to ws headers)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple of (SessionContext for the authenticated session, session secret)
|
Tuple of (SessionContext for the authenticated session, session secret)
|
||||||
"""
|
"""
|
||||||
@@ -97,18 +108,25 @@ async def authenticate_and_login(
|
|||||||
|
|
||||||
cred, new_sign_count = await authenticate_chat(ws, credential_ids)
|
cred, new_sign_count = await authenticate_chat(ws, credential_ids)
|
||||||
|
|
||||||
|
# Use overrides if provided, otherwise use websocket metadata
|
||||||
|
login_host = hostutil.normalize_host(session_host) if session_host is not None else normalized_host
|
||||||
|
if not login_host:
|
||||||
|
raise ValueError("Host required for session creation")
|
||||||
|
login_ip = session_ip if session_ip is not None else metadata["ip"]
|
||||||
|
login_user_agent = session_user_agent if session_user_agent is not None else metadata["user_agent"]
|
||||||
|
|
||||||
# Create session and update user/credential
|
# Create session and update user/credential
|
||||||
secret = db.login(
|
secret = db.login(
|
||||||
user_uuid=cred.user_uuid,
|
user_uuid=cred.user_uuid,
|
||||||
credential_uuid=cred.uuid,
|
credential_uuid=cred.uuid,
|
||||||
sign_count=new_sign_count,
|
sign_count=new_sign_count,
|
||||||
host=normalized_host,
|
host=login_host,
|
||||||
ip=metadata["ip"],
|
ip=login_ip,
|
||||||
user_agent=metadata["user_agent"],
|
user_agent=login_user_agent,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Fetch and return the full session context
|
# Fetch and return the full session context (using the same host the session was created with)
|
||||||
ctx = session_ctx(secret, host)
|
ctx = session_ctx(secret, login_host)
|
||||||
if not ctx:
|
if not ctx:
|
||||||
raise ValueError("Failed to create session context")
|
raise ValueError("Failed to create session context")
|
||||||
return ctx, secret
|
return ctx, secret
|
||||||
|
|||||||
Reference in New Issue
Block a user