Fix: allow OAuth callback to work on remote servers (fixes #186) (#212)

* fix: allow OAuth callback to work on remote servers via OAUTH_CALLBACK_HOST

Fixes #186.

The OAuth callback URL was hardcoded to `http://127.0.0.1:9876` in two
places (NEAR AI login and MCP server auth). On a remote server this URL
is unreachable from the user's browser, making authentication impossible.

Changes:
- Add `callback_host()` to `oauth_defaults` that reads `OAUTH_CALLBACK_HOST`
  (default: `127.0.0.1`)
- Update `bind_callback_listener()` to bind to `0.0.0.0` when a non-loopback
  host is configured, so the port is reachable from outside the machine
- Update `session.rs` and `mcp/auth.rs` to use `callback_host()` instead
  of hardcoded `127.0.0.1` / `localhost`

Usage on a remote server:
  export OAUTH_CALLBACK_HOST=<your-server-ip>
  ironclaw login

* fix: address PR review comments for OAuth callback security

* fix: address serrrfirat review comments on PR #212

---------

Co-authored-by: firat.sertgoz <[email protected]>
This commit is contained in:
Nitanshu Lokhande
2026-02-21 15:39:47 +04:00
committed by GitHub
co-authored by firat.sertgoz
parent 0a30c95ee1
commit 37c0158765
3 changed files with 172 additions and 32 deletions
+12 -1
View File
@@ -380,7 +380,18 @@ pub async fn authorize_mcp_server(
) -> Result<AccessToken, AuthError> {
// Find an available port for the callback first (needed for DCR)
let (listener, port) = find_available_port().await?;
let redirect_uri = format!("http://localhost:{}/callback", port);
let host = oauth_defaults::callback_host();
let redirect_uri = format!("http://{}:{}/callback", host, port);
// Warn when the callback is served over plain HTTP to a remote host.
// Authorization codes travel unencrypted; SSH port forwarding is safer:
// ssh -L <port>:127.0.0.1:<port> user@your-server
if !oauth_defaults::is_loopback_host(&host) {
println!("Warning: MCP OAuth callback is using plain HTTP to a remote host ({host}).");
println!(" Authorization codes will be transmitted unencrypted.");
println!(" Consider SSH port forwarding instead:");
println!(" ssh -L {port}:127.0.0.1:{port} user@{host}");
}
// Determine client_id and endpoints
let (client_id, authorization_url, token_url, use_pkce, scopes, extra_params) =