Skip to content

Add documentation for .NET 10 API endpoint authentication behavior changes #35895

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions aspnetcore/fundamentals/minimal-apis/responses.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ uid: fundamentals/minimal-apis/responses

[!INCLUDE[](~/includes/not-latest-version.md)]

This article explains how to create responses for minimal API endpoints in ASP.NET Core. Minimal APIs provide several ways to return data and HTTP status codes.

:::moniker range=">= aspnetcore-10.0"

Minimal endpoints support the following types of return values:
Expand All @@ -20,6 +22,8 @@ Minimal endpoints support the following types of return values:
1. `T` (Any other type) - This includes `Task<T>` and `ValueTask<T>`.
1. `IResult` based - This includes `Task<IResult>` and `ValueTask<IResult>`.

[!INCLUDE[](~/includes/api-endpoint-auth.md)]

## `string` return values

|Behavior|Content-Type|
Expand Down
2 changes: 2 additions & 0 deletions aspnetcore/includes/api-endpoint-auth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
> [!IMPORTANT]
> Starting with ASP.NET Core 10, known API endpoints no longer redirect to login pages when using cookie authentication. Instead, they return 401/403 status codes. For details, see <xref:security/authentication/api-endpoint-auth>.
109 changes: 109 additions & 0 deletions aspnetcore/security/authentication/api-endpoint-auth.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
---
title: API endpoint authentication behavior in ASP.NET Core
author: wadepickett
description: Learn how ASP.NET Core 10 and later handles authentication failures for API endpoints using cookie authentication.
ai-usage: ai-assisted
monikerRange: '>= aspnetcore-10.0'
ms.author: wpickett
ms.date: 08/06/2025
uid: security/authentication/api-endpoint-auth
---

# API endpoint authentication behavior in ASP.NET Core

:::moniker range=">= aspnetcore-10.0"

Starting with ASP.NET Core 10, the framework introduces a significant improvement in how authentication failures are handled for API endpoints when using cookie authentication. This change addresses the common issue where API endpoints would redirect unauthenticated requests to login pages, which is inappropriate for programmatic API access.

## The problem

In previous versions of ASP.NET Core, when using cookie authentication, all unauthenticated requests would trigger a redirect to the configured login page. This behavior was problematic for API endpoints because:

- API clients don't expect HTML login pages
- Redirects return 302 status codes instead of proper 401/403 codes
- API clients need clear HTTP status codes to handle authentication failures appropriately

## The solution in ASP.NET Core 10

ASP.NET Core 10 automatically detects known API endpoints and modifies the authentication behavior:

- **Web pages**: Continue to redirect to login pages as before
- **API endpoints**: Return appropriate 401 (Unauthorized) or 403 (Forbidden) status codes without redirects

## Which endpoints are considered API endpoints?

The framework automatically identifies the following as API endpoints:

- Controllers decorated with `[ApiController]` attribute
- Minimal API endpoints registered with `MapGet`, `MapPost`, `MapPut`, `MapDelete`, etc.
- Endpoints that explicitly request JSON responses
- SignalR hubs and endpoints

## Behavior differences

### Before ASP.NET Core 10

```http
GET /api/secure-data HTTP/1.1
Host: example.com

HTTP/1.1 302 Found
Location: /Account/Login?ReturnUrl=%2Fapi%2Fsecure-data
```

### ASP.NET Core 10 and later

```http
GET /api/secure-data HTTP/1.1
Host: example.com

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Cookie
```

## Configuring the behavior

While the default behavior works for most scenarios, you can customize it if needed:

```csharp
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/Account/Login";
// The framework automatically handles API endpoints
// No additional configuration needed
});
```

If you need to override the automatic detection for specific endpoints, you can use the `[Authorize]` attribute with specific authentication schemes or implement custom authentication handlers.

## Migration considerations

This change is designed to be non-breaking for existing applications:

- **Web applications**: Continue to work as before with login page redirects
- **Mixed applications**: API endpoints get proper status codes while web pages get redirects
- **API-only applications**: Benefit from proper HTTP status codes without additional configuration

### Testing your API endpoints

After upgrading to ASP.NET Core 10, verify that your API endpoints return appropriate status codes:

```csharp
[Test]
public async Task UnauthorizedApiRequest_Returns401()
{
var response = await client.GetAsync("/api/secure-data");
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
Assert.False(response.Headers.Location != null); // No redirect
}
```

## Related topics

- <xref:security/authentication/cookie>
- <xref:web-api/index>
- <xref:fundamentals/minimal-apis/responses>
- <xref:signalr/authn-and-authz>

:::moniker-range-end
4 changes: 4 additions & 0 deletions aspnetcore/security/authentication/cookie.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ By [Rick Anderson](https://twitter.com/RickAndMSFT)

For demonstration purposes in the sample app, the user account for the hypothetical user, Maria Rodriguez, is hardcoded into the app. Use the **Email** address `[email protected]` and any password to sign in the user. The user is authenticated in the `AuthenticateUser` method in the `Pages/Account/Login.cshtml.cs` file. In a real-world example, the user would be authenticated against a datastore.

:::moniker range=">= aspnetcore-10.0"
[!INCLUDE[](~/includes/api-endpoint-auth.md)]
:::moniker-end

## Add cookie authentication

* Add the Authentication Middleware services with the <xref:Microsoft.Extensions.DependencyInjection.AuthenticationServiceCollectionExtensions.AddAuthentication%2A> and <xref:Microsoft.Extensions.DependencyInjection.CookieExtensions.AddCookie%2A> methods.
Expand Down
4 changes: 4 additions & 0 deletions aspnetcore/signalr/authn-and-authz.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ uid: signalr/authn-and-authz

## Authenticate users connecting to a SignalR hub

:::moniker range=">= aspnetcore-10.0"
[!INCLUDE[](~/includes/api-endpoint-auth.md)]
:::moniker-end

SignalR can be used with [ASP.NET Core authentication](xref:security/authentication/identity) to associate a user with each connection. In a hub, authentication data can be accessed from the <xref:Microsoft.AspNetCore.SignalR.HubConnectionContext.User?displayProperty=nameWithType> property. Authentication allows the hub to call methods on all connections associated with a user. For more information, see [Manage users and groups in SignalR](xref:signalr/groups). Multiple connections may be associated with a single user.

The following code is an example that uses SignalR and ASP.NET Core authentication:
Expand Down
4 changes: 4 additions & 0 deletions aspnetcore/web-api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ ASP.NET Core supports creating web APIs using controllers or using minimal APIs.

This article shows how to use controllers for handling web API requests. For information on creating web APIs without controllers, see <xref:tutorials/min-web-api>.

:::moniker range=">= aspnetcore-10.0"
[!INCLUDE[](~/includes/api-endpoint-auth.md)]
:::moniker-end

## ControllerBase class

A controller-based web API consists of one or more controller classes that derive from <xref:Microsoft.AspNetCore.Mvc.ControllerBase>. The web API project template provides a starter controller:
Expand Down
Loading