feat(worker): remote MCP listener gated by per-session tokens
This commit is contained in:
+17
-1
@@ -7,12 +7,28 @@ public sealed class ExternalMcpAuthMiddleware
|
||||
{
|
||||
private const string HeaderName = "X-ClaudeDo-Key";
|
||||
|
||||
/// <summary>Header carrying an SSH session's token on the remote MCP listener.</summary>
|
||||
public const string RemoteTokenHeader = "X-ClaudeDo-Remote-Token";
|
||||
|
||||
private readonly RequestDelegate _next;
|
||||
|
||||
public ExternalMcpAuthMiddleware(RequestDelegate next) => _next = next;
|
||||
|
||||
public async Task InvokeAsync(HttpContext ctx, WorkerConfig cfg)
|
||||
public async Task InvokeAsync(HttpContext ctx, WorkerConfig cfg, RemoteSessionTokenRegistry remoteTokens)
|
||||
{
|
||||
// Tunnelled traffic arrives as loopback too, so the remote listener never falls back to loopback trust.
|
||||
if (cfg.RemoteMcpPort > 0 && ctx.Connection.LocalPort == cfg.RemoteMcpPort)
|
||||
{
|
||||
if (!remoteTokens.IsValid(ctx.Request.Headers[RemoteTokenHeader].ToString()))
|
||||
{
|
||||
ctx.Response.StatusCode = 401;
|
||||
await ctx.Response.WriteAsync($"Missing or invalid {RemoteTokenHeader} header");
|
||||
return;
|
||||
}
|
||||
await _next(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(cfg.ExternalMcpApiKey))
|
||||
{
|
||||
await _next(ctx);
|
||||
|
||||
Reference in New Issue
Block a user