I have Blazor WebAssembly application on .net 8. I tried to implement custom authentication in it, but my code doesn’t work. Elements located in the block [Authorized] are not displayed. In my solution i have 3 projects: Server, Client, Shared.
Server.Program.cs
builder.Services.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
o.RequireHttpsMetadata = false;
o.SaveToken = true;
o.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(JwtAuthenticationManager.JWT_SECURITY_KEY)),
ValidateAudience = false
};
});
builder.Services.AddSingleton<UserAccountService>();
builder.Services.AddAuthorizationCore();
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();
builder.Services.AddBlazoredSessionStorage();
Client.Program.cs
uilder.Services.AddBlazoredSessionStorage();
builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthenticationStateProvider>();
builder.Services.AddAuthorizationCore();
Client.CustomAuthenticationStateProvider.cs
public class CustomAuthenticationStateProvider : AuthenticationStateProvider
{
private readonly ISessionStorageService _sessionStorage;
private ClaimsPrincipal _anonymous = new ClaimsPrincipal(new ClaimsIdentity());
public CustomAuthenticationStateProvider(ISessionStorageService sessionStorage)
{
_sessionStorage = sessionStorage;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
try
{
var userSession = await _sessionStorage.ReadEncryptedItemAsync<UserSession>("userSession");
if (userSession == null)
return await Task.FromResult(new AuthenticationState(_anonymous));
var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
{
new Claim(ClaimTypes.Name,userSession.UserName),
new Claim(ClaimTypes.NameIdentifier,userSession.Id.ToString())
}, "JwtAuth"));
return await Task.FromResult(new AuthenticationState(claimsPrincipal));
}
catch
{
return await Task.FromResult(new AuthenticationState(_anonymous));
}
}
public async Task UpdateAuthenticationState(UserSession? userSession)
{
ClaimsPrincipal claimsPrincipal;
if (userSession != null)
{
claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
{
new Claim(ClaimTypes.Name, userSession.UserName),
new Claim(ClaimTypes.NameIdentifier,userSession.Id.ToString())
}));
userSession.ExpiryTimeStamp = DateTime.Now.AddSeconds(userSession.ExpiresIn);
await _sessionStorage.SaveItemEncryptedAsync("UserSession", userSession);
}
else
{
claimsPrincipal = _anonymous;
await _sessionStorage.RemoveItemAsync("UserSession");
}
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(claimsPrincipal)));
}
public async Task<string> GetToken()
{
var result = string.Empty;
try
{
var userSession = await _sessionStorage.ReadEncryptedItemAsync<UserSession>("UserSession");
if ( userSession != null && DateTime.Now< userSession.ExpiryTimeStamp)
result = userSession.Token;
}
catch
{
}
return result;
}
}
I have an assumption that the problems are due to the fact that the provider is registered in both projects, but I don’t know how to fix it. If I remove the provider registration from the server project, the application does not start.
Арсений Горбань is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.