Understanding .NET 11 Automatic CSRF Protection: A Guide for Identity Developers
Summary:
• .NET 11 introduces automatic CSRF protection by default for browser-based apps, which rejects unsafe cross-origin requests (such asPOST,PUT,DELETE, orPATCH)by inspectingSec-Fetch-SiteandOriginheaders.
• This change impacts common authentication and security flows, because legitimate cross-origin interactions may now be blocked, requiring developers to adjust their architecture.
• To prepare for this upgrade, developers should thoroughly test authentication flows, consider adopting the Backend-for-Frontend (BFF) pattern to maintain same-origin communication, or selectively disable the protection for specific endpoints as needed.
As identity and security experts, we love "safe by default" systems, but changes to defaults can often lead to headaches during migrations and upgrades. Recently, while reviewing the .NET 11 release notes, we noticed a notable change to the defaults that caught our attention, especially as it pertains to our ASP.NET Core and Duende communities.
.NET 11 introduces an additional lightweight cross-origin protection layer: automatic CSRF protection. Apps built with WebApplication.CreateBuilder now reject unsafe cross-origin browser requests by inspecting the Sec-Fetch-Site and Origin headers. No configuration required and no opt-in, as we said; safe by default.
That's a meaningful security improvement for many apps. But if your architecture involves a single-page application (SPA) on one origin communicating with an API on another, or if you run Duende IdentityServer, several of your critical flows are cross-origin by design. Here's what you need to know.
What Changed in .NET 11 CSRF Protection
The new middleware inspects two browser-supplied headers on every unsafe request (POST, PUT, DELETE, PATCH):
- Sec-Fetch-Site tells the server whether the request is
same-origin,same-site,cross-site, ornone. - Origin identifies where the request originated.
Same-origin requests pass through. User-initiated navigations pass through. Non-browser clients (no Sec-Fetch-Site header) pass through. Everything else gets rejected.
The feature applies across Minimal APIs, MVC, Razor Pages, and Blazor. The Blazor Web App templates no longer call app.UseAntiforgery() because this replaces it.
How .NET 11 CSRF Protection Affects SPA Developers
Dev server proxying is now required, not optional
Most SPA frameworks run a dev server, such as Vite, on a different port during development. For example, React on localhost:5173, the ASP.NET Core API on localhost:5001. That's cross-origin, and those requests will be rejected starting in .NET 11. What's the fix?
Configure your dev server to proxy API calls so they appear same-origin. Vite, webpack, and Angular CLI all support this. If you were skipping the proxy and relying on CORS alone, that approach no longer works. Even better, we suggest looking at our Duende BFF Security Framework for the best current practices for SPAs.
Production architectures with separate API origins
If your SPA lives at app.example.com and your API lives at api.example.com, every API call from the browser is cross-origin. CORS policies won't help here because the CSRF protection runs independently of CORS.
You have a few options:
- Serve the SPA and API from the same origin using a reverse proxy, using something like Duende BFF Security Framework
- Implement a custom
ICsrfProtectionto trust specific origins - Disable the protection on specific endpoints with
DisableAntiforgery()or[IgnoreAntiforgeryToken]
Third-party callbacks
Payment processors, identity providers, and webhook senders POST to your app from their domains. Each endpoint receiving these callbacks needs a DisableAntiforgery() or [IgnoreAntiforgeryToken] decorator.
WebViews in mobile and hybrid apps
Apps using Capacitor, MAUI, or other WebView-based frameworks may send unexpected Sec-Fetch-Site values, or none at all. Test your WebView-hosted app after upgrading. The key question is the behavior when these headers are absent.
Impact of .NET 11 CSRF Changes on Duende IdentityServer
Identity protocols are cross-origin by design. OAuth 2.0 and OpenID Connect require clients on different origins to POST to Duende IdentityServer endpoints. This is where the new protection creates the most friction and opportunity for issues.
Protocol endpoints that receive cross-origin POSTs
The token endpoint, revocation endpoint, introspection endpoint, device authorization endpoint, and CIBA endpoint all receive POSTs from client applications on different origins. If the CSRF middleware runs before Duende IdentityServer's middleware processes these requests, legitimate token exchanges will be rejected.
Authorization Code + PKCE flow with SPAs
This is the most common SPA authentication pattern. After the browser redirects back from the authorize endpoint, the SPA's JavaScript calls the token endpoint with the authorization code. That fetch() call goes from the SPA's origin to Duende IdentityServer's origin. It's cross-origin. It's a POST. It will be rejected. Again, our recommendation and best current practice is to implement the Duende BFF Security Framework to avoid this issue entirely.
External identity provider callbacks
When you federate with Azure Entra ID, Google, or any external provider using response_mode=form_post, the provider POSTs back to your /signin-oidc callback. That's a cross-origin form POST from the provider's domain. Whether the CSRF protection recognizes this as legitimate user navigation (via Sec-Fetch-Mode: none) determines whether it works or silently fails.
Front-channel logout
Duende IdentityServer's front-channel logout renders iframes pointing to each client's FrontChannelLogoutUri. These are cross-origin requests by definition. Depending on how the middleware evaluates Sec-Fetch-Dest: iframe combined with a cross-site Sec-Fetch-Site, logout notifications could be silently dropped.
Backchannel logout with Duende BFF Security Framework
Duende BFF Security Framework proxies API calls through a same-origin backend, so normal API traffic is fine. But BFF exposes a backchannel logout endpoint that receives POSTs from Duende IdentityServer when a user signs out. That's a server-to-server call, but if IdentityServer's HttpClient sets Origin or Sec-Fetch-Site headers, the request could be rejected.
By default no additional headers are added to any HttpClient instances from within the Duende codebase, but there are extensibility methods that could see developer-introduced changes. As always, it's best to test when upgrading.
Custom grants and extension endpoints
If you use token exchange (RFC 8693), delegation grants, or custom endpoints added to your IdentityServer pipeline, audit whether they're processed by Duende IdentityServer's middleware or fall through to the general ASP.NET Core pipeline, where the CSRF protection runs.
Preparing Your Apps for .NET 11 CSRF Protection
Test before you upgrade. Run your full authentication flow (login, token exchange, refresh, logout) against a .NET 11 build with a real browser. Automated tests using HttpClient won't surface these issues because non-browser clients don't send Sec-Fetch-Site headers.
Use DisableCsrfProtection as a diagnostic tool. If things break after upgrading, set this configuration key to confirm that the CSRF protection is the cause. Then, selectively exempt endpoints rather than disabling it globally.
Prefer the BFF pattern for SPAs. Proxying API calls through a same-origin backend sidesteps most of these issues. The SPA talks to its own origin, and the backend talks to the Duende IdentityServer instance server-to-server.
Wait for Duende guidance on IdentityServer integration. Duende IdentityServer's middleware will likely need to coordinate with or bypass this feature for protocol endpoints. Watch for updates before upgrading production IdentityServer deployments to .NET 11. Be sure to subscribe to our blog and our newsletter for more information and updates.
Action Steps for .NET 11 Developers
If you're running Duende IdentityServer or building SPAs against ASP.NET Core APIs, test your flows against .NET 11 now, while you have time to adjust. Check the ASP.NET Core .NET 11 Preview 6 release notes for the full details on the feature and its escape hatches.
For SPA security patterns that work with (not against) same-origin constraints, explore the Duende BFF Security Framework documentation.