Quantcast
Channel: Active questions tagged blazor - Stack Overflow
Viewing all articles
Browse latest Browse all 4839

Blazor WebAssembly: Move Authentication and Authorization templated code failed

$
0
0

I moved authentication and authorization from identity template of recently updated visual studio to my blazor webassembly (client-server) web application. Unfortunately, I got errors when completed movements of classes and other code elements.Below is list of what I've done.

AccountController.cs: (debugged, here is all ok)

[HttpPost][Route("/api/account/login")]public async Task<SignInResult> Login([FromBody] LoginModel model){    var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, false);    return result;}

PersistingServerAuthenticationStateProvider.cs: (not enter here on login at all, is it ok?)

internal sealed class PersistingServerAuthenticationStateProvider : ServerAuthenticationStateProvider, IDisposable{    private readonly PersistentComponentState state;    private readonly IdentityOptions options;    private readonly PersistingComponentStateSubscription subscription;    private Task<AuthenticationState>? authenticationStateTask;    public PersistingServerAuthenticationStateProvider(        PersistentComponentState persistentComponentState,        IOptions<IdentityOptions> optionsAccessor)    {        state = persistentComponentState;        options = optionsAccessor.Value;        AuthenticationStateChanged += OnAuthenticationStateChanged;        subscription = state.RegisterOnPersisting(OnPersistingAsync, RenderMode.InteractiveWebAssembly);    }    private void OnAuthenticationStateChanged(Task<AuthenticationState> task)    {        authenticationStateTask = task;    }    private async Task OnPersistingAsync()    {        if (authenticationStateTask is null)        {            throw new UnreachableException($"Authentication state not set in {nameof(OnPersistingAsync)}().");        }        var authenticationState = await authenticationStateTask;        var principal = authenticationState.User;        if (principal.Identity?.IsAuthenticated == true)        {            var userId = principal.FindFirst(options.ClaimsIdentity.UserIdClaimType)?.Value;            var email = principal.FindFirst(options.ClaimsIdentity.EmailClaimType)?.Value;            if (userId != null && email != null)            {                state.PersistAsJson(nameof(UserInfo), new UserInfo                {                    UserId = userId,                    Email = email,                });            }        }    }    public void Dispose()    {        subscription.Dispose();        AuthenticationStateChanged -= OnAuthenticationStateChanged;    }}

PersistentAuthenticationStateProvider (on authentication always empty return, on access to site pages, required authorizetion - not enter this class method):

public class PersistentAuthenticationStateProvider : AuthenticationStateProvider{    private static readonly Task<AuthenticationState> defaultUnauthenticatedTask =Task.FromResult(new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())));    private readonly Task<AuthenticationState> authenticationStateTask = defaultUnauthenticatedTask;    public PersistentAuthenticationStateProvider(PersistentComponentState state)    {        if (!state.TryTakeFromJson<UserInfo>(nameof(UserInfo), out var userInfo) || userInfo is null)        {            return; // always goes here        }        Claim[] claims = [            new Claim(ClaimTypes.NameIdentifier, userInfo.UserId),            new Claim(ClaimTypes.Name, userInfo.Email),            new Claim(ClaimTypes.Email, userInfo.Email) ];        authenticationStateTask = Task.FromResult(            new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(claims,                authenticationType: nameof(PersistentAuthenticationStateProvider)))));    }    public override Task<AuthenticationState> GetAuthenticationStateAsync() => authenticationStateTask;}

Server persistence provider registered at server Program.cs, another provider registered on client Program.cs. Mismatch with templated project is that Login.razor view in my project placed on client, but in template-generated - on server.Feeling that I've missing something simple - the thing why PersistingServerAuthenticationStateProvider not entering in debugger at all.

Registration code (client):

builder.Services.AddAuthorizationCore();builder.Services.AddCascadingAuthenticationState();builder.Services.AddSingleton<AuthenticationStateProvider, PersistentAuthenticationStateProvider>();

Registration code (server):

builder.Services.AddDbContext<IdentityDataContext>((options) =>{    options.UseSqlServer(databaseConfig?.ConnectionString);});builder.Services.AddIdentityCore<User>()//options => options.SignIn.RequireConfirmedAccount = true    .AddEntityFrameworkStores<IdentityDataContext>()    .AddSignInManager()    .AddDefaultTokenProviders();builder.Services.AddScoped<UserManager<User>>();builder.Services.AddScoped<AuthenticationStateProvider, PersistingServerAuthenticationStateProvider>();

Viewing all articles
Browse latest Browse all 4839

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>