|
| 1 | +--- |
| 2 | +title: Simple authorization in ASP.NET Core Razor Pages |
| 3 | +ai-usage: ai-assisted |
| 4 | +author: tdykstra |
| 5 | +description: Learn how to use the [Authorize] attribute to restrict access in ASP.NET Core Razor Pages apps. |
| 6 | +ms.author: tdykstra |
| 7 | +ms.date: 03/05/2026 |
| 8 | +uid: razor-pages/security/authorization/simple |
| 9 | +--- |
| 10 | +# Simple authorization in ASP.NET Core Razor Pages |
| 11 | + |
| 12 | +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. |
| 13 | + |
| 14 | +This article covers scenarios that pertain to Razor Pages apps. For more information, see <xref:security/authorization/simple>. |
| 15 | + |
| 16 | +## `[Authorize]` attribute |
| 17 | + |
| 18 | +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: |
| 19 | + |
| 20 | +```csharp |
| 21 | +[Authorize] |
| 22 | +public class LogoutModel : PageModel |
| 23 | +{ |
| 24 | + public async Task OnGetAsync() { ... } |
| 25 | + public async Task<IActionResult> OnPostAsync() { ... } |
| 26 | +} |
| 27 | +``` |
| 28 | + |
| 29 | +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: |
| 30 | + |
| 31 | +```csharp |
| 32 | +[Authorize(Roles = "Admin, Superuser")] |
| 33 | +public class OrderModel : PageModel |
| 34 | +{ |
| 35 | + ... |
| 36 | +} |
| 37 | +``` |
| 38 | + |
| 39 | +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): |
| 40 | + |
| 41 | +```csharp |
| 42 | +[Authorize(Policy = "Over21")] |
| 43 | +public class LicenseApplicationModel : PageModel |
| 44 | +{ |
| 45 | + ... |
| 46 | +} |
| 47 | +``` |
| 48 | + |
| 49 | +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: |
| 50 | + |
| 51 | +* Authenticated (signed-in) users are authorized. |
| 52 | +* Unauthenticated (signed-out) users are unauthorized. |
| 53 | + |
| 54 | +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. |
| 55 | + |
| 56 | +Use the [`[AllowAnonymous]` attribute](xref:Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute) to allow access by non-authenticated users to individual actions: |
| 57 | + |
| 58 | +```csharp |
| 59 | +[AllowAnonymous] |
| 60 | +``` |
| 61 | + |
| 62 | +For information on how to require authentication for all app users, see <xref:security/authorization/secure-data#require-authenticated-users>. |
| 63 | + |
| 64 | +## `[Authorize]` attribute in Razor Pages apps |
| 65 | + |
| 66 | +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. |
| 67 | + |
| 68 | +If you decide not to use an MVC controller, the following two approaches can be used to apply authorization to Razor Page handler methods: |
| 69 | + |
| 70 | +* 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. |
| 71 | +* 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. |
| 72 | + |
| 73 | +The `AuthorizeIndexPageHandlerFilter` implements the authorization filter: |
| 74 | + |
| 75 | +```csharp |
| 76 | +public class AuthorizeIndexPageHandlerFilter( |
| 77 | + IAuthorizationPolicyProvider policyProvider, |
| 78 | + IPolicyEvaluator policyEvaluator) : IAsyncPageFilter, IOrderedFilter |
| 79 | +{ |
| 80 | + private readonly IAuthorizationPolicyProvider policyProvider = |
| 81 | + policyProvider; |
| 82 | + private readonly IPolicyEvaluator policyEvaluator = policyEvaluator; |
| 83 | + |
| 84 | + // Run late in the execution pipeline |
| 85 | + public int Order => 10000; |
| 86 | + |
| 87 | + public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, |
| 88 | + PageHandlerExecutionDelegate next) |
| 89 | + { |
| 90 | + var attribute = context.HandlerMethod?.MethodInfo? |
| 91 | + .GetCustomAttribute<AuthorizePageHandlerAttribute>(); |
| 92 | + |
| 93 | + if (attribute is null) |
| 94 | + { |
| 95 | + await next(); |
| 96 | + return; |
| 97 | + } |
| 98 | + |
| 99 | + var policy = await AuthorizationPolicy |
| 100 | + .CombineAsync(policyProvider, new[] { attribute }); |
| 101 | + |
| 102 | + if (policy is null) |
| 103 | + { |
| 104 | + await next(); |
| 105 | + return; |
| 106 | + } |
| 107 | + |
| 108 | + var httpContext = context.HttpContext; |
| 109 | + var authenticateResult = await policyEvaluator |
| 110 | + .AuthenticateAsync(policy, httpContext); |
| 111 | + var authorizeResult = await policyEvaluator |
| 112 | + .AuthorizeAsync(policy, authenticateResult, httpContext, |
| 113 | + context.ActionDescriptor); |
| 114 | + |
| 115 | + if (authorizeResult.Challenged) |
| 116 | + { |
| 117 | + context.Result = policy.AuthenticationSchemes.Count > 0 |
| 118 | + ? new ChallengeResult(policy.AuthenticationSchemes.ToArray()) |
| 119 | + : new ChallengeResult(); |
| 120 | + |
| 121 | + return; |
| 122 | + } |
| 123 | + else if (authorizeResult.Forbidden) |
| 124 | + { |
| 125 | + context.Result = policy.AuthenticationSchemes.Count > 0 |
| 126 | + ? new ForbidResult(policy.AuthenticationSchemes.ToArray()) |
| 127 | + : new ForbidResult(); |
| 128 | + |
| 129 | + return; |
| 130 | + } |
| 131 | + |
| 132 | + await next(); |
| 133 | + } |
| 134 | + |
| 135 | + public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) |
| 136 | + => Task.CompletedTask; |
| 137 | +} |
| 138 | +``` |
| 139 | + |
| 140 | +The `AuthorizePageHandlerAttribute` provides an `[AuthorizePageHandler]` attribute to the app: |
| 141 | + |
| 142 | +```csharp |
| 143 | +[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] |
| 144 | +public class AuthorizePageHandlerAttribute(string policy = null) |
| 145 | + : Attribute, IAuthorizeData |
| 146 | +{ |
| 147 | + public string Policy { get; set; } = policy; |
| 148 | + public string Roles { get; set; } |
| 149 | + public string AuthenticationSchemes { get; set; } |
| 150 | +} |
| 151 | +``` |
| 152 | + |
| 153 | +The `[AuthorizePageHandler]` attribute is applied to page handlers. In the following example, the attribute is set on the `OnPostAuthorized` page handler: |
| 154 | + |
| 155 | +```csharp |
| 156 | +[TypeFilter(typeof(AuthorizeIndexPageHandlerFilter))] |
| 157 | +public class IndexModel : PageModel |
| 158 | +{ |
| 159 | + ... |
| 160 | + |
| 161 | + [AuthorizePageHandler] |
| 162 | + public void OnPostAuthorized() { ... } |
| 163 | +} |
| 164 | +``` |
| 165 | + |
| 166 | +> [!WARNING] |
| 167 | +> The preceding approach does ***not***: |
| 168 | +> |
| 169 | +> * 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. |
| 170 | +> * Work in conjunction with the rest of the ASP.NET Core authentication and authorization system. Verify that this approach works correctly for the app. |
| 171 | +
|
| 172 | +There are no plans to support the [`[Authorize]` attribute](xref:Microsoft.AspNetCore.Authorization.AuthorizeAttribute) on Razor Page handlers. |
| 173 | + |
| 174 | +## Additional resources |
| 175 | + |
| 176 | +* <xref:security/authorization/simple> |
| 177 | +* <xref:mvc/security/authorization/simple> |
0 commit comments