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
+15
View File
@@ -7,6 +7,8 @@
use std::path::PathBuf;
use std::sync::Arc;
use crate::cli::oauth_defaults::OAUTH_CALLBACK_PORT;
use chrono::{DateTime, Utc};
use reqwest::Client;
use secrecy::SecretString;
@@ -238,6 +240,7 @@ impl SessionManager {
use crate::cli::oauth_defaults;
let cb_url = oauth_defaults::callback_url();
let host = oauth_defaults::callback_host();
// Show auth provider menu BEFORE binding the listener
println!();
@@ -288,6 +291,18 @@ impl SessionManager {
}
}
// Warn about plain-HTTP token transmission only for OAuth paths (1, 2)
// where the callback URL actually carries the session token.
if !oauth_defaults::is_loopback_host(&host) {
println!();
println!("Warning: OAuth callback is using plain HTTP to a remote host ({host}).");
println!(" The session token will be transmitted unencrypted.");
println!(" Consider SSH port forwarding instead:");
println!(
" ssh -L {OAUTH_CALLBACK_PORT}:127.0.0.1:{OAUTH_CALLBACK_PORT} user@{host}"
);
}
// OAuth paths: bind the callback listener now
let listener = oauth_defaults::bind_callback_listener()
.await