Forge
csharp3407750f
1using AgentForge.Plugin.Sdk;
2using AgentForge.Services;
3
4namespace AgentForge.Middleware;
5
6public sealed class ForgeAuthMiddleware(RequestDelegate next)
7{
8 public async Task InvokeAsync(HttpContext context, ForgeAuthService auth)
9 {
10 if (!auth.RequireAuth || BypassesApiToken(context.Request))
11 {
12 await next(context);
13 return;
14 }
15
16 var bearer = ForgePluginHttpAuth.GetBearerToken(context);
17 if (auth.ValidateBootstrapToken(bearer))
18 {
19 await next(context);
20 return;
21 }
22
23 var token = ForgePluginHttpAuth.ResolveApiToken(context, auth);
24 if (token is null)
25 {
26 context.Response.StatusCode = StatusCodes.Status401Unauthorized;
27 await context.Response.WriteAsJsonAsync(new { detail = "Bearer API token required." });
28 return;
29 }
30
31 context.Items[ForgePluginHttpAuth.ApiTokenItemKey] = token;
32 await next(context);
33 }
34
35 private static bool BypassesApiToken(HttpRequest request)
36 {
37 var path = request.Path;
38 if (path.StartsWithSegments("/health", StringComparison.OrdinalIgnoreCase))
39 return true;
40 if (path == "/")
41 return true;
42 if (path.StartsWithSegments("/view", StringComparison.OrdinalIgnoreCase))
43 return true;
44 if (path.StartsWithSegments("/api/v1/ci/callback", StringComparison.OrdinalIgnoreCase))
45 return true;
46 if (path.StartsWithSegments("/api/v1/git", StringComparison.OrdinalIgnoreCase))
47 return true;
48 if (path.StartsWithSegments("/api/v1/admin", StringComparison.OrdinalIgnoreCase))
49 return true;
50 if (path.StartsWithSegments("/api/v1/orgs", StringComparison.OrdinalIgnoreCase))
51 return true;
52 if (path.StartsWithSegments("/api/v1/auth", StringComparison.OrdinalIgnoreCase))
53 return true;
54 if (path.StartsWithSegments("/api/v1/capabilities", StringComparison.OrdinalIgnoreCase))
55 return true;
56 return false;
57 }
58}
59
View only · write via MCP/CIDE