I noticed that when I am logging in, duplicate claims are being set for some reason like in this image:
I'm not sure what is the cause of this issue but as a result, I am unable to add custom claims to the claims list. The strangest thing is that this code came from another computer via Github and it worked there. Is there an area to clear cookies or something?
This is my login code
namespace Application.Areas.Identity.Pages.Account
{
[AllowAnonymous]
public class LoginModel : PageModel
{
private readonly SignInManager<ApplicationUsers> _signInManager;
private readonly UserManager<ApplicationUsers> _userManager;
private readonly ApplicationUsersData applicationUsersData;
private readonly CustomClaimsCookieSignInHelper<ApplicationUsers> _customClaimsCookieSignInHelper;
private readonly UserRolesData userRolesData;
private readonly ILogger<LoginModel> _logger;
private List<Claim> claims = new List<Claim>();
[BindProperty]
public LoginViewModel Input { get; set; }
public string ReturnUrl { get; set; }
[TempData]
public string ErrorMessage { get; set; }
public LoginModel(SignInManager<ApplicationUsers> signInManager, CustomClaimsCookieSignInHelper<ApplicationUsers> _customClaimsCookieSignInHelper, UserManager<ApplicationUsers> userManager, ApplicationUsersData applicationUsersData, UserRolesData userRolesData, ILogger<LoginModel> logger)
{
_signInManager = signInManager;
_userManager = userManager;
_logger = logger;
this.applicationUsersData = applicationUsersData;
this.userRolesData = userRolesData;
this._customClaimsCookieSignInHelper = _customClaimsCookieSignInHelper;
}
public async Task OnGetAsync(string returnUrl = null)
{
if (!string.IsNullOrEmpty(ErrorMessage))
{
ModelState.AddModelError(string.Empty, ErrorMessage);
}
returnUrl = returnUrl ?? Url.Content("~/");
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
ReturnUrl = returnUrl;
}
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl = returnUrl ?? Url.Content("~/");
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
var avm = applicationUsersData.GetByUsername(Input.Email);
var user = applicationUsersData.Get(avm.Id);
var roles = userRolesData.GetUserRoles(user.Id);
foreach (var item in roles)
{
var currentItem = new UserRoleDetailsViewModel
{
Id = item.Id,
Name = item.Name,
ApplicationId = item.ApplicationId,
ApplicationName = item.ApplicationName
};
var convertedItem = JsonConvert.SerializeObject(currentItem);
claims.Add(new Claim("Roles", convertedItem));
}
await _customClaimsCookieSignInHelper.SignInUserAsync(user, Input.RememberMe, claims);
_logger.LogInformation("User logged in.");
return LocalRedirect(returnUrl);
}
if (result.IsLockedOut)
{
_logger.LogWarning("User account locked out.");
return RedirectToPage("./Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return Page();
}
}
// If we got this far, something failed, redisplay form
return Page();
}
}
}
My Custom Claims Cookie Helper:
public class CustomClaimsCookieSignInHelper<TIdentityUser> where TIdentityUser : IdentityUser
{
private readonly SignInManager<TIdentityUser> _signInManager;
public CustomClaimsCookieSignInHelper(SignInManager<TIdentityUser> signInManager)
{
_signInManager = signInManager;
}
public async Task SignInUserAsync(TIdentityUser user, bool isPersistent, IEnumerable<Claim> customClaims)
{
//var claimsPrincipal = await _signInManager.CreateUserPrincipalAsync(user);
//if (customClaims != null && claimsPrincipal?.Identity is ClaimsIdentity claimsIdentity)
//{
// claimsIdentity.AddClaims(customClaims);
//}
//await _signInManager.Context.SignInAsync(IdentityConstants.ApplicationScheme,
// claimsPrincipal,
// new AuthenticationProperties { IsPersistent = isPersistent });
}
}
As you can see, even if this code is commented, after the cookie helper has been passed through, the claims are still duplicated.
I'm not sure where this is causing issues but the solution I had to myself was to clear all the existing claims and just re-add them