Skip to content

Commit f347dd2

Browse files
Copilotgewarren
andcommitted
Add breaking change documentation for cookie authentication API endpoints
Co-authored-by: gewarren <[email protected]>
1 parent 5090e28 commit f347dd2

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed
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](https://learn.microsoft.com/aspnet/core/fundamentals/routing) are identified using the new <xref:Microsoft.AspNetCore.Http.Metadata.IApiEndpointMetadata> interface, and metadata implementing the new interface has been added automatically to the following:
14+
15+
- `[ApiController]` endpoints
16+
- Minimal API endpoints that read JSON request bodies or write JSON responses
17+
- Endpoints using `TypedResults` return types
18+
- SignalR endpoints
19+
20+
## Version introduced
21+
22+
.NET 10 Preview 7
23+
24+
## Previous behavior
25+
26+
The cookie authentication handler would redirect unauthenticated and unauthorized requests to a login or access denied URI by default for all requests other than [XMLHttpRequests (XHRs)](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest).
27+
28+
## New behavior
29+
30+
Unauthenticated and unauthorized requests made to known API endpoints will 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 can affect [behavioral change](../../categories.md#behavioral-change).
35+
36+
## Reason for change
37+
38+
This change was highly requested, and 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 the `RedirectToLogin` and `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 which 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+
- <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 are 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: IActionContextAccessor and ActionContextAccessor are obsolete

0 commit comments

Comments
 (0)