feat(worker): remote MCP listener gated by per-session tokens

This commit is contained in:
mika kuns
2026-10-02 14:23:37 +02:00
parent 0314319872
commit 34970ca600
5 changed files with 127 additions and 2 deletions
@@ -0,0 +1,79 @@
using ClaudeDo.Worker.Config;
using ClaudeDo.Worker.External;
using Microsoft.AspNetCore.Http;
namespace ClaudeDo.Worker.Tests.External;
public sealed class ExternalMcpAuthMiddlewareTests
{
private const int RemotePort = 47_823;
private static async Task<(int Status, bool Passed)> Run(WorkerConfig cfg, RemoteSessionTokenRegistry tokens,
int localPort, string? remoteToken = null, string? apiKey = null)
{
var passed = false;
var mw = new ExternalMcpAuthMiddleware(_ => { passed = true; return Task.CompletedTask; });
var ctx = new DefaultHttpContext();
ctx.Connection.LocalPort = localPort;
if (remoteToken is not null) ctx.Request.Headers[ExternalMcpAuthMiddleware.RemoteTokenHeader] = remoteToken;
if (apiKey is not null) ctx.Request.Headers["X-ClaudeDo-Key"] = apiKey;
await mw.InvokeAsync(ctx, cfg, tokens);
return (ctx.Response.StatusCode, passed);
}
private static WorkerConfig Cfg(string? key = null) =>
new() { ExternalMcpPort = 47_822, RemoteMcpPort = RemotePort, ExternalMcpApiKey = key };
[Fact]
public async Task RemotePort_WithoutToken_Is401()
{
var (status, passed) = await Run(Cfg(), new RemoteSessionTokenRegistry(), RemotePort);
Assert.Equal(401, status);
Assert.False(passed);
}
[Fact]
public async Task RemotePort_WithUnknownToken_Is401()
{
var (status, passed) = await Run(Cfg(), new RemoteSessionTokenRegistry(), RemotePort, remoteToken: "nope");
Assert.Equal(401, status);
Assert.False(passed);
}
[Fact]
public async Task RemotePort_WithIssuedToken_PassesEvenWhenApiKeyConfigured()
{
var tokens = new RemoteSessionTokenRegistry();
var token = tokens.Issue();
var (_, passed) = await Run(Cfg(key: "secret"), tokens, RemotePort, remoteToken: token);
Assert.True(passed);
}
[Fact]
public async Task RemotePort_ApiKeyAlone_DoesNotPass()
{
var (status, passed) = await Run(Cfg(key: "secret"), new RemoteSessionTokenRegistry(), RemotePort, apiKey: "secret");
Assert.Equal(401, status);
Assert.False(passed);
}
[Fact]
public async Task NormalPort_WithoutKeyConfigured_StillPasses()
{
var (_, passed) = await Run(Cfg(), new RemoteSessionTokenRegistry(), 47_822);
Assert.True(passed);
}
[Fact]
public async Task Issue_ReturnsDistinct64HexTokens()
{
var tokens = new RemoteSessionTokenRegistry();
var a = tokens.Issue();
var b = tokens.Issue();
Assert.NotEqual(a, b);
Assert.Matches("^[0-9A-F]{64}$", a);
Assert.True(tokens.IsValid(a));
Assert.False(tokens.IsValid(""));
await Task.CompletedTask;
}
}