I have an Blazor WASM application. I use the Identity Framework for login with:
SignInResult signInResult = await signInManager<ApplicationUser>.PasswordSignInAsync(parameters.UserName, parameters.Password, parameters.RememberMe, true);
The signInResult
is always Succeeded
.
In the StateProvider in WebAssembly I get a UserInfo object which among other things tells if the user is Authenticated:
[HttpGet]
public UserInfoDto UserInfo()
{
return BuildUserInfo();
}
private UserInfoDto BuildUserInfo()
{
var userInfo = new UserInfoDto
{
IsAuthenticated = User.Identity.IsAuthenticated,
UserName = User.Identity.Name
};
foreach (var claim in User.Claims)
{
userInfo.ExposedClaims.Add(claim.Type, claim.Value);
}
if (userInfo.IsAuthenticated)
{
userInfo.Id = Guid.Parse(identityService.GetUserId(User));
}
return userInfo;
}
Here User.Identity.IsAuthenticated
is always false. I also checked it right after the PasswordSignInAsync but there it is the same as well.
My startup is setup this way:
services.AddIdentity<ApplicationUser, ApplicationIdentityRole>()
.AddEntityFrameworkStores<SupportToolContext>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = false;
options.Password.RequiredLength = MIN_PASSWORD_LENGTH;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(LOCKOUT_DURATION);
options.Lockout.MaxFailedAccessAttempts = MAX_TRIES_BEFORE_LOCKOUT;
options.Lockout.AllowedForNewUsers = true;
// Email Settings
options.User.RequireUniqueEmail = true;
options.SignIn.RequireConfirmedEmail = true;
});
// Configure LifeSpan of Identity email tokens
services.Configure<DataProtectionTokenProviderOptions>(options =>
{
options.TokenLifespan = TimeSpan.FromDays(3);
});
services.ConfigureApplicationCookie(options =>
{
options.Cookie.HttpOnly = false;
options.Events = new CookieAuthenticationEvents
{
OnRedirectToLogin = context =>
{
context.Response.StatusCode = UNAUTHORIZED_STATUS_CODE;
return Task.CompletedTask;
}
};
});
And the Configure method contains:
app.UseAuthentication();
app.UseAuthorization();
AuthenticationStateProvider:
public class IdentityAuthenticationStateProvider : AuthenticationStateProvider { private UserInfoDto userInfoCache; private readonly IServiceProvider serviceProvider;
public IdentityAuthenticationStateProvider(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
..
private async Task<UserInfoDto> GetUserInfoAsync()
{
var authorizeApi = serviceProvider.GetRequiredService<IAuthorizeApi>();
if (userInfoCache != null && userInfoCache.IsAuthenticated) return userInfoCache;
userInfoCache = await authorizeApi.GetUserInfoAsync();
return userInfoCache;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
var identity = new ClaimsIdentity();
try
{
UserInfoDto userInfo = await GetUserInfoAsync();
if (userInfo.IsAuthenticated)
{
IEnumerable<Claim> claims = new[] {new Claim(ClaimTypes.Name, userInfoCache.UserName)}.Concat(
userInfoCache.ExposedClaims.Select(c => new Claim(c.Key, c.Value)));
identity = new ClaimsIdentity(claims, "Server authentication");
}
}
catch (HttpRequestException ex)
{
Console.WriteLine("Request failed:" + ex);
}
return new AuthenticationState(new ClaimsPrincipal(identity));
}
}
In general the whole process is identical to this example: https://github.com/stavroskasidis/BlazorWithIdentity (which stopped working locally as well)
What confuses me is that it worked before and still does on the server and it doesn't work locally if I checkout that history at the point deployed to the server. What do I miss?
okay, this is frustrating. The solution was to reboot all my computer. It seems that the issue was somewhere in IIS Express or so - on both my computer simultaneously.