Correct .NET 10 cookie redirect behavior docs for API endpoints - #37638
Conversation
Co-authored-by: wadepickett <10985336+wadepickett@users.noreply.github.com>
Co-authored-by: wadepickett <10985336+wadepickett@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Add authorization requirements to the examples and clarify the remaining redirect-scope statements.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Updates .NET 10 cookie-authentication documentation to accurately describe API endpoint detection, redirect behavior, configuration APIs, and breaking changes.
Changes:
- Corrects detection criteria and
Locationheader behavior. - Documents endpoint-level and global redirect configuration.
- Updates API references and migration guidance.
File summaries
| File | Summary |
|---|---|
aspnetcore/security/authentication/api-endpoint-auth.md |
Updates conceptual guidance and configuration examples. |
aspnetcore/breaking-changes/10/cookie-authentication-api-endpoints.md |
Corrects API references and expands migration guidance. |
Review details
Suppressed comments (5)
aspnetcore/breaking-changes/10/cookie-authentication-api-endpoints.md:71
- This route is anonymous, so it never reaches a cookie challenge and
AllowCookieRedirect()cannot demonstrate restoring a login redirect. AddRequireAuthorization()(or state that a global authorization policy is assumed) so the recommended-action example exercises the behavior it documents.
app.MapGet("/reports/summary", () => new ReportSummary(1000))
.AllowCookieRedirect();
aspnetcore/security/authentication/api-endpoint-auth.md:51
- This endpoint doesn't require authorization, so it never reaches a cookie challenge/forbid and cannot demonstrate the documented behavior. Add
RequireAuthorization()(or state that a global authorization policy is assumed) so theDisableCookieRedirectexample actually produces the 401/403 response it describes.
var api = app.MapGroup("/api").DisableCookieRedirect();
api.MapGet("/status", () => "Ready");
aspnetcore/security/authentication/api-endpoint-auth.md:58
- As written, this route is also anonymous, so
AllowCookieRedirect()has no effect: no cookie challenge occurs and no login redirect can be observed. AddRequireAuthorization()(or document the assumed global policy) to make the example exercise the API-endpoint redirect behavior.
app.MapGet("/reports/summary", () => new ReportSummary(1000))
.AllowCookieRedirect();
aspnetcore/security/authentication/api-endpoint-auth.md:70
[ApiController]doesn't require authorization, so this controller action is reachable anonymously and theAllowCookieRedirectoverride is never used. Add[Authorize]to the controller or action (or state that a global authorization policy is assumed) so the sample actually demonstrates the cookie redirect behavior.
[ApiController]
[AllowCookieRedirect]
[Route("[controller]")]
public class ReportsController : ControllerBase
{
[HttpGet("summary")]
public ReportSummary GetSummary() => new(1000);
aspnetcore/security/authentication/api-endpoint-auth.md:108
- This blanket statement contradicts the detection caveat above: the page explicitly says a
string-returningMapGetcan still redirect, even in an API-only app. Qualify this to API endpoints that meet the automatic detection criteria, and point readers toDisableCookieRedirectfor other API endpoints.
* **API-only applications**: Return proper HTTP status codes without additional configuration
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
🔵 Needs a closer look
A moderate scope explanation issue and a missing explicit Location header note remain unresolved.
Review details
Suppressed comments (2)
aspnetcore/security/authentication/api-endpoint-auth.md:42
- These two adjacent notes describe the same scope twice, and the first one incorrectly attributes sign-out behavior to
OnRedirectToReturnUrl(the sign-out path isOnRedirectToLogout). Keeping both leaves a misleading explanation after the scope correction; replace them with one note that distinguishes return-URL and sign-out redirects and qualifies the 302 for non-XHR requests with a redirect URI.
> [!NOTE]
> Endpoint metadata only affects the challenge (401) and forbid (403) paths. Sign-out and return URL
> redirects aren't affected, because <xref:Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationEvents.OnRedirectToReturnUrl>
> only checks whether the request is an XHR. Signing out from an API endpoint redirects with a 302
> whenever a redirect URI is supplied and the request isn't an XHR, exactly as it did before .NET 10.
aspnetcore/security/authentication/api-endpoint-auth.md:34
- The main article changes the wording to distinguish a 401/403 from a 302, but it never states in the prose that the
Locationheader is still emitted; that fact appears only in the test comment. Add a note next to this behavior, as in the breaking-change article, so readers don't infer that the header is removed.
* **API endpoints**: Return 401 or 403 status codes instead of a 302 redirect
- Files reviewed: 2/2 changed files
- Comments generated: 0 new
- Review effort level: Lite
Clarified the behavior of endpoint metadata regarding sign-out redirects and return URL redirects in API authentication.
There was a problem hiding this comment.
🔵 Needs a closer look
Examples and redirect behavior guidance need clarification and correction before approval.
Review details
Suppressed comments (9)
Previously missed (1) — in code that hasn't changed since the last review.
aspnetcore/security/authentication/api-endpoint-auth.md:27
- This example is not protected, so a real unauthenticated request normally executes the handler and returns 200 rather than invoking cookie authentication. Qualify it as a protected endpoint (for example, by adding
.RequireAuthorization()) so the claim that it redirects on challenge is accurate.
aspnetcore/breaking-changes/10/cookie-authentication-api-endpoints.md:71
ReportSummaryis not declared in this article, and the endpoint has no authorization requirement, so this copyable example fails to compile and never reaches cookie authentication. Use a defined/anonymous response type and require authorization.
app.MapGet("/reports/summary", () => new ReportSummary(1000))
.AllowCookieRedirect();
aspnetcore/breaking-changes/10/cookie-authentication-api-endpoints.md:67
AllowCookieRedirectcannot restore a redirect for an XMLHttpRequest: the pre-existing XHR handling still produces 401/403 before the endpoint metadata distinction matters. Qualify this recommendation so readers don't interpret it as restoring redirects for every request to the endpoint.
To restore redirects for individual endpoints instead, call <xref:Microsoft.AspNetCore.Builder.CookieRedirectEndpointConventionBuilderExtensions.AllowCookieRedirect*> or apply the <xref:Microsoft.AspNetCore.Http.AllowCookieRedirectAttribute> to an action method or controller class:
aspnetcore/security/authentication/api-endpoint-auth.md:54
AllowCookieRedirectcontrols both challenge and forbid behavior, so it restores access-denied redirects as well as login redirects. Please describe both outcomes here; otherwise users handling 403 responses may miss that this API applies to them too.
Call <xref:Microsoft.AspNetCore.Builder.CookieRedirectEndpointConventionBuilderExtensions.AllowCookieRedirect*> to keep login redirects for endpoints that are detected as API endpoints:
aspnetcore/security/authentication/api-endpoint-auth.md:42
OnRedirectToReturnUrlhandles the post-logout return redirect, but sign-out itself invokesOnRedirectToLogout, which has its own XHR-only check. As written, this attributes the sign-out behavior to the wrong event and can send readers to the wrong hook; describe both handlers (or avoid naming only one).
> Endpoint metadata only affects the challenge (401) and forbid (403) paths. Sign-out and return URL
> redirects aren't affected, because <xref:Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationEvents.OnRedirectToReturnUrl>
> only checks whether the request is an XHR. Signing out from an API endpoint redirects with a 302
> whenever a redirect URI is supplied and the request isn't an XHR, exactly as it did before .NET 10.
aspnetcore/security/authentication/api-endpoint-auth.md:51
- This endpoint is not authorized, so the
DisableCookieRedirectcall cannot produce the documented 401/403 response in the shown example. Add.RequireAuthorization()to the mapped endpoint, or explicitly state that a global fallback policy is assumed.
api.MapGet("/status", () => "Ready");
aspnetcore/security/authentication/api-endpoint-auth.md:58
ReportSummaryis not declared anywhere in the article, and this endpoint has no authorization requirement, so the snippet both fails to compile and cannot exerciseAllowCookieRedirect. Use a defined/anonymous response type and require authorization in the example.
app.MapGet("/reports/summary", () => new ReportSummary(1000))
.AllowCookieRedirect();
aspnetcore/security/authentication/api-endpoint-auth.md:65
- The controller sample has no authorization requirement and returns the undeclared
ReportSummarytype, so it returns normally rather than exercising the redirect override and cannot be copied as shown. Add[Authorize]and use a defined/anonymous return type.
[AllowCookieRedirect]
aspnetcore/security/authentication/api-endpoint-auth.md:54
AllowCookieRedirectonly removes the endpoint-metadata opt-out; the existing XHR check still returns 401/403 even when the endpoint allows redirects. Since this sentence promises login redirects for the endpoint without qualifying the request type (while line 36 says XHRs always get status codes), say that this applies to non-XHR requests.
Call <xref:Microsoft.AspNetCore.Builder.CookieRedirectEndpointConventionBuilderExtensions.AllowCookieRedirect*> to keep login redirects for endpoints that are detected as API endpoints:
- Files reviewed: 2/2 changed files
- Comments generated: 0 new
- Review effort level: Lite
Clarified note about endpoint metadata and redirect behavior for sign-out and return URL in API authentication.
Updated API endpoint responses to return objects instead of specific types.
Updated example for allowing cookie redirects in API endpoints.
Split up dense paragraph.
There was a problem hiding this comment.
🟡 Changes recommended
Address the sample authorization behavior and restore the complete affected API inventory.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
aspnetcore/security/authentication/api-endpoint-auth.md:29
- Because this example omits
.RequireAuthorization(), the shown endpoint will return 200 and never invoke the cookie challenge; an unauthenticated request therefore won't redirect as the prose claims. Add authorization to the sample so it demonstrates the metadata behavior.
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Lite
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: wadepickett <10985336+wadepickett@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Address the outstanding date metadata and status-code guidance findings.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
aspnetcore/security/authentication/api-endpoint-auth.md:110
- This is broader than the detection rules described above: handlers returning
string,void, orIResultaren't automatically marked, and the next section requiresDisableCookieRedirectfor endpoints that aren't detected. Qualify this bullet to say that known/detected API endpoints get these status codes, rather than implying every endpoint in an API-only app does so automatically.
* **API-only applications**: Return proper HTTP status codes without additional configuration.
- Files reviewed: 2/2 changed files
- Comments generated: 2
- Review effort level: Lite
Update the date for the breaking change announcement regarding cookie authentication API endpoints. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Update the date for the API endpoint authentication documentation. Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: wadepickett <10985336+wadepickett@users.noreply.github.com>
Addressed all findings in this review. Both files use |
meaghanlewis
left a comment
There was a problem hiding this comment.
These changes LGTM @wadepickett ✨
The API endpoint auth article contradicted both the shipped product and its own sibling breaking-change doc: it claimed the change was "non-breaking", asserted that no
Locationheader is sent, described endpoint detection by registration verb, and omitted the actual opt-in/opt-out APIs entirely. The breaking-change doc referencedIApiEndpointMetadata, which was renamed before RTM and doesn't exist in the shipped product.All claims below were verified against
dotnet/aspnetcoreatrelease/10.0, and every API doc ID against the official XML indotnet/AspNetApiDocs.security/authentication/api-endpoint-auth.mdMapGet,MapPost..." and "endpoints that explicitly request JSON responses" with the criteriaRequestDelegateFactoryactually uses: JSON request bodies or JSON responses, plus a separateTypedResultsbullet. Added a paragraph clarifying this is build-time metadata inference, notAccept-header negotiation.Locationheader — "without redirects" → "instead of a 302 redirect", with a note thatLocationis still set. The sample test now asserts the header is present; as written it would have failed.OnRedirectToLogoutandOnRedirectToReturnUrlcheckIsAjaxRequestonly, so sign-out still issues a 302.AddCookiesample and the[Authorize]/custom-handler guidance are replaced withDisableCookieRedirect(),AllowCookieRedirect(), and[AllowCookieRedirect], plus the ordering rule (IAllowCookieRedirectMetadataalways wins).Microsoft.AspNetCore.Authentication.Cookies.IgnoreRedirectMetadataswitch in bothRuntimeHostConfigurationOptionandAppContext.SetSwitchforms.breaking-changes/10/cookie-authentication-api-endpoints.mdIApiEndpointMetadata→IDisableCookieRedirectMetadata, in both the intro and "Affected APIs".IAllowCookieRedirectMetadataoverride, theLocation-header fact, and the challenge/forbid-only scope.AllowCookieRedirectAttribute, and both metadata interfaces.Correction to the issue's analysis
The issue quotes only the second metadata add site and infers that a JSON request body suppresses the metadata. There are two add sites;
factoryContext.JsonRequestBodyParameter is nullatRequestDelegateFactory.cs:1061is a de-duplication guard, not a suppression:MapPost("/x", (Todo t) => new Todo())gets the metadata exactly once. The docs use the breaking-change doc's wording, which is correct for both paths.Note on the requested
<xref>The issue asks for an
<xref>to the breaking-change article. Breaking-change articles define nouid, so this uses the repo's existing relative-URL convention (/aspnet/core/breaking-changes/10/cookie-authentication-api-endpoints). The reverse link carries?view=aspnetcore-10.0&preserve-view=truesince the conceptual article is scoped to>= aspnetcore-10.0while the breaking-change article isn't moniker-scoped.Also worth flagging for review: there is no dedicated MSBuild property for the opt-out switch in
dotnet/aspnetcore—RuntimeHostConfigurationOptionis the generic runtime-switch mechanism, which is how it's documented here.Internal previews
Build report