Context
We're using per-connect relay auth tokens (meshrelay.ashx?auth=<token>, the {u, a:3, once, time, expire} cookie format) instead of session cookies, generated via encodeCookie/decodeCookie. Works well nonce is properly single-use, expire enforcement is solid.
Problem
Because the token is in the query string, it ends up in reverse-proxy / access logs by default (nginx, etc.) for the duration it's valid. It's single-use so replay risk is bounded, but it's still avoidable exposure for anyone with log access.
Observation
PerformWSSessionAuth already supports header-based auth for user/pass via req.headers['x-meshauth'] (base64 comma-joined user,pass,token). The a:3 cookie-token path, however, only reads from req.query.auth — there's no header equivalent for it.
Proposal
Add a header fallback for the existing a:3 cookie-token format, e.g. x-meshauth-token, checked before/instead of req.query.auth, keeping the query param as the default for backward compatibility (agents, MeshCmd, peer-server relay, etc. all rely on it). Something like:
var authSource = req.query.auth;
if ((!authSource) && req.headers['x-meshauth-token']) {
authSource = req.headers['x-meshauth-token'];
}
Question for maintainers
Is this direction welcome, or is there a reason relay auth is intentionally query-string-only (e.g. a client — mobile app, MeshCmd, peer-server relay that can't set custom WS headers)? Also wasn't sure if meshrelay.ashx calls PerformWSSessionAuth directly or has additional relay-specific cookie validation on top of it — our testing found expire is treated as absolute epoch-ms for relay auth, while decodeCookie here has a hardcoded 60-minute relative timeout, so there may be a second layer I'm not seeing in this file. Wanted to check before assuming this is the right patch point. Happy to put together a PR if this is a good idea.
Context
We're using per-connect relay auth tokens (
meshrelay.ashx?auth=<token>, the{u, a:3, once, time, expire}cookie format) instead of session cookies, generated viaencodeCookie/decodeCookie. Works well nonce is properly single-use,expireenforcement is solid.Problem
Because the token is in the query string, it ends up in reverse-proxy / access logs by default (nginx, etc.) for the duration it's valid. It's single-use so replay risk is bounded, but it's still avoidable exposure for anyone with log access.
Observation
PerformWSSessionAuthalready supports header-based auth for user/pass viareq.headers['x-meshauth'](base64 comma-joineduser,pass,token). Thea:3cookie-token path, however, only reads fromreq.query.auth— there's no header equivalent for it.Proposal
Add a header fallback for the existing
a:3cookie-token format, e.g.x-meshauth-token, checked before/instead ofreq.query.auth, keeping the query param as the default for backward compatibility (agents, MeshCmd, peer-server relay, etc. all rely on it). Something like:Question for maintainers
Is this direction welcome, or is there a reason relay auth is intentionally query-string-only (e.g. a client — mobile app, MeshCmd, peer-server relay that can't set custom WS headers)? Also wasn't sure if
meshrelay.ashxcallsPerformWSSessionAuthdirectly or has additional relay-specific cookie validation on top of it — our testing foundexpireis treated as absolute epoch-ms for relay auth, whiledecodeCookiehere has a hardcoded 60-minute relative timeout, so there may be a second layer I'm not seeing in this file. Wanted to check before assuming this is the right patch point. Happy to put together a PR if this is a good idea.