← Files Duende SkillsARCHIVED FILE

skills/identity-testing-patterns/docs/bff-testing.md

2.46 KB · Oct 5, 2026 · 18:31 UTC

↓ Download file

# BFF Endpoint Testing

## Pattern 7: Testing BFF Endpoints

BFF tests require cookie-based session simulation. The `WebApplicationFactory` needs to track cookies between requests to simulate a logged-in user.

```csharp
public sealed class BffFactory : WebApplicationFactory<Program>
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureTestServices(services =>
        {
            // Replace OIDC with a short-circuit test handler
            // that immediately signs in a test user on /bff/login
            services.Configure<OpenIdConnectOptions>("oidc", options =>
            {
                options.Events.OnRedirectToIdentityProvider = ctx =>
                {
                    // In tests, bypass the external redirect and sign in directly
                    ctx.HandleResponse();
                    return Task.CompletedTask;
                };
            });
        });
    }
}
```

### Cookie Jar for Session Tests

```csharp
public class BffUserEndpointTests : IClassFixture<BffFactory>
{
    private readonly HttpClient _client;

    public BffUserEndpointTests(BffFactory factory)
    {
        // ✅ Use a CookieContainer so session cookies are stored and sent automatically
        var cookieContainer = new CookieContainer();
        var handler = new HttpClientHandler
        {
            CookieContainer = cookieContainer,
            AllowAutoRedirect = false
        };
        _client = factory.CreateDefaultClient(handler);
    }

    [Fact]
    public async Task UserEndpoint_WithoutSession_ShouldReturn401()
    {
        // Act — no prior login
        var response = await _client.GetAsync("/bff/user");

        // Assert — BFF user endpoint returns 401, not a redirect
        Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
    }

    [Fact]
    public async Task ApiEndpoint_RequiresAntiForgeryHeader()
    {
        // ✅ BFF endpoints require x-csrf: 1 header
        _client.DefaultRequestHeaders.Add("x-csrf", "1");

        var response = await _client.GetAsync("/api/data");

        // Without a session this is 401, but the header check passes
        Assert.NotEqual(HttpStatusCode.BadRequest, response.StatusCode);
    }

    [Fact]
    public async Task ApiEndpoint_WithoutAntiForgeryHeader_ShouldReturn400()
    {
        // ❌ Missing x-csrf: 1
        var response = await _client.GetAsync("/api/data");

        Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
    }
}
```

SHA-256: 2fb5ac12d9c255b07800b859a69f5bc62b84b06988b1a6a50adde3731f7d16cc