Home > Mobile >  Blazor folder authorization not working, allows non-logged in users to see content
Blazor folder authorization not working, allows non-logged in users to see content

Time:11-15

latest blazor .NET blazor. Program.cs

using APICommon;
using Common.Settings;
using EventApiService;
using Events.Application.Commands.Coins;
using FluentValidation;
using Identity.Application.Commands;
using Identity.Persistence;

using MediatR;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Serilog;

var builder = WebApplication.CreateBuilder(args);

//Serilog
builder.WebHost.UseSerilog((hostingContext, loggerConfiguration) => loggerConfiguration
    .ReadFrom.Configuration(hostingContext.Configuration)
    .Enrich.FromLogContext());

//code removed

builder.Services.AddCustomAuthorization(dbSettings);
builder.Services.AddHttpClient();

builder.Services.AddRazorPages(options =>
    {
        options.Conventions.AuthorizeFolder("/admin",  "Administrators");
        options.Conventions.AuthorizeFolder("/client",  "Owners");

    }
);
builder.Services.AddServerSideBlazor();



builder.Services.AddTelerikBlazor();


builder.Services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();
var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();
internal static class ExtensionMethods
{

    public static IServiceCollection AddCustomAuthorization(this IServiceCollection services,
        DatabaseSettings dbSettings)
    {
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(dbSettings.IdentityConnectionString));

        services.AddDatabaseDeveloperPageExceptionFilter();

        services.AddDefaultIdentity<ApplicationUser>(options =>
            {
                options.SignIn.RequireConfirmedAccount = true;
                options.Password.RequiredLength = 6;
                options.Password.RequireDigit = false;
                options.Password.RequireLowercase = false;
                options.Password.RequiredUniqueChars = 0;
                options.Password.RequireNonAlphanumeric = false;
                options.Password.RequireUppercase = false;
            })
            .AddRoles<IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>();

      
   
        return services;
    }
}

Above is suppose to make sure only authorized "Owners" role see /client or any pages inside it, but even if i dont log in i can hit /client and view its content.

CodePudding user response:

Blazor does not support authorizing "folders". You will need to authorize components instead. One way of handling this is to have use a AdminPanelComponent for all admin elements, and apply admin authorization rules on that component.

Since you are using blazor server, you may however match routes and apply authorization using a middleware. Example:

app.Use(async (context, next) =>
{
    if(context.Request.Path.StartsWithSegments("/admin", System.StringComparison.OrdinalIgnoreCase))
    {
        if (!context.User.IsAdministrator()) // ext. method... replace with your own logic
        {
            await context.ForbidAsync();
            return;
        }
    }
    if(context.Request.Path.StartsWithSegments("/client", System.StringComparison.OrdinalIgnoreCase))
    {
        if (!context.User.IsOwner()) 
        {
            await context.ForbidAsync();
            return;
        }
    }
    await next.Invoke();
});

(You can refactor this to it's own middleware class if you'd like.)

CodePudding user response:

I'm of the opinion that you shouldn't use this in Blazor:

builder.Services.AddRazorPages(options =>
    {
        options.Conventions.AuthorizeFolder("/admin",  "Administrators");
        options.Conventions.AuthorizeFolder("/client",  "Owners");

    }
);

Instead you should apply the Authorize attribute, something like this:

[Authorize(Roles = "Administrators")]

ya i have the above in one of the pages and it works, but I dont want to repeat this in every page, and in case a page is added in the future i want to make sure be default its protected if its under the folder

In that case you can place the Authorize attribute in the _Imports.razor file, thus enabling all your pages with the attribute. You can also define a component base class with the Authorize attribute, and derive all your component pages from that class. This technique is more common as there are other things common to all pages that you can place in the base class. That is the Blazor way to do that. What you were trying to do is, actually was, common in MVC or Razor pages, and it is not applicable to Blazor.

  • Related