I'm implementing a custom AuthenticationStateProvider and using information from user claims in mainLayout. As far as I understood after executing NotifyAuthenticationStateChanged method should itself rerender all the components which use <AuthorizeView> e.t.c. But it doesn't. Moreover, I implemented my own reloader for mainLayout and I reload it using StateHasChanged after the user logs in. But for some reason it still thinks that there is no one authorized and renders block of code in <NotAuthorized> block. But if I reload the page manually GetAuthenticationStateAsync method is executed and after that block of code inside <Authorized> is rendered. Am I doing smth wrong or it's a bug?
My CustomAuthenticationStateProvider code:
public class CustomAuthenticationStateProvider : AuthenticationStateProvider
{
private readonly ISessionStorageService _sessionStorage;
public CustomAuthenticationStateProvider(ISessionStorageService sessionStorage)
{
_sessionStorage = sessionStorage;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
var userModel = await _sessionStorage.GetItemAsync<AuthorizedModel>("userModel");
var identity = new ClaimsIdentity();
if (userModel != null)
{
identity = new ClaimsIdentity( new []
{
//Some my claims
...
}, "api");
}
else
{
identity = new ClaimsIdentity();
}
var claimsPrincipal = new ClaimsPrincipal(identity);
return new AuthenticationState(claimsPrincipal);
}
public void AuthenticateUser(AuthorizedModel model)
{
var identity = new ClaimsIdentity(new []
{
//Some my claims
...
});
var user = new ClaimsPrincipal(identity);
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
}
public async Task LogUserOut()
{
await _sessionStorage.RemoveItemAsync("nickName");
var identity = new ClaimsIdentity();
var user = new ClaimsPrincipal(identity);
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
}
}
My login:
public async Task HandleValidSubmit()
{
var authorizedUser = await loginRepository.TryLogin(_model);
...
((CustomAuthenticationStateProvider)authenticationStateProvider).AuthenticateUser(authorizedUser);
await sessionStorage.SetItemAsync("userModel", authorizedUser);
navigationManager.NavigateTo("/");
//This is for my custom page reload
authorizationState.LoggedIn = true;
}
My MainLayout:
@inherits LayoutComponentBase
...
<AuthorizeView>
<Authorized>
<UserInfo />
</Authorized>
<NotAuthorized>
//Some block of code for non-authorized
...
</NotAuthorized>
</AuthorizeView>
...
And finally UserInfo code:
@using System.Security.Claims
...
<div class="user-info">
<span class="user-name">
@userFirstName
<strong>@userSecondName</strong>
</span>
<span class="user-role">@userNickName</span>
<span class="user-status">
<i class="fa fa-circle"></i>
<span>Online</span>
</span>
</div>
@code{
[CascadingParameter]
private Task<AuthenticationState> authenticationStateTask { get; set; }
ClaimsPrincipal user;
string userFirstName;
...
protected override async Task OnInitializedAsync()
{
user = (await authenticationStateTask).User;
//Here I just get userInfo from claims
...
}
}