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

How to store ClaimsPrincipal in Blazor Server used in AuthenticationStateProvider in .Net 9

$
0
0

I have a Blazor app, server, global, .NET 9. I created myApiAuthenticationStateProvider : AuthenticationStateProvider in which I have GetAuthenticationStateAsync, Login, Logout.

How can I store user information to retrieve it in GetAuthenticationStateAsync? Theoretically the safest option is a cookie, but when I want to save the created ClaimsPrincipal using HttpContext.SignInAsync I get an error:

headers cannot be modified if the response has already been sent to the client.

So I try to use ProtectedLocalStorage, but already at the start in GetAuthenticationStateAsync with

await _protectedLocalStorage.GetAsync<string?>("token");

I get the error

System.InvalidOperationException: 'JavaScript interop calls cannot be issued at this time. This is because the component is being statically rendered. When prerendering is enabled, JavaScript interop calls can only be performed during the OnAfterRenderAsync lifecycle method.'

In Microsoft's documentation, the only example is returning a user from the backing field, which is weak because all you have to do is refresh the page and you lose information about the logged-in user.

I have no more ideas on how to properly implement GetAuthenticationStateAsync() and where to store information about the logged-in user and their session, which would be good if it lasted max. 15 minutes and was extended if the user was active.

My test code:

public sealed class ApiAuthenticationStateProvider    : AuthenticationStateProvider{    private readonly ILogger<ApiAuthenticationStateProvider> _logger;    private readonly ProtectedLocalStorage _protectedLocalStorage;    private readonly IJWTService _jWTService;    private ClaimsPrincipal _getAnnonymousUser => new ClaimsPrincipal(new ClaimsIdentity());    public ApiAuthenticationStateProvider(ILogger<ApiAuthenticationStateProvider> logger, ProtectedLocalStorage protectedLocalStorage, IJWTService jWTService)    {        _logger = logger;        _protectedLocalStorage = protectedLocalStorage;        _jWTService = jWTService;    }    public override async Task<AuthenticationState> GetAuthenticationStateAsync()    {        ProtectedBrowserStorageResult<string?> result = await _protectedLocalStorage.GetAsync<string?>(Definitions.LocalStorage.JWT_TOKEN);        string? authStateString = result.Value;        if (string.IsNullOrEmpty(authStateString))        {            return new AuthenticationState(_getAnnonymousUser);        }        ClaimsPrincipal? claimsPrincipal = _jWTService.GetClaimsPrincipalFromToken(authStateString);        if (claimsPrincipal is not null)        {            return new AuthenticationState(claimsPrincipal);        }        else        {            return new AuthenticationState(_getAnnonymousUser);        }    }    public async Task<bool> Login(int idOperator, string login, string actor, List<string>? permissions = null)    {        try        {            List<Claim> claims = new List<Claim>            {                new Claim(ClaimTypes.NameIdentifier, idOperator.ToString()),                new Claim(ClaimTypes.Name, login),                new Claim(ClaimTypes.Actor, actor),            };            if (permissions.IsAny())            {                claims.AddRange(permissions.Select(permission => new Claim(Definitions.Claim.PERMISSION, permission)));            }            ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);            ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(claimsIdentity);            string jwtToken = _jWTService.GenerateJwt(claimsPrincipal, expirationTimeInMin: 15);            await _protectedLocalStorage.SetAsync(Definitions.LocalStorage.JWT_TOKEN, jwtToken);            NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(claimsPrincipal)));            return true;        }        catch (Exception ex)        {            _logger.LogError(ex, "Error during login.");            NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(_getAnnonymousUser)));            return false;        }    }    public async Task Logout()    {        await _protectedLocalStorage.DeleteAsync(Definitions.LocalStorage.JWT_TOKEN);        NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(_getAnnonymousUser)));    }}

Viewing all articles
Browse latest Browse all 4839

Trending Articles



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