Require authorization on ALL Blazor pages
Asked Answered
A

3

36

I am playing with Blazor and created a web app that is server hosted. I have to put an authorize line on top of the page like this @attribute [Authorize] to ensure the user is logged in.

It seems like I have to add this line to each page individually. Is there a global setting that protects ALL the pages in the app, except for the login page of course.

Allocate answered 14/3, 2020 at 22:26 Comment(1)
Can't you just put your Authorize component in the Layout Page? The default MVC login system doesn't use that layout page, I'm pretty sure.Briscoe
H
56

I believe that will work... Place the following code snippet in the _Imports.razor file

@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]

In that case, when the Index page is hit, the user will be redirected to the Login page. If you want to perform authentication before the Blazor App is being render, add the code snippet from above in the _Host.cshtml file

Add the @attribute [AllowAnonymous] to specific pages you want to exculde from authentication, as for instance, the Index page.

Homicide answered 14/3, 2020 at 22:59 Comment(6)
Wow, that worked! Never would've thought to add it to the _imports file. Thanks!Allocate
Awesome, I was about to look for a solution for this also.Aluminiferous
@Sebazzz, how do you know it doesn't work ? Did you try it? No, you didn't ! Did you read the comments above yours ? Just for the records, a page must always be a component.Homicide
Its an old thread and it's working fine for the situation asked. But I am curious to ask a follow-up questions here. Is it possible to dynamically add Authorize attribute in _imports.razor? Because we don't want authentication to enable in development environment. I couldn't ad any @code block inside _imports.razorLenka
This won't work unless you also add @attribute [AllowAnonymous] to the Authentication.razor page. Reference here: github.com/dotnet/AspNetCore.Docs/issues/20689 Please update the answer to include this information!Trilingual
This does only work for Pages in the main Assembly. I have also added pages from a Razor class Library to my routing, and those are still accessible without authentication. Any ideas on how to fix this?Sow
R
6

You can do this by adding a authorization fallback policy :

services.AddRazorPages();

services.AddAuthorization(options =>
{
    options.FallbackPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
});

The fallback authentication policy requires all users to be authenticated, except for Razor Pages, controllers, or action methods with an authentication attribute.

That means that you can use the attributes for Example @attribute [Authorize] (attributes) to customize Authentication and Authorization.

Rafferty answered 21/6, 2021 at 12:54 Comment(1)
Using options.FallbackPolicy causes my authorization middleware to send 302 Found on the GET /_framework/blazor.web.js request for unauthenticated users: blazor.web.js will not be loaded. This breaks InteractiveServer rendering on pages/components that need to be public (@attribute [AllowAnonymous]). I spent quite some time figuring this out. The solution is to remove the FallbackPolicy, and use @attribute [Authorize] in _Imports.razor instead. Target framework: net8.0.Beekman
C
2

Edit: I actually found a problem with the first solution where it would not allow me to have any endpoint or page that did not require authorization. I did find this link and it works like a charm.

I was looking for a solution for this myself and found the following link. So far it seems to work as expected.

New solution:

//RedirectToLogin
@inject NavigationManager NavigationManager
@code{

protected override async Task OnInitializedAsync()
{
    var returnUrl = "~/" + NavigationManager.ToBaseRelativePath(NavigationManager.Uri);
    NavigationManager.NavigateTo($"Identity/Account/Login?returnUrl={returnUrl}", forceLoad:true);
}

//App.razor
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
    <NotAuthorized>
        <RedirectToLogin />
    </NotAuthorized>
    <Authorizing>
        <p>Authorizing...</p>
    </Authorizing>
</AuthorizeRouteView>

//this in the page I want authorization for
@attribute [Authorize]

Old solution: I put the following in my ConfigureServices:

// Add a default AuthorizeFilter to all endpoints
services.AddRazorPages()
    .AddMvcOptions(options => options.Filters.Add(new AuthorizeFilter()));
Cas answered 10/9, 2021 at 8:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.