Analyzer to warn when [Authorize] is overridden by [AllowAnymous] from "farther" away #56310
Description
Background and Motivation
A lot of people don't realize that the relative order of [Authorize]
and [AllowAnonymous]
does not matter, and incorrectly assume that if they put [Authorize]
"closer" to an MVC action than [AllowAnonymous]
, that it will still force authorization. The following code shows examples of where a closer [Authorize]
attribute gets overridden by an [AllowAnonymous]
attribute that is further away.
[AllowAnonymous]
public class OAuthControllerAnon : ControllerBase
{
}
[Authorize]
public class OAuthControllerAuthz : ControllerBase
{
}
[Authorize] // BUG
public class OAuthControllerInherited : OAuthControllerAnon
{
}
public class OAuthControllerInherited2 : OAuthControllerAnon
{
[Authorize] // BUG
public IActionResult Privacy() => null;
}
[AllowAnonymous]
[Authorize] // BUG
public class OAuthControllerMultiple : ControllerBase
{
}
[AllowAnonymous]
public class OAuthControllerInherited3 : ControllerBase
{
[Authorize] // BUG
public IActionResult Privacy() => null;
}
Proposed Analyzer
Title
[Authorize] overridden by [AllowAnonymous] from farther away
Message
This [Authorize] attribute is overridden by an [AllowAnonymous] attribute from farther away on '{0}'. See https://aka.ms/aspnetcore-warnings/ASP0026 for more details.
And then https://aka.ms/aspnetcore-warnings/ASP0026 would point to documentation explaining.
- When authorization is run, [AllowAnonymous] takes precedence over [Authorize]. If both are present, then authorization doesn't run.
- MVC actions inherit metadata from the controller. And controllers inherit metadata from base controls.
- Investigate your controllers and actions and decide whether to remove the [Authorize] attribute or move where the [AllowAnonymous] attribute is placed.
Category
- Design
- Documentation
- Globalization
- Interoperability
- Maintainability
- Naming
- Performance
- Reliability
- Security
- Style
- Usage
Severity Level
- Error
- Warning
- Info
- Hidden
Risks
This could have some false positives where [Authorize]
and [AllowAnonymous]
were intended to be used together like when specifying an authentication scheme (e.g. [Authorize(AuthenticationSchemes = “Cookies”)]
). No analyzer can catch every accidental application of [AllowAnonymous]
, but false positives and negatives can be mitigated by making the analyzer more or less conservative as need be.