How to Restrict Pages using Middleware and PageFilters

April 30th, 2025

Today's quick tip demonstrates how to limit users to a small number of pages

Restricting pages to a user on a website can be tricky. There are times when users are only allowed to view a select number of pages.

While this is easily implemented through MS Identity using the [Authorize] attribute on most pages, how could this concept apply to anonymous users?

The most relevant question is why would someone need this?

Luckily, there's a couple of ways to accomplish this and it's been available since ASP.NET Core 2.0. 

Restrict Users With IAsyncPageFilter

One way to accomplish this is with the IAsyncPageFilter class.

Razor Page Filters are implemented with the IPageFilter and IAsyncPageFilter interfaces and they run before and after the Razor Page Handler. They work similar to ActionFilters, but in addition to working on a single page, it can also apply to a larger scale of pages.

In the example below, a list of pages are contained in an array at the top of the class allowing only the Index and About page available to anyone accessing the site. If a user tries to access any other page (or even a page that doesn't exist), they're returned to the Index page.

\Filters\PageAccessFilter.cs

public class PageAccessFilter : IAsyncPageFilter
{
    private readonly string[] _allowedPages = ["/Index", "/About"];

    public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, 
PageHandlerExecutionDelegate next)     {         if (!_allowedPages.Any(p => context.ActionDescriptor.RelativePath.Contains(p)))         {             context.HttpContext.Response.Redirect("/Index");             return;         }
        await next();     }
    public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context) => Task.CompletedTask; }

In the Program.cs file, add the PageAccessFilter filter through the AddRazorPages() method.

builder.Services.AddRazorPages(options =>
{
    options.Conventions.ConfigureFilter(new PageAccessFilter());
});

While this can be used for either a page or an entire website, another alternative is to implement a Middleware component.

Restrict Users with Middleware

The Middleware version is similar and can be used in a more global manner as opposed to the PageFilter approach. The Middleware approach is a bit more enticing since it's encountered earlier in the pipeline process.

Keep in mind, a Middleware's order of operation is extremely important when adding Middleware components.

Here is the PageAccessMiddleware component

\Middleware\PageAccessMiddleware.cs

public class PageAccessMiddleware(ILogger<PageAccessMiddleware> logger, RequestDelegate next)
{
    private readonly string[] _allowedPages = ["/Index", "/About"];

    public async Task InvokeAsync(HttpContext context)     {         if (!_allowedPages.Any(p => context.Request.Path.HasValue && context.Request.Path.Value.Contains(p)))         {             context.Response.Redirect("/Index");             return;         }
        await next(context);     } }

In the Program.cs, use the UseMiddleware<PageAccessMiddleware>() method at the top of the method.

app.UseMiddleware<PageAccessMiddleware>();

Let's clean it up a bit by creating a Middleware extension method.

public static class PageAccessMiddlewareExtensions
{
    public static IApplicationBuilder UsePageAccessMiddleware(this IApplicationBuilder builder) => 
        builder.UseMiddleware<PageAccessMiddleware>();
}

Finally, replace the UseMiddleware() method with the new extension method.

app.UsePageAccessMiddleware();

Once updated, running the example displays the main page and allow access to the About page. If trying to access the Privacy page, it redirects the user to the Index page.

For additional points, instead of hard-coding an array of pages, they could easily be passed into the Middleware component.

Conclusion

In this short post, we covered a way to restrict users to a collection of pages.

Since HttpContext.Request is available in both versions, other possibilities to implement could include:

If a website has to "go down" temporarily or force users to one or more pages, PageFilters or Middleware is a simple, quick, and efficient solution.

How do you restrict users from other pages? What could be added to make the component better? Post your comments below and let's discuss.