0

I am quite new to Blazor and I am trying to understand authentication and authorization. What I did so far is reading the docs Authentication and Authorization in ASP.NET Core Blazor and Rolebased Authorization in Asp.NET Core. I managed to get authentication running, but I am struggeling with authorization. I would like to store every windows user who is visiting my server side app in a database and say User1 is Admin, User2 is Editor etc. and showing users diffrent areas of pages.

I was able to read out Windows users, but until now I couldn't set roles. I tried something like this with claims:

public class CustomAuthenticationStateProvider : AuthenticationStateProvider
{
    public override Task<AuthenticationState> GetAuthenticationStateAsync()
    {

        var identity = new ClaimsIdentity(new[]
        {
        new Claim(  type: ClaimTypes.Name, value: @"User1")
        }, "Editor");


        var user = new ClaimsPrincipal(identity);

        return Task.FromResult(new AuthenticationState(user));
    }
}

And I attached it into ConfigureServices

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        services.AddServerSideBlazor();

        services.AddAuthorizationCore();

        services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();

    }

From what I understand is that this function will not work with

<AuthorizeView Roles="Editor">
   <p>Show User Identity: @context.User.Identity</p>
</AuthorizeView>

on razor pages because Roles simply are not Claims. But how can I tell my application that User1 is in Role "Editor" and User2 is in role "Admin"? Or is there another way to ask for Users claims and show the User different areas of a page? Am I missing something?

Tim
  • 7
  • 2

1 Answers1

0

What I did so far is reading the docs Authentication and Authorization in ASP.NET Core Blazor and Rolebased Authorization in Asp.NET Core. I managed to get authentication running, but I am struggeling with authorization. I would like to store every windows user who is visiting my server side app in a database and say User1 is Admin, User2 is Editor etc. and showing users diffrent areas of pages.

In the official document (you are reading), the role based authorization is achieved via the Asp.net Core Identity. You can find it from Add Role services to Identity.

enter image description here

So, you could refer to the following articles to configure your application to use Asp.net Core Identity.

Introduction to Identity on ASP.NET Core

Scaffold Identity in ASP.NET Core projects.

Besides, from your description, you are using a database to store the user account, it seems that you are using Individual User Accounts. You could refer to the following sample to achieve role based authorization in asp.net core Blazor application.

  1. Create an asp.net core Blazor Server App and Choose "Individual User Accounts" type and keep default "Store user accounts in-app" to store SQL tables locally for identity framework.

    enter image description here

  2. Generate the database and Indentity Schema:

    Using the following command in the Package Manager Console tools. More detail information, check EF Core Migrations.

     add-migration InitialCreate
     update-database
    

    After that, using SQL Server Management Studio(SSMS) to check tables in the database:

    enter image description here

    Open the Startup.cs file, modify the "ConfigureServices" method with below change (add .AddRoles<IdentityRole>();). So that we can control the authorization with identity roles in the application.

     public void ConfigureServices(IServiceCollection services)
     {
         services.AddDbContext<ApplicationDbContext>(options =>
             options.UseSqlServer(
                 Configuration.GetConnectionString("DefaultConnection")));
         services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
             .AddRoles<IdentityRole>()
             .AddEntityFrameworkStores<ApplicationDbContext>();
         services.AddRazorPages();
         services.AddServerSideBlazor();
         services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();
         services.AddDatabaseDeveloperPageExceptionFilter();
         services.AddSingleton<WeatherForecastService>();
     }
    

    Running the application, and register two users: adminuser@hotmail.com and normaluser@hotmail.com.

    Then, you could find the users from the dbo.AspNetUsers table (via SSMS):

    enter image description here

    Open the SSMS, right click the dbo.AspNetRoles table and click "View Data", and add two roles (Id is a Guid):

    enter image description here

    Open the SSMS, right click the dbo.AspNetUserRoles table and click "View Data", copy the user id and role id to this table and add roles to the user.

    enter image description here

    If you don't want to use this method to add roles to specific user, you could use UserManager.AddToRoleAsync() method to add the specified user to the named role. You could refer this article.

  3. Create the Admin page and Normal page in the Pages folder.

    AdminPage.razor:

     @page "/adminpage"
    
     @attribute [Authorize(Roles = "admin")]
    
     <h3>AdminPage</h3>
    
     @code {
    
     }
    

    NormalPage.Razor

     @page "/adminpage"
    
     @attribute [Authorize(Roles = "admin")]
    
     <h3>AdminPage</h3>
    
     @code {
    
     }
    

    Modify the shared component "NavMenu" with below changes.

     <AuthorizeView Roles="admin">
         <li class="nav-item px-3">
             <NavLink class="nav-link" href="adminpage">
                 <span class="oi oi-list-rich" aria-hidden="true"></span> Admin Page
             </NavLink>
         </li>
     </AuthorizeView>
     <AuthorizeView Roles="normal">
         <li class="nav-item px-3">
             <NavLink class="nav-link" href="normalpage">
                 <span class="oi oi-list-rich" aria-hidden="true"></span> Normal Page
             </NavLink>
         </li>
     </AuthorizeView>
    

    Running the application, the result like this:

    enter image description here

Reference:

Role Based Authorization In Blazor

how to use usermanager on a blazor page?

Zhi Lv
  • 18,845
  • 1
  • 19
  • 30
  • Thanks you for the quick response! But I'm having trouble connection to the database. I did create the InitialCreate and update-database but there wasn't any database shown in VS. Also SSMS couldn't find any on my pc which means it wasn't created or did I not connect properly? – Tim Jan 12 '21 at 16:05
  • Hi @Tim, Which version of VS are you using? On my machine, I'm using VS 2019 16.8.3 version, you could try to upgrade the VS version to the latest version and select [the "Data Storage and processing"](https://i.stack.imgur.com/4O6Rc.png) when install the VS. Besides,please check the connection string in the appsetting.json file, it should like this: `Server=(localdb)\\mssqllocaldb;Database=aspnet-BlazorAuthSample;Trusted_Connection=True;MultipleActiveResultSets=true`, if you are using the same server, the database should be in the `C:\Users\{your current user}` folder, you could check it. – Zhi Lv Jan 13 '21 at 01:47
  • According to the connection string in the appsetting.json file, if you could find the database from the folder. Click the "View" in VS 2019, and select the SQL Server Object Explorer, and refresh the SQL Server, if still can't find the database, click the View in the VS 2019, choose the Server Explorer, click the "Connect to Database" icon, in the Add Connection dialog, click the Browser button to find the database, after testing the connection click the OK button, check this [screenshot](https://i.stack.imgur.com/El8Gd.png), then you could check the tables in the database. – Zhi Lv Jan 13 '21 at 02:26
  • Thank you A LOT! It worked now for me. I do have the same VS installed as you so I was able to find the database with SQL Server Object Explorer. I think I understood this a little better know. I do have some follow up questions about that topic know for my understanding: 1) Roles are represented as GUID, so if I want to manage user accounts I have to change RoleId in dbo.AspNetUserRoles which can be done by functions as you were referring? 2) How to achieve that Admin is allowed to view anything Normal also seeing by keeing the same check of roles in .pages? Can this be done with claims? – Tim Jan 14 '21 at 13:00
  • Hi @Tim, For the first question, when using [Asp.net Core Identity](https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity?view=aspnetcore-5.0&tabs=visual-studio), we could use UserManger and RoleManger to manage the users and roles, the class contains many related methods, you could search them online, there have multiple articles about it. By using them, we can manage users and roles programmatically. Refer [this article](https://www.c-sharpcorner.com/article/adding-role-authorization-to-a-asp-net-mvc-core-application/). – Zhi Lv Jan 15 '21 at 09:26
  • For the question 2, you could add `[Authorize(Roles = "Admin, Normal")]` at the head of the controller or action method, then, both the Admin user and Normal user could access this action. Here are some related articles, you could check them: [Role-based authorization in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/security/authorization/roles?view=aspnetcore-5.0), [Policy-Based And Role-Based Authorization In ASP.NET Core 3.0 Using Custom Handler](https://www.c-sharpcorner.com/article/policy-based-role-based-authorization-in-asp-net-core/) – Zhi Lv Jan 15 '21 at 09:27
  • Thank you a lot for your time and very good explanation! – Tim Jan 18 '21 at 10:00