Problem
/.tunnel requires WebID auth but reads the credential only from the Authorization header (getWebIdFromRequestAsync(request) in src/tunnel/index.js). A browser WebSocket can't set request headers, so a browser-based tunnel client can't authenticate — it gets {type:"error", message:"Authentication required"} and the socket closes.
Node clients work fine (they set Authorization: Bearer <jwt>), which is why the existing demos work; only browser clients are blocked.
Precedent
/.webrtc already solved this — it injects a ?token= query param into the Authorization header before authenticating:
// src/webrtc/index.js
const queryToken = request.query?.token;
if (queryToken && !request.headers.authorization) {
request.headers.authorization = `Bearer ${queryToken}`;
}
/.tunnel should do the same, for consistency.
Proposed fix
In src/tunnel/index.js, before the getWebIdFromRequestAsync(request) call in the /.tunnel route:
const queryToken = request.query?.token;
if (queryToken && !request.headers.authorization) {
request.headers.authorization = `Bearer ${queryToken}`;
}
~4 lines, mirroring /.webrtc.
Test
- Obtain a WebID-bound JWT (
POST /.pods).
- From a browser:
new WebSocket("wss://<host>/.tunnel?token=<jwt>"), then send {type:"register", name:"demo"}.
- Expect
{type:"registered", url:"/tunnel/demo/"}; confirm https://<host>/tunnel/demo/ proxies to the client.
Motivation
Enables a browser-based tunnel client (the solid-apps/tunnel control panel) — pods reachable on the web with no inbound ports, straight from the browser.
Security note
Same trade-off /.webrtc already accepts: the token rides in the WS upgrade URL. Acceptable parity; tokens are WebID-bound / short-lived. (Worth a docs note.)
Related
#527 (tunnel client mode: jss --tunnel-connect) — this resolves its "relay auth for the client" open question for browser clients; the same ?token= mechanism also supports a pre-shared-token outbound (Node) client.
Problem
/.tunnelrequires WebID auth but reads the credential only from theAuthorizationheader (getWebIdFromRequestAsync(request)insrc/tunnel/index.js). A browserWebSocketcan't set request headers, so a browser-based tunnel client can't authenticate — it gets{type:"error", message:"Authentication required"}and the socket closes.Node clients work fine (they set
Authorization: Bearer <jwt>), which is why the existing demos work; only browser clients are blocked.Precedent
/.webrtcalready solved this — it injects a?token=query param into the Authorization header before authenticating:/.tunnelshould do the same, for consistency.Proposed fix
In
src/tunnel/index.js, before thegetWebIdFromRequestAsync(request)call in the/.tunnelroute:~4 lines, mirroring
/.webrtc.Test
POST /.pods).new WebSocket("wss://<host>/.tunnel?token=<jwt>"), then send{type:"register", name:"demo"}.{type:"registered", url:"/tunnel/demo/"}; confirmhttps://<host>/tunnel/demo/proxies to the client.Motivation
Enables a browser-based tunnel client (the
solid-apps/tunnelcontrol panel) — pods reachable on the web with no inbound ports, straight from the browser.Security note
Same trade-off
/.webrtcalready accepts: the token rides in the WS upgrade URL. Acceptable parity; tokens are WebID-bound / short-lived. (Worth a docs note.)Related
#527 (tunnel client mode:
jss --tunnel-connect) — this resolves its "relay auth for the client" open question for browser clients; the same?token=mechanism also supports a pre-shared-token outbound (Node) client.