feat(worker): MCP bearer-token auth middleware

This commit is contained in:
mika kuns
2026-04-23 21:15:38 +02:00
parent 9e09ae6b4e
commit b115a4c512
2 changed files with 46 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
namespace ClaudeDo.Worker.Planning;
public sealed class PlanningMcpContext
{
public required string ParentTaskId { get; init; }
}

View File

@@ -0,0 +1,40 @@
using ClaudeDo.Data.Repositories;
using Microsoft.AspNetCore.Http;
namespace ClaudeDo.Worker.Planning;
public sealed class PlanningTokenAuthMiddleware
{
private readonly RequestDelegate _next;
public PlanningTokenAuthMiddleware(RequestDelegate next) => _next = next;
public async Task InvokeAsync(HttpContext ctx, TaskRepository tasks)
{
if (!ctx.Request.Path.StartsWithSegments("/mcp"))
{
await _next(ctx);
return;
}
var auth = ctx.Request.Headers["Authorization"].ToString();
if (!auth.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase))
{
ctx.Response.StatusCode = 401;
await ctx.Response.WriteAsync("Missing bearer token");
return;
}
var token = auth.Substring("Bearer ".Length).Trim();
var parent = await tasks.FindByPlanningTokenAsync(token, ctx.RequestAborted);
if (parent is null || parent.Status != ClaudeDo.Data.Models.TaskStatus.Planning)
{
ctx.Response.StatusCode = 401;
await ctx.Response.WriteAsync("Invalid or expired planning token");
return;
}
ctx.Items["PlanningContext"] = new PlanningMcpContext { ParentTaskId = parent.Id };
await _next(ctx);
}
}