I am working on a project in Blazor WASM client / API back end with IdentityServer4 for authentication and Dapper for data access to a custom user store. Much of the code is stolen directly from the below article
https://markjohnson.io/articles/asp-net-core-identity-without-entity-framework/
I have implemented my own classes for User, Role, UserStore, RoleStore, and SignInManager and have registered them in the startup of IdentityServer4 Quickstart project as below:
services.AddIdentity<CustomUser, CustomRole>()
.AddDefaultTokenProviders()
.AddSignInManager<CustomSignInManager>();
var builder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
})
.AddInMemoryIdentityResources(Config.Ids)
.AddInMemoryApiResources(Config.Apis)
.AddInMemoryClients(Config.Clients)
.AddAspNetIdentity<CustomUser>(); //Added recently
Also, in Configure method
app.UseIdentityServer();
app.UseAuthorization();
From the Quickstart of IdentityServer4 Account Controller for Login Post:
var result = await _signInManager.PasswordSignInAsync(model.Username,
model.Password, model.RememberLogin, lockoutOnFailure: true);
if (result.Succeeded)
{
var user = await _userManager.FindByNameAsync(model.Username);
if (context != null)
{
if (await _clientStore.IsPkceClientAsync(context.ClientId))
return this.LoadingPage("Redirect", model.ReturnUrl);
The above code correctly uses my SignInManager and I get a successful password check. The _userManager.FindByNameAsync finds and populates the user correctly, but when it reaches the "return this.LoadingPage" part... it never goes back to the Blazor Client application. The ID4 Login page just refreshes.
I found another person who was having similar issues with not re-routing and found they added the following code right before the return to redirect to theirs. I tried it and it WORKS!!
if (await _clientStore.IsPkceClientAsync(context.ClientId))
{
Claim[] claims = new Claim[] { new Claim("test", "test") };
await HttpContext.SignInAsync(user.Id.ToString(), user.UserName, claims);
return this.LoadingPage("Redirect", model.ReturnUrl);
}
My question is... Why is the HttpContext.SignInAsync required when I have my custom SignInManager and NOT when I use the default implementation? Where SHOULD this code go?