fix(security): require auth on every MCP request; stop stale refreshes banning clients

- Remove the authless "sole connected phone" fallback and SB_REQUIRE_MCP_AUTH:
  an unauthenticated request no longer reaches whichever phone is online alone.
- Mcp-Session-Id is no longer a credential; the Bearer token is checked on
  every request (MCP auth spec).
- Refresh tokens live 90 days (was 30, equal to the access token, so they
  were always dead when first needed).
- A rejected refresh no longer counts toward the IP ban: a client with an
  expired token was retrying into a self-renewing ban on its own IP.
- 401s carry the RFC 9728 WWW-Authenticate discovery header.
This commit is contained in:
AletheiaVox
2026-09-27 12:55:16 +02:00
parent 605f71b742
commit 7bb9d8473b
9 changed files with 124 additions and 53 deletions

View File

@@ -163,10 +163,6 @@ SB_HOST=0.0.0.0
SB_PORT=8420
SB_REGISTRATION_OPEN=true
SB_TOKEN_EXPIRY_HOURS=720
# true = every MCP request must be authenticated (multi-user servers).
# false = single-user convenience: unauthenticated MCP requests go to the
# sole connected phone.
SB_REQUIRE_MCP_AUTH=false
SB_HEARTBEAT_INTERVAL=2.0
SB_HEARTBEAT_TIMEOUT=6.0
SB_BAN_THRESHOLD=20
@@ -313,12 +309,6 @@ The server implements the full OAuth 2.0 flow that claude.ai custom connectors e
4. Save — claude.ai will open your server's login page
5. Sign in with the username and password you registered in step 1.4
### Option C: claude.ai without login (single-user fallback)
If you skip the OAuth login, the server falls back to routing unauthenticated MCP requests to the sole connected phone — convenient for a private single-user server.
**Important**: The authless fallback only works when exactly one phone/relay client is connected to the server (and is disabled entirely when `SB_REQUIRE_MCP_AUTH=true`). If no phones are connected, claude.ai will show a connection error. Start your relay client first, then connect from claude.ai.
---
## Part 4: Relay Client — Windows PC
@@ -524,8 +514,8 @@ Too many rapid reconnection attempts. Restart the Docker container to clear in-m
**Relay connects but finds 0 devices**
Intiface Central can't see your Bluetooth devices. Make sure devices are turned on and in range. On Android, verify Location and Bluetooth permissions are granted to Intiface.
**claude.ai stuck on "checking connection"**
The authless fallback requires at least one relay client connected. Start your relay first, then add the connector in claude.ai.
**Connector keeps asking to reconnect / sign-in popup hangs**
Check whether your IP is banned: `curl -X POST https://your-server/mcp` answering `{"error":"Temporarily banned"}` means yes. Bans are in memory; restart the container to clear one. Since v1.2, expired refresh tokens no longer count toward the ban, so a client with a stale token can't ban its own IP any more.
**Heartbeat timeout / disconnects after a few commands**
Use the Termux v3 relay (`termux_relay_v3.py`), which processes commands in background tasks so heartbeat responses are never blocked.