Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
21 changes: 16 additions & 5 deletions aspnetcore/diagnostics/asp0026.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
---
title: "ASP0026: Analyzer to warn when [Authorize] is overridden by [AllowAnonymous] from 'farther away'"
ms.date: 03/27/2025
description: "Learn about analysis rule ASP0026: [Authorize] is overridden by [AllowAnonymous] from 'farther away'"
ai-usage: ai-assisted
author: tdykstra
description: "Learn about analysis rule ASP0026: [Authorize] is overridden by [AllowAnonymous] from 'farther away'"
monikerRange: '>= aspnetcore-9.0'
ms.author: tdykstra
ms.date: 11/06/2025
uid: diagnostics/asp0026
---
# ASP0026: `[Authorize]` is overridden by `[AllowAnonymous]` from "farther away"
Expand All @@ -19,6 +20,9 @@ uid: diagnostics/asp0026

It seems intuitive that an `[Authorize]` attribute placed "closer" to an MVC action than an `[AllowAnonymous]` attribute would override the `[AllowAnonymous]` attribute and force authorization. However, this is not necessarily the case. What does matter is the relative order of the attributes.

> [!NOTE]
> The `[AllowAnonymous]` attribute doesn't disable authentication entirely. When credentials are sent to an endpoint with `[AllowAnonymous]`, the endpoint still authenticates those credentials and establishes the user's identity. The `[AllowAnonymous]` attribute only means that authentication is **not required**—the endpoint will run as anonymous only when no credentials are provided. This behavior can be useful for endpoints that need to work for both authenticated and anonymous users.

The following code shows examples where a closer `[Authorize]` attribute gets overridden by an `[AllowAnonymous]` attribute that is farther away.

```csharp
Expand Down Expand Up @@ -58,7 +62,12 @@ public class MyControllerMultiple : ControllerBase

## Rule description

Warning that an `[Authorize]` attribute is overridden by an `[AllowAnonymous]` attribute from "farther away."
This warning indicates that an `[Authorize]` attribute is overridden by an `[AllowAnonymous]` attribute from "farther away." When `[AllowAnonymous]` takes precedence, the endpoint doesn't require authentication but still accepts and processes credentials if they're provided. This means:

- If a request includes authentication credentials, the endpoint authenticates the user and makes their identity available.
- If a request doesn't include credentials, the endpoint allows anonymous access.

This behavior might unintentionally expose endpoints that were meant to require authentication.

## How to fix violations

Expand All @@ -70,8 +79,10 @@ public class MyController
{
// This produces no warning because the second, "closer" [AllowAnonymous]
// clarifies that [Authorize] is intentionally overridden.
// Specifying AuthenticationSchemes can still be useful
// for endpoints that allow but don't require authenticated users.
// Specifying AuthenticationSchemes can be useful for endpoints that
// allow but don't require authenticated users. When credentials are sent,
// they will be authenticated; when no credentials are sent, the endpoint
// allows anonymous access.
[Authorize(AuthenticationSchemes = "Cookies")]
[AllowAnonymous]
public IActionResult Privacy() => null;
Expand Down
9 changes: 7 additions & 2 deletions aspnetcore/release-notes/aspnetcore-9/includes/asp0026.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

It seems intuitive that an `[Authorize]` attribute placed "closer" to an MVC action than an `[AllowAnonymous]` attribute would override the `[AllowAnonymous]` attribute and force authorization. However, this is not necessarily the case. What does matter is the relative order of the attributes.

> [!NOTE]
> The `[AllowAnonymous]` attribute doesn't disable authentication entirely. When credentials are sent to an endpoint with `[AllowAnonymous]`, the endpoint still authenticates those credentials and establishes the user's identity. The `[AllowAnonymous]` attribute only means that authentication is **not required**—the endpoint will run as anonymous only when no credentials are provided. This behavior can be useful for endpoints that need to work for both authenticated and anonymous users.

The following code shows examples where a closer `[Authorize]` attribute gets overridden by an `[AllowAnonymous]` attribute that is farther away.

```csharp
Expand Down Expand Up @@ -53,8 +56,10 @@ public class MyController
{
// This produces no warning because the second, "closer" [AllowAnonymous]
// clarifies that [Authorize] is intentionally overridden.
// Specifying AuthenticationSchemes can still be useful
// for endpoints that allow but don't require authenticated users.
// Specifying AuthenticationSchemes can be useful for endpoints that
// allow but don't require authenticated users. When credentials are sent,
// they will be authenticated; when no credentials are sent, the endpoint
// allows anonymous access.
[Authorize(AuthenticationSchemes = "Cookies")]
[AllowAnonymous]
public IActionResult Privacy() => null;
Expand Down