I am confused on how to add authorization to my components.
In the client part I am using AuthenticationStateProvider and in the server part ServerAuthenticationStateProvider. Segum I've been looking at the documentation and other examples.
My blazor app doesn't use individual accounts. I log in to my api and get a token, how do I tell it that I am already authenticated in the AuthenticationStateProvider and ServerAuthenticationStateProvider providers?
so the state behaves, or is this not so? how do I proceed?
Server:
public class PersistingAuthenticationStateProvider : ServerAuthenticationStateProvider, IDisposable
{
private Task<AuthenticationState>? _authenticationStateTask;
private readonly PersistentComponentState _state;
private readonly PersistingComponentStateSubscription _subscription;
private readonly IdentityOptions _options;
public PersistingAuthenticationStateProvider(
PersistentComponentState persistentComponentState,
IOptions<IdentityOptions> optionsAccessor)
{
_options = optionsAccessor.Value;
_state = persistentComponentState;
AuthenticationStateChanged += OnAuthenticationStateChanged;
_subscription = _state.RegisterOnPersisting(OnPersistingAsync, RenderMode.InteractiveWebAssembly);
}
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 role = principal.FindFirst(_options.ClaimsIdentity.RoleClaimType)?.Value;
if (userId != null && role != null)
{
_state.PersistAsJson(nameof(UserInfoResponse), new UserInfoResponse
{
Id = Convert.ToInt32(userId),
IdProfile = Convert.ToInt32(role),
Email = "",
Identification = "",
Name = "",
Phone = ""
});
}
}
}
private void OnAuthenticationStateChanged(Task<AuthenticationState> authenticationStateTask)
{
_authenticationStateTask = authenticationStateTask;
}
public void Dispose()
{
_authenticationStateTask?.Dispose();
_subscription.Dispose();
AuthenticationStateChanged -= OnAuthenticationStateChanged;
}
}
Client:
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<UserInfoResponse>(nameof(UserInfoResponse), out var userInfoResponse) || userInfoResponse is null)
{
return;
}
var claims = new List<Claim>()
{
new Claim(ClaimTypes.NameIdentifier, userInfoResponse.Id.ToString()),
new Claim(ClaimTypes.Role, "Administrador")
};
_authenticationStateTask = Task.FromResult(
new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(claims,
authenticationType: nameof(PersistentAuthenticationStateProvider)))));
}
public override Task<AuthenticationState> GetAuthenticationStateAsync() => _authenticationStateTask;
}
Login:
var claims = new List<Claim>()
{
new Claim(ClaimTypes.NameIdentifier, userInfo.Id.ToString()),
new Claim(ClaimTypes.Role, "Administrador")
};
var claimPrincipal = new ClaimsPrincipal(new ClaimsIdentity(claims, "profile"));
((PersistingAuthenticationStateProvider)authenticationStateProvider).SetAuthenticationState(Task.FromResult(new AuthenticationState(claimPrincipal)));
Then I have other components with
<AuthorizeView>
<Authorized>
<Component>
</Authorized>
</AuthorizeView>
But I never log in, because I lose authentication with the providers.