Skip to content

Commit 7c9eb66

Browse files
authored
Document cookie authentication API endpoint breaking change for .NET 10 (#47904)
1 parent 714a8a3 commit 7c9eb66

File tree

3 files changed

+116
-3
lines changed

3 files changed

+116
-3
lines changed

docs/core/compatibility/10.0.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
title: Breaking changes in .NET 10
33
titleSuffix: ""
44
description: Navigate to the breaking changes in .NET 10.
5-
ms.date: 06/05/2025
5+
ms.date: 08/08/2025
66
ai-usage: ai-assisted
77
no-loc: [Blazor, Razor, Kestrel]
88
---
@@ -17,8 +17,9 @@ If you're migrating an app to .NET 10, the breaking changes listed here might af
1717
1818
## ASP.NET Core
1919

20-
| Title | Type of change | Introduced version |
21-
|-------|---------------------|--------------------|
20+
| Title | Type of change | Introduced version |
21+
|-------|-------------------|--------------------|
22+
| [Cookie login redirects disabled for known API endpoints](aspnet-core/10/cookie-authentication-api-endpoints.md) | Behavioral change | Preview 7 |
2223
| [Deprecation of WithOpenApi extension method](aspnet-core/10/withopenapi-deprecated.md) | Source incompatible | Preview 7 |
2324
| [Exception diagnostics suppressed when TryHandleAsync returns true](aspnet-core/10/exception-handler-diagnostics-suppressed.md) | Behavioral change | Preview 7 |
2425
| [IActionContextAccessor and ActionContextAccessor are obsolete](aspnet-core/10/iactioncontextaccessor-obsolete.md) | Source incompatible/behavioral change | Preview 7 |
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
---
2+
title: "Cookie login redirects are disabled for known API endpoints"
3+
description: "Learn about the breaking change in ASP.NET Core 10 where cookie authentication no longer redirects to login or access denied URIs for known API endpoints."
4+
ms.date: 08/08/2025
5+
ai-usage: ai-assisted
6+
ms.custom: https://github.com/aspnet/Announcements/issues/525
7+
---
8+
9+
# Cookie login redirects are disabled for known API endpoints
10+
11+
By default, unauthenticated and unauthorized requests made to known API endpoints protected by cookie authentication now result in 401 and 403 responses rather than redirecting to a login or access-denied URI.
12+
13+
Known API [endpoints](/aspnet/core/fundamentals/routing) are identified using the new `IApiEndpointMetadata` <!--xref:Microsoft.AspNetCore.Http.Metadata.IApiEndpointMetadata--> interface, and metadata implementing the new interface has been added automatically to the following:
14+
15+
- [`[ApiController]`](xref:Microsoft.AspNetCore.Mvc.ApiControllerAttribute) endpoints.
16+
- Minimal API endpoints that read JSON request bodies or write JSON responses.
17+
- Endpoints using <xref:Microsoft.AspNetCore.Http.TypedResults> return types.
18+
- SignalR endpoints.
19+
20+
## Version introduced
21+
22+
.NET 10 Preview 7
23+
24+
## Previous behavior
25+
26+
Previously, the cookie authentication handler redirected unauthenticated and unauthorized requests to a login or access-denied URI by default for all requests other than [XMLHttpRequests (XHRs)](https://developer.mozilla.org/docs/Web/API/XMLHttpRequest).
27+
28+
## New behavior
29+
30+
Starting in .NET 10, unauthenticated and unauthorized requests made to known API endpoints result in 401 and 403 responses rather than redirecting to a login or access-denied URI. XHRs continue to result in 401 and 403 responses regardless of the target endpoint.
31+
32+
## Type of breaking change
33+
34+
This change is a [behavioral change](../../categories.md#behavioral-change).
35+
36+
## Reason for change
37+
38+
This change was highly requested. Redirecting unauthenticated requests to a login page doesn't usually make sense for API endpoints, which typically rely on 401 and 403 status codes rather than HTML redirects to communicate auth failures.
39+
40+
## Recommended action
41+
42+
If you want to always redirect to the login and access-denied URIs for unauthenticated or unauthorized requests regardless of the target endpoint or whether the source of the request is an XHR, you can override <xref:Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationEvents.RedirectToLogin*> and <xref:Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationEvents.RedirectToAccessDenied*> as follows:
43+
44+
```csharp
45+
builder.Services.AddAuthentication()
46+
.AddCookie(options =>
47+
{
48+
options.Events.OnRedirectToLogin = context =>
49+
{
50+
context.Response.Redirect(context.RedirectUri);
51+
return Task.CompletedTask;
52+
};
53+
54+
options.Events.OnRedirectToAccessDenied = context =>
55+
{
56+
context.Response.Redirect(context.RedirectUri);
57+
return Task.CompletedTask;
58+
};
59+
});
60+
```
61+
62+
If you want to revert to the exact previous behavior that avoids redirecting for only XHRs, you can override the events with this slightly more complicated logic:
63+
64+
```csharp
65+
builder.Services.AddAuthentication()
66+
.AddCookie(options =>
67+
{
68+
bool IsXhr(HttpRequest request)
69+
{
70+
return string.Equals(request.Query[HeaderNames.XRequestedWith], "XMLHttpRequest", StringComparison.Ordinal) ||
71+
string.Equals(request.Headers.XRequestedWith, "XMLHttpRequest", StringComparison.Ordinal);
72+
}
73+
74+
options.Events.OnRedirectToLogin = context =>
75+
{
76+
if (IsXhr(context.Request))
77+
{
78+
context.Response.Headers.Location = context.RedirectUri;
79+
context.Response.StatusCode = 401;
80+
}
81+
else
82+
{
83+
context.Response.Redirect(context.RedirectUri);
84+
}
85+
86+
return Task.CompletedTask;
87+
};
88+
89+
options.Events.OnRedirectToAccessDenied = context =>
90+
{
91+
if (IsXhr(context.Request))
92+
{
93+
context.Response.Headers.Location = context.RedirectUri;
94+
context.Response.StatusCode = 403;
95+
}
96+
else
97+
{
98+
context.Response.Redirect(context.RedirectUri);
99+
}
100+
101+
return Task.CompletedTask;
102+
};
103+
});
104+
```
105+
106+
## Affected APIs
107+
108+
- `Microsoft.AspNetCore.Http.Metadata.IApiEndpointMetadata` <!--xref:Microsoft.AspNetCore.Http.Metadata.IApiEndpointMetadata?displayProperty=fullName-->
109+
- <xref:Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationEvents.RedirectToLogin*?displayProperty=fullName>
110+
- <xref:Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationEvents.RedirectToAccessDenied*?displayProperty=fullName>

docs/core/compatibility/toc.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ items:
1010
href: 10.0.md
1111
- name: ASP.NET Core
1212
items:
13+
- name: Cookie login redirects disabled for known API endpoints
14+
href: aspnet-core/10/cookie-authentication-api-endpoints.md
1315
- name: Deprecation of WithOpenApi extension method
1416
href: aspnet-core/10/withopenapi-deprecated.md
1517
- name: Exception diagnostics suppressed when TryHandleAsync returns true

0 commit comments

Comments
 (0)