fix remote auth: create session for requesting device host
This commit is contained in:
@@ -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