Skip to content

Correct .NET 10 cookie redirect behavior docs for API endpoints - #37638

Merged
wadepickett merged 19 commits into
mainfrom
copilot/fix-api-endpoint-auth-dotnet-10
Sep 16, 2026
Merged

wadepickett merged 19 commits into
mainfrom
copilot/fix-api-endpoint-auth-dotnet-10

Conversation

Copilot AI commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

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 Location header is sent, described endpoint detection by registration verb, and omitted the actual opt-in/opt-out APIs entirely. The breaking-change doc referenced IApiEndpointMetadata, which was renamed before RTM and doesn't exist in the shipped product.

All claims below were verified against dotnet/aspnetcore at release/10.0, and every API doc ID against the official XML in dotnet/AspNetApiDocs.

security/authentication/api-endpoint-auth.md

  • Detection criteria — replaced "registered with MapGet, MapPost..." and "endpoints that explicitly request JSON responses" with the criteria RequestDelegateFactory actually uses: JSON request bodies or JSON responses, plus a separate TypedResults bullet. Added a paragraph clarifying this is build-time metadata inference, not Accept-header negotiation.
  • Location header — "without redirects" → "instead of a 302 redirect", with a note that Location is still set. The sample test now asserts the header is present; as written it would have failed.
  • Scope caveat — new note that only challenge (401) and forbid (403) consider metadata. OnRedirectToLogout and OnRedirectToReturnUrl check IsAjaxRequest only, so sign-out still issues a 302.
  • Configuration — the no-op AddCookie sample and the [Authorize]/custom-handler guidance are replaced with DisableCookieRedirect(), AllowCookieRedirect(), and [AllowCookieRedirect], plus the ordering rule (IAllowCookieRedirectMetadata always wins).
  • Global opt-out — documents the Microsoft.AspNetCore.Authentication.Cookies.IgnoreRedirectMetadata switch in both RuntimeHostConfigurationOption and AppContext.SetSwitch forms.
  • "Migration considerations" → "Breaking change considerations" — the "designed to be non-breaking" claim is replaced with an accurate behavioral-change statement linking the breaking-change notice.

breaking-changes/10/cookie-authentication-api-endpoints.md

  • IApiEndpointMetadataIDisableCookieRedirectMetadata, in both the intro and "Affected APIs".
  • Adds the IAllowCookieRedirectMetadata override, the Location-header fact, and the challenge/forbid-only scope.
  • "Recommended action" now leads with the global switch and the per-endpoint APIs before the manual event-override samples, which were previously the only documented escape hatch.
  • "Affected APIs" gains the convention-builder extensions, 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 null at RequestDelegateFactory.cs:1061 is a de-duplication guard, not a suppression:

// Site A (:406) — JSON request body
if (factoryContext.JsonRequestBodyParameter is not null)
{
    factoryContext.EndpointBuilder.Metadata.Add(DisableCookieRedirectMetadata.Instance);
}

// Site B (:1061) — JSON response, skipped only to avoid adding it twice
if (factoryContext.JsonRequestBodyParameter is null)
{
    builder.Metadata.Add(DisableCookieRedirectMetadata.Instance);
}

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 no uid, 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=true since the conceptual article is scoped to >= aspnetcore-10.0 while 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/aspnetcoreRuntimeHostConfigurationOption is the generic runtime-switch mechanism, which is how it's documented here.


Internal previews

File Preview link
aspnetcore/breaking-changes/10/cookie-authentication-api-endpoints.md Learn preview
aspnetcore/security/authentication/api-endpoint-auth.md Learn preview

Build report

Copilot AI linked an issue Sep 15, 2026 that may be closed by this pull request
@wadepickett wadepickett changed the title [WIP] Fix API endpoint authentication behavior for .NET 10 [WIP] Update API endpoint authentication behavior Sep 15, 2026
Copilot AI and others added 2 commits September 15, 2026 00:49
Co-authored-by: wadepickett <10985336+wadepickett@users.noreply.github.com>
Co-authored-by: wadepickett <10985336+wadepickett@users.noreply.github.com>
Copilot AI changed the title [WIP] Update API endpoint authentication behavior Correct .NET 10 cookie redirect behavior docs for API endpoints Sep 15, 2026
Copilot AI requested a review from wadepickett September 15, 2026 00:54
@wadepickett
wadepickett marked this pull request as ready for review September 15, 2026 15:17
@wadepickett
wadepickett requested a lite review from Copilot September 15, 2026 15:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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 Location header 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. Add RequireAuthorization() (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 the DisableCookieRedirect example 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. Add RequireAuthorization() (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 the AllowCookieRedirect override 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-returning MapGet can still redirect, even in an API-only app. Qualify this to API endpoints that meet the automatic detection criteria, and point readers to DisableCookieRedirect for 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.

Comment thread aspnetcore/security/authentication/api-endpoint-auth.md Outdated
Comment thread aspnetcore/security/authentication/api-endpoint-auth.md Outdated
@wadepickett
wadepickett requested a lite review from Copilot September 15, 2026 15:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 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 is OnRedirectToLogout). 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 Location header 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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 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

  • ReportSummary is 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

  • AllowCookieRedirect cannot 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

  • AllowCookieRedirect controls 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

  • OnRedirectToReturnUrl handles the post-logout return redirect, but sign-out itself invokes OnRedirectToLogout, 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 DisableCookieRedirect call 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

  • ReportSummary is not declared anywhere in the article, and this endpoint has no authorization requirement, so the snippet both fails to compile and cannot exercise AllowCookieRedirect. 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 ReportSummary type, 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

  • AllowCookieRedirect only 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.
@wadepickett
wadepickett requested a lite review from Copilot September 15, 2026 20:42
Comment thread aspnetcore/security/authentication/api-endpoint-auth.md Outdated
Split up dense paragraph.

@wadepickett wadepickett left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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, or IResult aren't automatically marked, and the next section requires DisableCookieRedirect for 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

Comment thread aspnetcore/breaking-changes/10/cookie-authentication-api-endpoints.md Outdated
Comment thread aspnetcore/security/authentication/api-endpoint-auth.md Outdated
wadepickett and others added 2 commits September 16, 2026 08:36
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>

Copilot AI commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

🟡 Changes recommended

Address the outstanding date metadata and status-code guidance findings....

Addressed all findings in this review. Both files use ms.date: 09/16/2026, and commit 8b81e6a qualifies the API-only guidance to detected API endpoints.

@meaghanlewis meaghanlewis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes LGTM @wadepickett

@wadepickett
wadepickett merged commit 72e83ce into main Sep 16, 2026
5 checks passed
@wadepickett
wadepickett deleted the copilot/fix-api-endpoint-auth-dotnet-10 branch September 16, 2026 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

API Endpoint Auth: Verify updated for .NET 10 - Freshness

4 participants