asp.net-coreblazorblazor-client-sideasp.net-core-security

Initial state of AuthenticationStateProvider


Following the documentation, I created my custom AuthenticationStateProvider as follows:

public class ApiAuthStateProvider : AuthenticationStateProvider
{
    private static AuthenticationState anonymousState = ?

    private AuthenticationState _authState;

    public ApiAuthStateProvider()
    {
        _authState = anonymousState;
    }

    public void SetAuthenticationState(AuthenticationState authState)
    {
        _authState = authState ?? anonymousState;
        NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
    }

    public override Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        return Task.FromResult(_authState);
    }
}

The issue is how to initialize anonymous state, so that _authState.User.Identity.IsAuthenticated is false. As in the document, the following will result in authenticated user:

private static AuthenticationState anonymousState = 
    new AuthenticationState(new ClaimsPrincipal(
    new ClaimsIdentity(new Claim[] {}, "none")));

Even the following resulted in authenticated user:

public class AnonymousIdentity : IIdentity
{
    public string AuthenticationType => "none";
    public bool IsAuthenticated => false;
    public string Name => string.Empty;
}

private static AuthenticationState anonymousState;

static ApiAuthStateProvider()
{
    var anonymousIdentity = new AnonymousIdentity();
    var user = new ClaimsIdentity(anonymousIdentity);
    anonymousState = new AuthenticationState(
        new ClaimsPrincipal(user));
}

What am I missing here?


Solution

  • Yes, just use:

    new AuthenticationState(new ClaimsPrincipal());
    

    This code works for me:

        public class CustomAuthenticationProvider : AuthenticationStateProvider
        {
            private readonly HttpClient _httpClient;
            public CustomAuthenticationProvider(HttpClient httpClient)
            {
                _httpClient = httpClient;
            }
            public override async Task<AuthenticationState>
                GetAuthenticationStateAsync()
            {
                ClaimsPrincipal user;
                // Call the GetUser method to get the status
                // This only sets things like the AuthorizeView
                // and the AuthenticationState CascadingParameter
                var result =
                    await _httpClient.GetJsonAsync<BlazorUser>("api/user/GetUser");
                // Was a UserName returned?
                if (result.UserName != "")
                {
                    // Create a ClaimsPrincipal for the user
                    var identity = new ClaimsIdentity(new[]
                    {
                       new Claim(ClaimTypes.Name, result.UserName),
                    }, "AzureAdAuth");
                    user = new ClaimsPrincipal(identity);
                }
                else
                {
                    user = new ClaimsPrincipal(); // Not logged in
                }
                return await Task.FromResult(new AuthenticationState(user));
            }
        }
    

    See: Client Side Blazor Authentication Using Azure AD and a Custom AuthenticationStateProvider