Luka
Luka

Reputation: 4211

Custom authentication not working on Blazor Wasm 8.0

I have big problems in using AuthenticationState in Blazor 8.0 Wasm (Hosted). The problem is that after I log in, the AuthenticationState is not refreshed and the DefaultAuthorizationService.Authorize method gets old ClaimPrincipal data.

All the services are registered in DI container.

I have implemented custom AuthenticationStateProvider like this:

public class PersistentAuthenticationStateProvider : AuthenticationStateProvider
{
    private readonly UserInfoProvider _userInfoProvider;
    private readonly ILogger<PersistentAuthenticationStateProvider> _logger;
    private ClaimsPrincipal UnauthorizedPrincipal => new ClaimsPrincipal(new 
            ClaimsIdentity(new List<Claim>(){new Claim(ClaimTypes.Name, "Anonymous")}));

    public PersistentAuthenticationStateProvider(UserInfoProvider userInfoProvider, 
           ILogger<PersistentAuthenticationStateProvider> logger)
    {
        _userInfoProvider = userInfoProvider;
        _logger = logger;
    }

    public override Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var claimsPrincipal = UnauthorizedPrincipal;
        var info = _userInfoProvider.GetCurrentUserInfo();
        if (info != null)
        {
            claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(
                info.UserClaims.Select(x => new Claim(x.ClaimType, x.ClaimValue)),
                authenticationType: "PersistentAuthenticationStateProvider"));
        }

        var stateTask = Task.FromResult(new AuthenticationState(claimsPrincipal));
        return stateTask;
    }

    public void NotifyUserHasChanged()
    {
        NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
    }
}

On User login I call NotifyUserHasChanged() method on an instance of PersistentAuthenticationStateProvider, but nothing happens.

I have put a breakpoint in the AuthorizeView.OnParameterSetAsync where it is getting the AuthenticationState, and this method is not executed when NotifyAuthenticationStateChanged is called.

My workflow for user authentication is:

  1. At the startup, the framework checks if the user is logged in, if not, it will redirect to LoginPage
  2. User enters username and password and tries to login
  3. This makes a Rest request to the api endpoint and returns token. This token is saved in local storage.
  4. Then I make a request to get UserInfo containing user claims.
  5. If this success, i store it into local storage and NotifyAuthenticationStateChanged.
  6. I use NavigationManager to navigate to HomePAge that has [Authorize] attribute.
  7. The framework calls AuthorizeView.OnParameterSetAsync() and there is a call to await AuthenticationState, this state returns old data.

But if I close the browser and restart it, it will find the user data stored in localstorage and the user will correctly be authorized.

Also if i log-out the user, I clear up the local storage and NotifyAuthenticationStateChanged, it will correctly be unauthorized.

NOTE: It works if I navigate using "forceLoad:true"

I need help to find what I'm doing wrong? Please help

Thanks

Upvotes: 0

Views: 501

Answers (1)

Luka
Luka

Reputation: 4211

Found the problem... I was registering PersistentAuthenticationStateProvider as itself and as AuthenticationStateProvider. So there were two instances active in memory at the same time.

Upvotes: 0

Related Questions