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
15 changes: 12 additions & 3 deletions aspnetcore/fundamentals/error-handling-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: Learn about error handling in ASP.NET Core APIs with Minimal APIs a
ai-usage: ai-assisted
ms.author: wpickett
monikerRange: '>= aspnetcore-7.0'
ms.date: 08/15/2025
ms.date: 03/04/2026
uid: fundamentals/error-handling-api
---

Expand Down Expand Up @@ -139,9 +139,18 @@ In the following code, `httpContext.Response.WriteAsync("Fallback: An error occu

The preceding code:

* Writes an error message with the fallback code if the `problemDetailsService` is unable to write a `ProblemDetails`. For example, an endpoint where the [Accept request header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Accept) specifies a media type that the `DefaulProblemDetailsWriter` does not support.
* Writes an error message with the fallback code if the `problemDetailsService` is unable to write a `ProblemDetails`. For example, an endpoint where the [Accept request header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Accept) specifies a media type that the `DefaultProblemDetailsWriter` does not support.
* Uses the [Exception Handler Middleware](#exception-handler).

> [!NOTE]
> The `DefaultProblemDetailsWriter` supports the following media types in the `Accept` request header:
>
> * `application/json`
> * `application/problem+json`
> * Wildcard types such as `*/*` and `application/*`
>
> Non-JSON media types, such as `application/xml` or `text/html`, are **not** supported and trigger the fallback behavior.

The following sample is similar to the preceding except that it calls the [`Status Code Pages middleware`](#client-and-server-error-responses).

:::code language="csharp" source="~/fundamentals/minimal-apis/handle-errors/sample8/Program.cs" id="snippet_IProblemDetailsServiceWithStatusCodePageFallback" highlight="15":::
Expand Down Expand Up @@ -255,4 +264,4 @@ The contents of the response can be modified from outside of the controller usin

* [How to Use ModelState Validation in ASP.NET Core Web API](https://code-maze.com/aspnetcore-modelstate-validation-web-api/)
* [View or download sample code](https://github.com/dotnet/AspNetCore.Docs.Samples/tree/main/fundamentals/middleware/problem-details-service)
* [Hellang.Middleware.ProblemDetails](https://www.nuget.org/packages/Hellang.Middleware.ProblemDetails/)
* [Hellang.Middleware.ProblemDetails](https://www.nuget.org/packages/Hellang.Middleware.ProblemDetails/)
1 change: 0 additions & 1 deletion aspnetcore/includes/requireAuth.md

This file was deleted.

83 changes: 83 additions & 0 deletions aspnetcore/mvc/security/authorization/simple.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
title: Simple authorization in ASP.NET Core MVC
ai-usage: ai-assisted
author: tdykstra
description: Learn how to use the [Authorize] attribute to restrict access in ASP.NET Core MVC apps.
ms.author: tdykstra
ms.date: 03/05/2026
uid: mvc/security/authorization/simple
---
# Simple authorization in ASP.NET Core MVC

Authorization in ASP.NET Core is controlled with the [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) and its various parameters. In its most basic form, applying the `[Authorize]` attribute to a Razor component, controller, action, or Razor Page, limits access to that component to authenticated users.

This article covers scenarios that pertain to MVC apps. For the primary coverage on this subject, see <xref:security/authorization/simple>.

## `[Authorize]` attribute

The following example limits access to authenticated users by specifying the [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute):

```csharp
[Authorize]
public class AccountController : Controller
{
public ActionResult Login() { ... }
public ActionResult Logout() { ... }
}
```

The [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) also supports role-based or policy-based authorization. For role-based authorization, use the <xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute.Roles> parameter. In the following example, the user can only access the page if they're in the `Admin` or `Superuser` role:

```csharp
[Authorize(Roles = "Admin, Superuser")]
public class OrderController : Controller
{
...
}
```

For policy-based authorization, use the <xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute.Policy> parameter. In the following example, the user can only access the page if they satisfy the requirements of the `Over21` [authorization policy](xref:security/authorization/policies):

```csharp
[Authorize(Policy = "Over21")]
public class LicenseApplicationController : Controller
{
...
}
```

If neither <xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute.Roles> nor <xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute.Policy> is specified, [`[Authorize]`](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) uses the default policy:

* Authenticated (signed-in) users are authorized.
* Unauthenticated (signed-out) users are unauthorized.

To apply authorization to an action rather than the controller, apply the [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) to the action. In the following example, only authenticated users can trigger a logout (call the `Logout` method):

```csharp
public class AccountController : Controller
{
public ActionResult Login() { ... }

[Authorize]
public ActionResult Logout() { ... }
}
```

Use the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute) to allow access by non-authenticated users to individual actions:

```csharp
[AllowAnonymous]
```

> [!WARNING]
> For MVC controllers, the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute) bypasses authorization statements. If you combine `[AllowAnonymous]` and one or more `[Authorize]` attributes, the `[Authorize]` attributes are ignored. If you apply `[AllowAnonymous]` at the controller level:
>
> * Any authorization requirements from `[Authorize]` attributes on the same controller or action methods on the controller are ignored.
> * Authentication middleware isn't short-circuited but doesn't need to succeed.

For information on how to require authentication for all app users, see <xref:security/authorization/secure-data#require-authenticated-users>.

## Additional resources

* <xref:security/authorization/simple>
* <xref:razor-pages/security/authorization/simple>
2 changes: 1 addition & 1 deletion aspnetcore/razor-pages/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ Add <xref:Microsoft.Extensions.DependencyInjection.MvcRazorPagesMvcCoreBuilderEx
## Additional resources

* See [Get started with Razor Pages](xref:tutorials/razor-pages/razor-pages-start), which builds on this introduction.
* [Authorize attribute and Razor Pages](xref:security/authorization/simple#aarp)
* [`[Authorize]` attribute in Razor Pages apps](xref:razor-pages/security/authorization/simple#authorize-attribute-in-razor-pages-apps)
* [Download or view sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/razor-pages/index/6.0sample)
* <xref:index>
* <xref:mvc/views/razor>
Expand Down
2 changes: 1 addition & 1 deletion aspnetcore/razor-pages/index/includes/index35.md
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ Add <xref:Microsoft.Extensions.DependencyInjection.MvcRazorPagesMvcCoreBuilderEx
## Additional resources

* See [Get started with Razor Pages](xref:tutorials/razor-pages/razor-pages-start), which builds on this introduction.
* [Authorize attribute and Razor Pages](xref:security/authorization/simple#aarp)
* [`[Authorize]` attribute in Razor Pages apps](xref:razor-pages/security/authorization/simple#authorize-attribute-in-razor-pages-apps)
* [Download or view sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/razor-pages/index/3.0sample)
* <xref:index>
* <xref:mvc/views/razor>
Expand Down
177 changes: 177 additions & 0 deletions aspnetcore/razor-pages/security/authorization/simple.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
---
title: Simple authorization in ASP.NET Core Razor Pages
ai-usage: ai-assisted
author: tdykstra
description: Learn how to use the [Authorize] attribute to restrict access in ASP.NET Core Razor Pages apps.
ms.author: tdykstra
ms.date: 03/05/2026
uid: razor-pages/security/authorization/simple
---
# Simple authorization in ASP.NET Core Razor Pages

Authorization in ASP.NET Core is controlled with the [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) and its various parameters. In its most basic form, applying the `[Authorize]` attribute to a Razor component, controller, action, or Razor Page, limits access to that component to authenticated users.

This article covers scenarios that pertain to Razor Pages apps. For more information, see <xref:security/authorization/simple>.

## `[Authorize]` attribute

Apply the [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) to the page model class that derives from <xref:Microsoft.AspNetCore.Mvc.RazorPages.PageModel>. In the following example, only authenticated users can reach the `LogoutModel` page:

```csharp
[Authorize]
public class LogoutModel : PageModel
{
public async Task OnGetAsync() { ... }
public async Task<IActionResult> OnPostAsync() { ... }
}
```

The [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) also supports role-based or policy-based authorization. For role-based authorization, use the <xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute.Roles> parameter. In the following example, the user can only access the page if they're in the `Admin` or `Superuser` role:

```csharp
[Authorize(Roles = "Admin, Superuser")]
public class OrderModel : PageModel
{
...
}
```

For policy-based authorization, use the <xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute.Policy> parameter. In the following example, the user can only access the page if they satisfy the requirements of the `Over21` [authorization policy](xref:security/authorization/policies):

```csharp
[Authorize(Policy = "Over21")]
public class LicenseApplicationModel : PageModel
{
...
}
```

If neither <xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute.Roles> nor <xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute.Policy> is specified, [`[Authorize]`](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) uses the default policy:

* Authenticated (signed-in) users are authorized.
* Unauthenticated (signed-out) users are unauthorized.

For guidance on <xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute> and Razor Page handlers, see the [`[Authorize]` attribute in Razor Pages apps](#authorize-attribute-in-razor-pages-apps) section.

Use the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute) to allow access by non-authenticated users to individual actions:

```csharp
[AllowAnonymous]
```

For information on how to require authentication for all app users, see <xref:security/authorization/secure-data#require-authenticated-users>.

## `[Authorize]` attribute in Razor Pages apps

The <xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute> can't be applied to Razor Page handlers. For example, the [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) can't be applied to `OnGet`, `OnPost`, or any other page handler. In a Razor Pages app, consider using an ASP.NET Core MVC controller for pages with different authorization requirements for different handlers. Using a controller when different authorization requirements are required is the least complex approach we recommend.

If you decide not to use an MVC controller, the following two approaches can be used to apply authorization to Razor Page handler methods:

* Use separate pages for page handlers requiring different authorization. Move shared content into one or more [partial views](xref:mvc/views/partial). When possible, this is the recommended approach.
* For content that must share a common page, write a filter that performs authorization as part of <xref:Microsoft.AspNetCore.Mvc.Filters.IAsyncPageFilter.OnPageHandlerExecutionAsync%2A?displayProperty=nameWithType>. This approach is demonstrated by the following example.

The `AuthorizeIndexPageHandlerFilter` implements the authorization filter:

```csharp
public class AuthorizeIndexPageHandlerFilter(
IAuthorizationPolicyProvider policyProvider,
IPolicyEvaluator policyEvaluator) : IAsyncPageFilter, IOrderedFilter
{
private readonly IAuthorizationPolicyProvider policyProvider =
policyProvider;
private readonly IPolicyEvaluator policyEvaluator = policyEvaluator;

// Run late in the execution pipeline
public int Order => 10000;

public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context,
PageHandlerExecutionDelegate next)
{
var attribute = context.HandlerMethod?.MethodInfo?
.GetCustomAttribute<AuthorizePageHandlerAttribute>();

if (attribute is null)
{
await next();
return;
}

var policy = await AuthorizationPolicy
.CombineAsync(policyProvider, new[] { attribute });

if (policy is null)
{
await next();
return;
}

var httpContext = context.HttpContext;
var authenticateResult = await policyEvaluator
.AuthenticateAsync(policy, httpContext);
var authorizeResult = await policyEvaluator
.AuthorizeAsync(policy, authenticateResult, httpContext,
context.ActionDescriptor);

if (authorizeResult.Challenged)
{
context.Result = policy.AuthenticationSchemes.Count > 0
? new ChallengeResult(policy.AuthenticationSchemes.ToArray())
: new ChallengeResult();

return;
}
else if (authorizeResult.Forbidden)
{
context.Result = policy.AuthenticationSchemes.Count > 0
? new ForbidResult(policy.AuthenticationSchemes.ToArray())
: new ForbidResult();

return;
}

await next();
}

public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
=> Task.CompletedTask;
}
```

The `AuthorizePageHandlerAttribute` provides an `[AuthorizePageHandler]` attribute to the app:

```csharp
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class AuthorizePageHandlerAttribute(string policy = null)
: Attribute, IAuthorizeData
{
public string Policy { get; set; } = policy;
public string Roles { get; set; }
public string AuthenticationSchemes { get; set; }
}
```

The `[AuthorizePageHandler]` attribute is applied to page handlers. In the following example, the attribute is set on the `OnPostAuthorized` page handler:

```csharp
[TypeFilter(typeof(AuthorizeIndexPageHandlerFilter))]
public class IndexModel : PageModel
{
...

[AuthorizePageHandler]
public void OnPostAuthorized() { ... }
}
```

> [!WARNING]
> The preceding approach does ***not***:
>
> * Compose with authorization attributes applied to the page, page model, or globally. Composing authorization attributes results in authentication and authorization executing multiple times when you have one more [`[Authorize]` attributes](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) or <xref:Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter> instances also applied to the page.
> * Work in conjunction with the rest of the ASP.NET Core authentication and authorization system. Verify that this approach works correctly for the app.

There are no plans to support the [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) on Razor Page handlers.

## Additional resources

* <xref:security/authorization/simple>
* <xref:mvc/security/authorization/simple>
4 changes: 2 additions & 2 deletions aspnetcore/security/authentication/identity-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ builder.Services.Configure<PasswordHasherOptions>(option =>

## Globally require all users to be authenticated

[!INCLUDE[](~/includes/requireAuth.md)]
For information on how to require authentication for all app users, see <xref:security/authorization/secure-data#require-authenticated-users>.

<a name="iss6"></a>

Expand Down Expand Up @@ -296,6 +296,6 @@ services.Configure<PasswordHasherOptions>(option =>

## Globally require all users to be authenticated

[!INCLUDE[](~/includes/requireAuth.md)]
For information on how to require authentication for all app users, see <xref:security/authorization/secure-data#require-authenticated-users>.

:::moniker-end
2 changes: 1 addition & 1 deletion aspnetcore/security/authentication/identity.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ ASP.NET Core Identity:

Users can create an account with the login information stored in Identity or they can use an external login provider. Supported external login providers include [Facebook, Google, Microsoft Account, and Twitter](xref:security/authentication/social/index).

[!INCLUDE[](~/includes/requireAuth.md)]
For information on how to require authentication for all app users, see <xref:security/authorization/secure-data#require-authenticated-users>.

The [Identity source code](https://github.com/dotnet/AspNetCore/tree/main/src/Identity) is available on GitHub. [Scaffold Identity](xref:security/authentication/scaffold-identity) and view the generated files to review the template interaction with Identity.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ ASP.NET Core Identity:

Users can create an account with the login information stored in Identity or they can use an external login provider. Supported external login providers include [Facebook, Google, Microsoft Account, and Twitter](xref:security/authentication/social/index).

[!INCLUDE[](~/includes/requireAuth.md)]
For information on how to require authentication for all app users, see <xref:security/authorization/secure-data#require-authenticated-users>.

The [Identity source code](https://github.com/dotnet/AspNetCore/tree/main/src/Identity) is available on GitHub. [Scaffold Identity](xref:security/authentication/scaffold-identity) and view the generated files to review the template interaction with Identity.

Expand Down Expand Up @@ -258,7 +258,7 @@ ASP.NET Core Identity:

Users can create an account with the login information stored in Identity or they can use an external login provider. Supported external login providers include [Facebook, Google, Microsoft Account, and Twitter](xref:security/authentication/social/index).

[!INCLUDE[](~/includes/requireAuth.md)]
For information on how to require authentication for all app users, see <xref:security/authorization/secure-data#require-authenticated-users>.

The [Identity source code](https://github.com/dotnet/AspNetCore/tree/main/src/Identity) is available on GitHub. [Scaffold Identity](xref:security/authentication/scaffold-identity) and view the generated files to review the template interaction with Identity.

Expand Down
Loading
Loading