Home > Software design >  How to implement role-based authorization in Blazor WASM without modifying Identity Server code
How to implement role-based authorization in Blazor WASM without modifying Identity Server code

Time:07-21

Before posting this question I' ve done lots of research in the Internet, I' ve found some stuff, but I wasn't able to find something that fits my case. So please provide me the right direction or code snippets to go on.

I'm developing an app in .NET 6 which consists of 2 projects: Blazor WASM project for the client-side and a WEB-API project for the API's of my app.

At the moment, I've successfully implemented authentication from a central Identity Server 4. I receive "id_token" and "access_token" and use them to secure access to my web-APIs from unauthenticated users.

The problem is that now I want to implement "role-based authorization". The facts are:

  • I cannot modify the code of the common Identity Server I use.
  • I have the users, the roles and their connection inside my app's database.

I think that the right solution here is implementing a MIDDLEWARE which reads the roles from my database and adds them into the "Claims".

Where should I develop the middleware? Web-Api project, blazor project or both???

If I developed a middleware in the Web-Api project (where by default there is already a pipeline) which adds roles into the Claims of "access_token", the blazor project wouldn't work bacause of the modified token, right???

Could you help me with code snippets or provide me the right directions?

Thank you for your time!!!

CodePudding user response:

Authorization is solely an API responsibility:

  • The Blazor app sends up an access token to identify the user, via the subject claim
  • The API verifies the JWT on every request, then looks up other claims for that subject
  • The extra claims can be cached for subsequent requests with the same access token

My sample .NET API shows one way of doing this and building a custom ClaimsPrincipal. Once you've done that, .NET's standard authorization techniques such as the [Authorize] attribute will work based on the ClaimsPrincipal's contents.

CodePudding user response:

The client sends the access_token in every request. The server validates the access_token and then creates a ClaimsPrincipal with the claims that were included in the token. In your server can add additional claims to the ClaimsPrincipal using the OnTokenValidated event. Example:

.AddJwtBearer("Bearer", options =>
{
    options.Events = new JwtBearerEvents
    {
        OnTokenValidated = async context =>
        {
            var user = context.Principal;
            var userId = user.FindFirstValue(ClaimTypes.NameIdentifier);

            // Get DbContext. If you don't use Entity Framework request your own data access service.
            //var dbContext = context.HttpContext.RequestServices.GetRequiredService<AppDbContext>();

            // Retrieve user roles from database and create a list of role claims.
            var claims = new List<Claim>
            {
                new Claim(ClaimTypes.Role, "admin")
            };

            var claimsIdentity = new ClaimsIdentity(claims);

            user.AddIdentity(claimsIdentity);
            await Task.CompletedTask;
        }
    };
});

Then in your controllers you can check for the role using [Authorize(roles = "admin")] or User.IsInRole("admin");.

  • Related