Description
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.
Known API Endpoints are identified using the new IDisableCookieRedirectMetadata interface (previously IApiEndpointMetadata), and metadata implementing this interface is added automatically to the following:
[ApiController] endpoints
- Minimal API endpoints that read JSON request bodies or write JSON responses
- Endpoints using
TypedResults return types
- SignalR endpoints
Update: Additional Workarounds and Metadata
After feedback on the initial change, we've added more flexible ways to work around issues caused by this breaking change:
- New metadata interface:
IDisableCookieRedirectMetadata replaces IApiEndpointMetadata.
- Opt-in attribute & metadata: You can now use the
[AllowCookieRedirect] attribute or implement the IAllowCookieRedirectMetadata interface on your endpoints to explicitly allow cookie authentication redirects, even on endpoints that would otherwise suppress them.
- Global opt-out AppContext Switch: You can set the AppContext switch
Microsoft.AspNetCore.Authentication.Cookies.IgnoreRedirectMetadata to true to revert to the old behavior globally and ignore the new metadata-based suppression. This is particularly useful for large apps or frameworks (like UmbracoCMS) that need a quick mitigation.
Version
.NET 10 Preview 7
Previous behavior
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).
New behavior
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.
Type of breaking change
Reason for change
dotnet/aspnetcore#9039 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.
Recommended action
To always redirect (fully disable new behavior):
Recommended for frameworks/applications needing an immediate opt-out or full legacy compatibility:
Set the following AppContext switch (e.g., in your app's runtimeconfig.json or programmatically at startup):
{
"runtimeOptions": {
"configProperties": {
"Microsoft.AspNetCore.Authentication.Cookies.IgnoreRedirectMetadata": true
}
}
}
Or, set programmatically before building the host:
AppContext.SetSwitch("Microsoft.AspNetCore.Authentication.Cookies.IgnoreRedirectMetadata", true);
To allow redirects on specific endpoints:
Apply the [AllowCookieRedirect] attribute to controllers or endpoints that should preserve cookie-based redirects, or implement the IAllowCookieRedirectMetadata interface.
[AllowCookieRedirect]
public class MyLegacyApiController : Controller { ... }
To revert to the exact previous handler logic (redirect except for XHRs):
You can override the events with the following logic:
builder.Services.AddAuthentication()
.AddCookie(options =>
{
bool IsXhr(HttpRequest request)
{
return string.Equals(request.Query[HeaderNames.XRequestedWith], "XMLHttpRequest", StringComparison.Ordinal) ||
string.Equals(request.Headers.XRequestedWith, "XMLHttpRequest", StringComparison.Ordinal);
}
options.Events.OnRedirectToLogin = context =>
{
if (IsXhr(context.Request))
{
context.Response.Headers.Location = context.RedirectUri;
context.Response.StatusCode = 401;
}
else
{
context.Response.Redirect(context.RedirectUri);
}
return Task.CompletedTask;
};
options.Events.OnRedirectToAccessDenied = context =>
{
if (IsXhr(context.Request))
{
context.Response.Headers.Location = context.RedirectUri;
context.Response.StatusCode = 403;
}
else
{
context.Response.Redirect(context.RedirectUri);
}
return Task.CompletedTask;
};
});
To always redirect regardless of endpoint type or XHR:
Override the events to always redirect:
builder.Services.AddAuthentication()
.AddCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
};
options.Events.OnRedirectToAccessDenied = context =>
{
context.Response.Redirect(context.RedirectUri);
return Task.CompletedTask;
};
});
References
Affected APIs
Description
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.
Known API Endpoints are identified using the new
IDisableCookieRedirectMetadatainterface (previouslyIApiEndpointMetadata), and metadata implementing this interface is added automatically to the following:[ApiController]endpointsTypedResultsreturn typesUpdate: Additional Workarounds and Metadata
After feedback on the initial change, we've added more flexible ways to work around issues caused by this breaking change:
IDisableCookieRedirectMetadatareplacesIApiEndpointMetadata.[AllowCookieRedirect]attribute or implement theIAllowCookieRedirectMetadatainterface on your endpoints to explicitly allow cookie authentication redirects, even on endpoints that would otherwise suppress them.Microsoft.AspNetCore.Authentication.Cookies.IgnoreRedirectMetadatatotrueto revert to the old behavior globally and ignore the new metadata-based suppression. This is particularly useful for large apps or frameworks (like UmbracoCMS) that need a quick mitigation.Version
.NET 10 Preview 7
Previous behavior
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).
New behavior
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.
Type of breaking change
Reason for change
dotnet/aspnetcore#9039 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.
Recommended action
To always redirect (fully disable new behavior):
Recommended for frameworks/applications needing an immediate opt-out or full legacy compatibility:
Set the following AppContext switch (e.g., in your app's runtimeconfig.json or programmatically at startup):
{ "runtimeOptions": { "configProperties": { "Microsoft.AspNetCore.Authentication.Cookies.IgnoreRedirectMetadata": true } } }Or, set programmatically before building the host:
To allow redirects on specific endpoints:
Apply the
[AllowCookieRedirect]attribute to controllers or endpoints that should preserve cookie-based redirects, or implement theIAllowCookieRedirectMetadatainterface.To revert to the exact previous handler logic (redirect except for XHRs):
You can override the events with the following logic:
To always redirect regardless of endpoint type or XHR:
Override the events to always redirect:
References
Affected APIs
Microsoft.AspNetCore.Http.Metadata.IDisableCookieRedirectMetadataMicrosoft.AspNetCore.Http.Metadata.IAllowCookieRedirectMetadata[AllowCookieRedirect]attribute