From 68192f9e5b4dd7ef2c3844a3858dff3f6c8f5b26 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sun, 21 Jun 2026 21:23:36 +0100 Subject: [PATCH] test(client): cookies + middleware-based user injection for POSTs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - WebApplicationFactoryClientOptions.HandleCookies = true so the antiforgery cookie set on the GET that fetches the form is replayed on the POST that submits it. Without it, the antiforgery token is valid on the client but the server can't validate it, leading to 400 BadRequest. - Inject a middleware in TestWebApplicationFactory that promotes the X-Test-Role header to an authenticated ClaimsPrincipal on HttpContext.User, so anything that reads User.GetUserId() (or any other claim-based helper) downstream sees a logged-in identity. The TestAuthPolicyProvider only short-circuits [Authorize(...)] checks; it does not touch HttpContext.User, which is what user code reads. - Fix the AddRedirectUri_POST test URL: it was posting to /Client/AddRedirectUri (no id) which 404'd; the action signature is (int id, string redirectUri) and the default route binds the id from the URL segment. WIP: the MapStaticAssets() default lookup at {AssemblyName}.staticwebassets.endpoints.json still needs the manifest to be renamed on copy — the Yavsc.Org.Tests.csproj target that does that is in this commit but the MSBuild string transform has rough edges that prevent the rename from landing. Will revisit. --- .../ClientControllerCollectionTests.cs | 11 +++-- .../TestWebApplicationFactory.cs | 40 +++++++++++++++++++ src/Yavsc.Org.Tests/Yavsc.Org.Tests.csproj | 17 +++++++- 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/Yavsc.Org.Tests/Controllers/ClientControllerCollectionTests.cs b/src/Yavsc.Org.Tests/Controllers/ClientControllerCollectionTests.cs index 352f25f9..59f4747e 100644 --- a/src/Yavsc.Org.Tests/Controllers/ClientControllerCollectionTests.cs +++ b/src/Yavsc.Org.Tests/Controllers/ClientControllerCollectionTests.cs @@ -76,10 +76,12 @@ public class ClientControllerCollectionTests : IClassFixture[Authorize("AdministratorOnly")] (and any other policy /// requiring a role) is satisfied by sending an /// X-Test-Role: Administrator header, without a real login. +/// Also injects a middleware that promotes the same header into a +/// real on HttpContext.User so +/// that user code reading User.GetUserId() sees a logged-in +/// identity. /// public class TestWebApplicationFactory : WebApplicationFactory { @@ -33,5 +40,38 @@ public class TestWebApplicationFactory : WebApplicationFactory // becomes irrelevant: any GetPolicyAsync call is routed here. services.AddSingleton(); }); + + // Promote the X-Test-Role header to an authenticated identity + // on the request, so anything that reads User.GetUserId() (or + // any other claim-based helper) downstream sees a logged-in + // user. The policy provider above only short-circuits + // [Authorize(...)] checks; it does not touch HttpContext.User. + builder.Configure(app => + { + app.Use(InjectTestUser); + }); + } + + private static RequestDelegate InjectTestUser(RequestDelegate next) + { + return async ctx => + { + var role = ctx.Request.Headers[TestAuthPolicyProvider.HeaderName].ToString(); + if (!string.IsNullOrEmpty(role) && + (ctx.User.Identity is null || !ctx.User.Identity.IsAuthenticated)) + { + var identity = new ClaimsIdentity( + new[] + { + new Claim( + "http://schemas.microsoft.com/ws/2008/06/identity/claims/role", + role), + new Claim(ClaimTypes.NameIdentifier, "test-user"), + }, + authenticationType: "TestAuth"); + ctx.User = new ClaimsPrincipal(identity); + } + await next(ctx); + }; } } diff --git a/src/Yavsc.Org.Tests/Yavsc.Org.Tests.csproj b/src/Yavsc.Org.Tests/Yavsc.Org.Tests.csproj index f2106a88..c1d7faf1 100644 --- a/src/Yavsc.Org.Tests/Yavsc.Org.Tests.csproj +++ b/src/Yavsc.Org.Tests/Yavsc.Org.Tests.csproj @@ -64,10 +64,25 @@ <_YavscOrgStaticAssetsDir>$(MSBuildProjectDirectory)\..\Yavsc.Org\bin\$(Configuration)\$(TargetFramework) + <_YavscOrgStaticAssetsFiles Include="$(_YavscOrgStaticAssetsDir)\Yavsc.Org.staticwebassets.*.json" />