dotnet / dotnet/aspnetcore

Minimal API incorrectly returns 400 with antiforgery error message

Open
#66,329 4 comments 1 reaction 0 assignees View on GitHub
area-middleware area-minimal bug feature-antiforgery Needs: Repro
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 6h
Merged PRs (30d)
290

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues

### Describe the bug

I have a Blazor web app on net10.

My `Program.cs` has a pretty common setup:

```cs
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel( opt => opt.AddServerHeader = false );

builder.Services
.AddAntiforgery()
.AddMyCustomServices()
.AddRazorComponents()
.AddInteractiveServerComponents();

var app = builder.Build();

app.UseStatusCodePagesWithReExecute( "/status-{0}", createScopeForStatusCodePages: true );
app.UseHttpsRedirection();
app.UseRequestLocalization();
app.UseAntiforgery();

app.MapStaticAssets();

// We will write custom CSP headers with app.Use() below
app.MapRazorComponents()
.AddInteractiveServerRenderMode( opt => opt.ContentSecurityFrameAncestorsPolicy = null )
.AddAdditionalAssemblies( typeof( MyFallbackPage ).Assembly );

app.Use( AddCustomCspHeaders );
app.MapCustomMinimalApis();

await app.RunAsync();
```

The "MapCustomMinimalApis" registers various routes to be handled as API routes or intercepts that I don't want Blazor to handle. The one that's giving me the issue is a webhook callback.

```cs
app.MapPost( "/api/webhooks/callback", ProcessWebhook )
.DisableAntiforgery().ShortCircuit();
```
A complication is that `MyFallbackPage` is a Blazor page with the route `@page "/{*RequestPath}"` - it's a fallback that should receive all requests that aren't APIs, static assets or other registered pages.

This setup works perfectly... for the most part.

If I execute this webhook from Postman it behaves exactly as expected, however when the webhook is called from a 3rd party service I always get a 400 response with the body text:
`A valid antiforgery token was not provided with the request. Add an antiforgery token, or disable antiforgery validation for this endpoint.`

The only material differences between the Postman request that works, and the actual webhook callback that doesn't are:
- Failed request has no "Accept" header
- Failed request has no "Accept-Encoding" headers
- Failed request has no "Cache-Control" headers
- Failed request has no "Cookie" headers
- Failed request has multiple "User-Agent" headers

At present I am running through a Dev Tunnel, so it's not clear to me whether the tunnel is contributing, but I suspect not.
No breakpoints in my code get hit in the 400 condition.

The response 400 error includes the header "blazor-enhanced-nav: allow" which makes me think the request is being routed to the Blazor fallback page rather than being picked up by the Minimal API route, but I don't understand why or how to account for this missing header, if that indeed is the issue.

### Expected Behavior

"Accept" header should not influence routing to mapped handlers.

### Steps To Reproduce

_No response_

### Exceptions (if any)

_No response_

### .NET Version

10.0.201

### Anything else?

```text
.NET SDK:
Version: 10.0.201
Commit: 4d3023de60
Workload version: 10.0.200-manifests.121cc9e6
MSBuild version: 18.3.0-release-26153-122+4d3023de6

Runtime Environment:
OS Name: Windows
OS Version: 10.0.22631
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\10.0.201\

.NET workloads installed:
[android]
Installation Source: VS 18.4.11626.88
Manifest Version: 36.1.30/10.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\10.0.100\microsoft.net.sdk.android\36.1.30\WorkloadManifest.json
Install Type: Msi

[wasm-tools]
Installation Source: VS 18.4.11626.88
Manifest Version: 10.0.105/10.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\10.0.100\microsoft.net.workload.mono.toolchain.current\10.0.105\WorkloadManifest.json
Install Type: Msi

[maui-windows]
Installation Source: VS 18.4.11626.88
Manifest Version: 10.0.20/10.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\10.0.100\microsoft.net.sdk.maui\10.0.20\WorkloadManifest.json
Install Type: Msi

[maccatalyst]
Installation Source: VS 18.4.11626.88
Manifest Version: 26.2.10217/10.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\10.0.100\microsoft.net.sdk.maccatalyst\26.2.10217\WorkloadManifest.json
Install Type: Msi

[ios]
Installation Source: VS 18.4.11626.88
Manifest Version: 26.2.10217/10.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\10.0.100\microsoft.net.sdk.ios\26.2.10217\WorkloadManifest.json
Install Type: Msi

Configured to use workload sets when installing new manifests.
No workload sets are installed. Run "dotnet workload restore" to install a workload set.

Host:
Version: 10.0.5
Architecture: x64
Commit: a612c2a105

.NET SDKs installed:
9.0.115 [C:\Program Files\dotnet\sdk]
10.0.100-preview.7.25380.108 [C:\Program Files\dotnet\sdk]
10.0.100-rc.1.25451.107 [C:\Program Files\dotnet\sdk]
10.0.201 [C:\Program Files\dotnet\sdk]

.NET runtimes installed:
Microsoft.AspNetCore.App 8.0.25 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 9.0.14 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 10.0.0-preview.7.25380.108 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 10.0.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.36 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.25 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 9.0.14 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 10.0.0-preview.7.25380.108 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 10.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 8.0.25 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 9.0.14 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 10.0.0-preview.7.25380.108 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 10.0.5 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.