Skip to content

Middleware Pipeline

Getting the middleware pipeline order right is critical for BFF to function correctly. Placing middleware in the wrong order can silently disable security features with no obvious error message.

Program.cs
var app = builder.Build();
// 1. Forwarded headers (if behind a reverse proxy)
app.UseForwardedHeaders();
// 2. HTTPS redirection
app.UseHttpsRedirection();
// 3. Static files (serve before auth to avoid unnecessary overhead)
app.UseStaticFiles();
// 4. Routing — must come before UseBff and UseAuthorization
app.UseRouting();
// 5. Authentication — must come before UseBff
app.UseAuthentication();
// 6. BFF middleware — must come AFTER UseAuthentication and UseRouting,
// but BEFORE UseAuthorization
app.UseBff();
// 7. Authorization
app.UseAuthorization();
// 8. Map your endpoints
app.MapGet("/api/data", () => Results.Ok("hello"))
.RequireAuthorization()
.AsBffApiEndpoint();
app.Run();

Each middleware in the pipeline can only see the work done by the middleware before it. Here’s why each position is required:

PositionMiddlewareWhy Here
Before UseBffUseRouting()BFF needs the endpoint route resolved to know which endpoints require anti-forgery protection
Before UseBffUseAuthentication()BFF reads the authenticated user from the HttpContext; without this, the user is always null
After UseAuthentication, before UseAuthorizationUseBff()BFF anti-forgery checks run here; placing it after UseAuthorization silently disables them
After UseBffUseAuthorization()Authorization decisions depend on BFF’s pre-processing having already run

BFF v4 — Automatic Middleware Registration

Section titled “BFF v4 — Automatic Middleware Registration”

In BFF v4, when AutomaticallyRegisterBffMiddleware is enabled (the default), the middleware components are registered automatically. You still need to call UseBff() yourself in the correct position, but the frontend selection, path mapping, OpenID Connect callbacks, and static file proxying middlewares are added automatically.

If you need full control over the pipeline, disable automatic registration:

builder.Services.AddBff(options =>
{
options.AutomaticallyRegisterBffMiddleware = false;
});

Then register each component manually:

// Before Authentication:
app.UseForwardedHeaders();
app.UseBffPreProcessing(); // Frontend selection, path mapping, OIDC callbacks
app.UseAuthentication();
app.UseRouting();
// The main BFF middleware (anti-forgery):
app.UseBff();
app.UseAuthorization();
// After endpoint mapping:
app.UseBffPostProcessing(); // Management endpoints, remote API handling, static file proxying

Blazor applications need a slightly different order to accommodate Blazor’s own middleware:

app.UseRouting();
app.UseAuthentication();
// BFF must come after UseAuthentication
app.UseBff();
app.UseAuthorization();
// Blazor's anti-forgery protection (separate from BFF's anti-forgery)
app.UseAntiforgery();
// In v3, also add:
// app.MapBffManagementEndpoints();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode()
.AddInteractiveWebAssemblyRenderMode();
MistakeSymptomFix
UseBff() after UseAuthorization()Anti-forgery silently disabled; 401 on API callsMove UseBff() before UseAuthorization()
Missing UseAuthentication()All users appear anonymous; no redirect to loginAdd app.UseAuthentication() before app.UseBff()
Missing UseRouting() before UseBff()Anti-forgery checks don’t apply correctly to routesAdd app.UseRouting() before app.UseBff()
.AsBffApiEndpoint() missingAPI returns 302 redirect instead of 401Add .AsBffApiEndpoint() to each API endpoint