CSLA and Blazor WebAssembly Authentication #3324
-
Hi There CSLA community, I'm now working on a project that's based on Blazor WebAssembly and CSLA.net, and I am seeking assistance with configuring authentication. I have been following the steps outlined in this GitHub repository: https://github.com/MarimerLLC/BlazorBook/tree/master/BlazorCslaAuthentication/BlazorCslaAuthentication. In CSLA version 5.4, there was CslaUserService to add the ClaimsPrincipal. However, with the latest version, CSLA 6.2, I have been unable to configure the CslaAuthenticationStateProvider to set the ClaimsPrincipal object after authenticating the user with JWT. I need this ClaimsPrincipal object for authorization of business object properties. Specifically, my business object has three properties and I want to enforce the following rule: users with the 'user' role can only view the Name and HireDate properties, while users with the 'admin' role can view all three properties (Name, HireDate, and Salary). I intend to apply this rule using a CSLA business rule. If anyone has experience with this authentication mechanism or can provide a code snippet to assist me, it would be greatly appreciated. my login page is : @page "/login"
@using Data_Layer.Model
@using Csla.DataPortalClient;
@using Csla.Configuration;
@using Csla;
@using Csla.Security;
@using Csla.Blazor.Authentication;
@using System.Security.Claims
@using Csla.Blazor
@inject NavigationManager Navigation
@inject HttpClient httpClient
@inject cslabwasmpoc.Client.ILocalStorage LocalStorage
@inject CslaAuthenticationStateProvider clsaAuthenticationStateProvider
<div class="w-25">
<h3>Login</h3>
<form class="mt-3">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" class="form-control" @bind-value="loginModel.userName">
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" class="form-control" @bind-value="loginModel.passWord">
</div>
<button type="button" class="btn btn-primary" @onclick="LoginHandler">Login</button>
</form>
@if (loginError)
{
<div class="alert alert-danger mt-3">@loginErrorMessage</div>
}
@if (loginSucess)
{
<div class="alert alert-sucess mt-2" style="width:400px">@loginSucessMessage</div>
}
</div>
@code {
LoginModel loginModel = new LoginModel();
private bool loginError;
private bool loginSucess;
private string? loginErrorMessage;
private string? loginSucessMessage;
private async Task LoginHandler()
{
loginErrorMessage = "";
loginErrorMessage = "";
loginError = false;
loginSucess = false;
using (var msg= await httpClient.PostAsJsonAsync<LoginModel>("/api/Auth", loginModel))
{
if (msg.IsSuccessStatusCode)
{
LoginResult result = await msg.Content.ReadFromJsonAsync<LoginResult>();
if (!string.IsNullOrEmpty(result.JwtToken))
{
await LocalStorage.SaveStringAsync("jwtToken", result.JwtToken);
loginSucess = true;
loginSucessMessage = $"sucessfully logged in {await LocalStorage.GetStringAsync("jwtToken")} {result.Role} ";
var identity = new ClaimsIdentity("customType");
identity.AddClaim(new Claim(ClaimTypes.Role, result?.Role));
var principal = new System.Security.Claims.ClaimsPrincipal(identity);
clsaAuthenticationStateProvider.SetPrincipal(principal);
await Task.Delay(5000);
Navigation.NavigateTo("/login", true);
}
else
{
loginError = true;
loginErrorMessage = "Invalid username or password.";
}
}
}
}
} and my program.cs file is : using csla_bwasm_poc.Client;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Csla.Configuration;
using Csla;
using cslabwasmsecurity;
using Csla.DataPortalClient;
using cslabwasmpoc.Client;
using Microsoft.AspNetCore.Components.Authorization;
using Csla.Blazor.Authentication;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();
builder.Services.AddSingleton<CslaAuthenticationStateProvider>();
builder.Services.AddTransient<ILocalStorage, LocalStorage>();
var provider = builder.Services.BuildServiceProvider();
var localStorage = provider.GetRequiredService<ILocalStorage>();
var token = await localStorage.GetStringAsync("jwtToken");
var proxyOptions = new Csla.Channels.Http.HttpProxyOptions();
builder.Services.AddTransient(typeof(IDataPortalProxy),
sp =>
{
var applicationContext = sp.GetRequiredService<ApplicationContext>();
var client = applicationContext.GetRequiredService<HttpClient>();
return new CustomHttpProxy(applicationContext, client, proxyOptions, token);
});
builder.Services.AddCsla(o => o
.AddBlazorWebAssembly());
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
await builder.Build().RunAsync(); Thank you. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Take a look at the The Login page shows how to do this in CSLA v6 and v7. |
Beta Was this translation helpful? Give feedback.
Take a look at the
Samples/BlazorExample
code.The Login page shows how to do this in CSLA v6 and v7.