简体   繁体   中英

.net Blazor authentication mechanism

After weeks of research, I am still running into the wall....

My objective is: After the Windows authentication, invoke a custom application authorization process which will provide the ClaimsPrincipal for Blazor to perform role-based authorization.

In my Blazor's program.cs, I am using the Windows Authentication and have an Event to "react" to the authentication:

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
            .AddNegotiate(
              options => { 
                options.Events = 
                  new CMAPNegotiateEvents(builder.Environment);
              });

I also have a custom AuthenticationStateProvider with a method to absorb the ClaimsPrincipal .

If I perform the custom authentication in the WhenAuthenticated() event, how do I invoke the AuthenticationStateProvider?

PS I don't want to use the Microsoft's MVC authentication model, because we already have our own model established.

I think I understand what you are trying to do so here's my shot at answering it.

I've used the standard Server template with Windows Authentication as my base. The complete VS solution is here: https://github.com/ShaunCurtis/SO73545707

It's all in the AuthenticationStateProvider . Mine:

  1. Inherits from ServerAuthenticationStateProvider rather than AuthenticationStateProvider so we can call the base method and get the state.
  2. Adds a ClaimsIdentity with the relevant information to the existing ClaimsPrincipal .
  3. Returns a new AuthenticationState based on the updated ClaimsPrincipal .
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server;
using Microsoft.AspNetCore.Connections.Features;
using System.Security.Claims;

namespace SO73545707.Data
{
    // Inherit from ServerAuthenticationStateProvider 
    public class MyAuthenticationStateProvider : ServerAuthenticationStateProvider
    {
        public async override Task<AuthenticationState> GetAuthenticationStateAsync()
        {
            // Call the base to get the AuthState and the user provided in the Security Headers by the server
            var authstate = await base.GetAuthenticationStateAsync();
            var user = authstate.User;

            if (user is not null)
            {
                // Do whatever you want here to retrieve the additional user information you want to
                // include in the ClaimsPrincipal - probably some form of Identity Service
                
                // Construct a ClaimsIdentity instance to attach to the ClaimsPrincipal
                var myIdentity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Role, "User") });
                // Add it to the existing ClaimsPrincipal
                user.AddIdentity(myIdentity);
            }

            // construct a new state with the updated ClaimsPrincipal
            // - or an empty one of you didn't get a user in the first place
            // All the Authorization components and classes will now use this ClaimsPrincipal 
            return new AuthenticationState(user ?? new ClaimsPrincipal());
        }
    }
}

The service registration looks like this:

// Add services to the container.
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
   .AddNegotiate();

builder.Services.AddAuthorization(options =>
{
    // By default, all incoming requests will be authorized according to the default policy.
    options.FallbackPolicy = options.DefaultPolicy;
});

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
// must be after AddServerSideBlazor
builder.Services.AddScoped<AuthenticationStateProvider, MyAuthenticationStateProvider>();
builder.Services.AddSingleton<WeatherForecastService>();

I've added some Authorize attributes to the standard pages to test it.

@attribute [Authorize(Roles = "User")]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM