Authorization in ASP .NET Core Razor pages
Razor Pages doesn't support [Authorize]
at the handler level. i.e. You can only authorise a page as a whole, on the PageModel
itself, as noted in the docs:
Policies can not be applied at the Razor Page handler level, they must be applied to the Page.
If authorising the page as a whole isn't a workable solution, you might need to move your OnGetCreateAsync
handler into a controller/action pair, which can be attributed with [Authorize]
accordingly.
There's also a related GitHub issue in the docs for this:
The
[Authorize]
filter attribute has been supported since 2.0 in Razor Pages, but note that it works at the page model class level
If you need a better workaround, see akbar's answer and Jim Yabro's answer.
Another solution for it is to check authentication by if clause.like this:
if (!HttpContext.User.Identity.IsAuthenticated)
{
return Redirect("/Front/Index");
}
and you can check roles
in it too by finding role:
var user = await _userManager.FindByEmailAsync(model.Email);
var roles = await _userManager.GetRolesAsync(user);
I would recommend following Razor Pages authorization conventions in ASP.NET Core that looks like this:
services.AddRazorPages(options =>
{
options.Conventions.AuthorizePage("/Contact");
options.Conventions.AuthorizeFolder("/Private");
options.Conventions.AllowAnonymousToPage("/Private/PublicPage");
options.Conventions.AllowAnonymousToFolder("/Private/PublicPages");
});
In your case with policy test
it would look like this:
options.Conventions.AuthorizePage("/Account", "test");
Source:
https://docs.microsoft.com/en-us/aspnet/core/security/authorization/razor-pages-authorization?view=aspnetcore-5.0
Authorize attribute is supported but only on PageModel
like this:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace PageFilter.Pages
{
[Authorize]
public class ModelWithAuthFilterModel : PageModel
{
public IActionResult OnGet() => Page();
}
}
Source:
https://docs.microsoft.com/en-us/aspnet/core/razor-pages/filter?view=aspnetcore-5.0#authorize-filter-attribute
Don't use the AuthorizeAttribute
since it's unsupported.
Instead, once you have configured your policies in Startup.cs
, you will be able to check those policies from within the page handlers.
- Inject
IAuthorizationService
into your page model constructor - Call
AuthorizeAsync()
from within the handler. - Run a conditional check on the result's
.Succeeded
property. - If
.Succeeded
is false, return aForbid()
result.
This has nearly the same result as the [Authorize(Policy=...)]
but executes later in the page lifecycle.
using Microsoft.AspNetCore.Authorization;
// ...
public class TestPageModel : PageModel {
readonly IAuthorizationService AuthorizationService;
public TestPageModel(IAuthorizationService authorizationService) {
AuthorizationService= authorizationService;
}
// Everyone can see this handler.
public void OnGet() { }
// Everyone can access this handler, but will be rejected after the check.
public async Task<IActionResult> OnPostAsync() {
// This is your policy you've defined in Startup.cs
var policyCheck = await AuthorizationService.AuthorizeAsync(User, "test");
// Check the result, and return a forbid result to the user if failed.
if (!policyCheck.Succeeded) {
return Forbid();
}
// ...
return Page(); // Or RedirectToPage etc
}
}