in our application I'd like to use the user management of our fat client. For this I have written a custom AuthenticationStateProvider:
public class MyAuthenticationStateProvider : ServerAuthenticationStateProvider, IAuthentorizationService, IDisposable
{
public MyAuthenticationStateProvider (IPermissionManager permissionManager)
{
//User management service of the fat client
_permissionManager = permissionManager;
}
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
if (_permissionManager.PermissionUser == null)
{
var emptyUser = new ClaimsPrincipal(new ClaimsIdentity(new Claim[0]));
return Task.FromResult(new AuthenticationState(emptyUser));
}
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, _permissionManager.PermissionUser.User.GetName())
}, "FatClientAuthentication");
var user = new ClaimsPrincipal(identity);
return Task.FromResult(new AuthenticationState(user));
}
public async Task<bool> LoginUser(string userName, string password)
{
//Login via WCF connection
var response = await _clientProxy.Login(new LoginRequest
{
LoginUserName = userName,
Password = password
});
response.LogExceptionIfFaulted(_logger);
if (response.Ok)
{
_permissionManager.Initialize(response.LoggedInUser);
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
}
return response.Ok;
}
The login works fine. For testing purposes I always log in with fixed user credentials. After the successful login I fire the NotifyAuthenticationStateChanged event, which results in a correct call of the GetAuthenticationStateAsync method. The now logged in user is correctly wrapped inside the AuthenticationState. When debugging the code I can see that the Identity with the name claim is the correct user and the IsAuthenticated property is true.
However, when using the "AuthorizeView" component, I always get an "empty user" (no name claim, no user name, IsAuthenticated is false)
I now have a small component just for testing:
<AuthorizeView>
<Authorized>
<h2>User @context.User.Identity.Name</h2> is logged in!
Claims:
<ul>
@foreach (var claim in context.User.Claims)
{
<li>[email protected]; [email protected]</li>
}
</ul>
@context.User.Claims
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
</Authorized>
<NotAuthorized>
<h2>User @context.User.Identity.Name</h2> @*this is an empty string*@
<h2>Authentication Type: @context.User.Identity.AuthenticationType</h2> @*empty*@
<h2>Authenticated: @context.User.Identity.IsAuthenticated</h2>@*false*@
No user is logged in!
</NotAuthorized>
Im using the AuthorizeRouteView and the CascadingAuthenticationState in the App.razor like in the official sample displayed in https://learn.microsoft.com/en-us/aspnet/core/security/blazor/?view=aspnetcore-3.1
Accessing the AuthenticationState via an CascadingParameter also results in the same "empty user".
Appreciate any help,
tilt32
EDIT 1
So I looked into the login behaviour again, making sure that the event is called. I then figured out, that my AuthenticationStateChanged event has no subscribers (is null). My impression was, that something in the framework attaches to this event at startup. Maybe I did forget some configuration method call in the startup ? This is what I do in the configure services:
services.AddScoped<AuthenticationStateProvider, MyAuthenticationStateProvider>();
services.AddScoped<ServerAuthenticationStateProvider, MyAuthenticationStateProvider>();
//Interface which I use in my LoginCompontent and at Startup to log in with the default user or some real user credentials
services.AddScoped<IAuthenticationService, MyAuthenticationStateProvider>();
I also tried the approach suggested by user enet. Sadly with no success, the result was the same. During the login a call to NotifyAuthenticationStateChanged and hence to the event with no subscribers is done.
The WCF service we use in the background requires a logged in user. Hence i made a guest user with limited rights to solve this issue. So the app steps into the GetAuthenticationStateAsync and tries to fire the AuthenticationStateEvent directly after startup (during a loading screen).
EDIT 2
So I now tried some additional setup steps, from which Microsoft wrote in the Blazor documentation, that they should not be necessary for server-side blazor:
The ConfigureServices now looks like this
//Authentication & Authorization setup
services.AddOptions();
services.AddAuthenticationCore();
services.AddAuthorizationCore();
services.AddScoped<IPermissionManager, SingleUserPermissionManager>();
services.AddScoped<AuthenticationStateProvider, MyAuthenticationStateProvider>();
services.AddScoped<ServerAuthenticationStateProvider, MyAuthenticationStateProvider>();
services.AddScoped<IAuthenticationService, MyAuthenticationStateProvider>();
In the Configure(IApplicationBuilder app, IWebHostEnvironment env) Method, I added the following calls:
app.UseAuthentication();
app.UseAuthorization();
This did also have no effect.