fix(auth): improve xAI OAuth SSH hint with visual header and auto-detected host

This commit is contained in:
konsisumer 2026-05-17 01:41:42 +02:00 committed by Teknium
parent bf6eeb3f93
commit 226680500d
2 changed files with 78 additions and 6 deletions

View file

@ -2895,6 +2895,21 @@ def _is_remote_session() -> bool:
return bool(os.getenv("SSH_CLIENT") or os.getenv("SSH_TTY"))
def _ssh_user_at_host() -> str:
"""Return best-effort 'user@hostname' for the SSH tunnel hint command.
Falls back to placeholder tokens when the values cannot be determined so
the hint is always syntactically valid even if not copy-pasteable.
"""
try:
import socket as _socket
hostname = _socket.gethostname() or "<this-host>"
except OSError:
hostname = "<this-host>"
user = os.getenv("USER") or os.getenv("LOGNAME") or "<user>"
return f"{user}@{hostname}"
def _print_loopback_ssh_hint(redirect_uri: str, *, docs_url: str | None = None) -> None:
"""Print an SSH tunnel hint when running a loopback-redirect OAuth flow on a
remote host. The auth server (xAI, Spotify, ...) will redirect the user's
@ -2918,19 +2933,22 @@ def _print_loopback_ssh_hint(redirect_uri: str, *, docs_url: str | None = None)
port = parsed.port
if host not in {"127.0.0.1", "::1", "localhost"} or not port:
return
divider = "-" * 60
print()
print("Remote session detected. Your browser will redirect to")
print(f" {redirect_uri}")
print("which the loopback listener on THIS machine is waiting on. If your")
print("browser is on a different machine, forward the port first from your")
print("local machine in a separate terminal:")
print(divider)
print("Remote session detected — SSH tunnel required")
print(divider)
print(f"Hermes is waiting for the OAuth callback on {redirect_uri}")
print("but your browser is on a different machine. Run this command")
print("in a NEW terminal on your local machine BEFORE opening the URL:")
print()
print(f" ssh -N -L {port}:127.0.0.1:{port} <user>@<this-host>")
print(f" ssh -N -L {port}:127.0.0.1:{port} {_ssh_user_at_host()}")
print()
print("Then open the authorize URL above in your local browser.")
if docs_url:
print(f"Provider docs: {docs_url}")
print(f"SSH/jump-box guide: {OAUTH_OVER_SSH_DOCS_URL}")
print(divider)
print()

View file

@ -9,6 +9,7 @@ from __future__ import annotations
import io
import contextlib
import socket
import pytest
@ -93,3 +94,56 @@ def test_loopback_ssh_hint_accepts_localhost_hostname(monkeypatch):
"http://localhost:56121/callback"
))
assert "ssh -N -L 56121:127.0.0.1:56121" in out
def test_loopback_ssh_hint_includes_user_at_host(monkeypatch):
"""The SSH command should include a detected user@host so the user can
copy-paste it without manually substituting placeholders."""
monkeypatch.setattr(auth_mod, "_is_remote_session", lambda: True)
monkeypatch.setattr(auth_mod, "_ssh_user_at_host", lambda: "alice@myserver.lan")
out = _cap(lambda: auth_mod._print_loopback_ssh_hint(
"http://127.0.0.1:56121/callback"
))
assert "ssh -N -L 56121:127.0.0.1:56121 alice@myserver.lan" in out
def test_loopback_ssh_hint_has_visual_header(monkeypatch):
"""The hint should print a divider and header so it stands out in noisy output."""
monkeypatch.setattr(auth_mod, "_is_remote_session", lambda: True)
out = _cap(lambda: auth_mod._print_loopback_ssh_hint(
"http://127.0.0.1:56121/callback"
))
assert "Remote session detected" in out
assert "---" in out # divider is present
class TestSshUserAtHost:
def test_resolves_user_and_hostname(self, monkeypatch):
monkeypatch.setenv("USER", "alice")
monkeypatch.delenv("LOGNAME", raising=False)
monkeypatch.setattr(socket, "gethostname", lambda: "myserver")
assert auth_mod._ssh_user_at_host() == "alice@myserver"
def test_falls_back_to_logname(self, monkeypatch):
monkeypatch.delenv("USER", raising=False)
monkeypatch.setenv("LOGNAME", "bob")
monkeypatch.setattr(socket, "gethostname", lambda: "host1")
assert auth_mod._ssh_user_at_host() == "bob@host1"
def test_placeholder_when_no_env_vars(self, monkeypatch):
monkeypatch.delenv("USER", raising=False)
monkeypatch.delenv("LOGNAME", raising=False)
monkeypatch.setattr(socket, "gethostname", lambda: "host1")
assert auth_mod._ssh_user_at_host() == "<user>@host1"
def test_placeholder_when_socket_raises(self, monkeypatch):
monkeypatch.setenv("USER", "charlie")
def _raise():
raise OSError("no network")
monkeypatch.setattr(socket, "gethostname", _raise)
assert auth_mod._ssh_user_at_host() == "charlie@<this-host>"
def test_placeholder_when_empty_hostname(self, monkeypatch):
monkeypatch.setenv("USER", "dave")
monkeypatch.setattr(socket, "gethostname", lambda: "")
assert auth_mod._ssh_user_at_host() == "dave@<this-host>"