I need to add a claim to the user's identity after a successful user login. This is where I think it needs to happen:
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl, string myClaimValue)
{
if (!ModelState.IsValid)
{
return View(model);
}
var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);
switch (result)
{
case SignInStatus.Success:
UserManager.AddClaim(User.Identity.GetUserId(), new Claim("MyClaim", myClaimValue));
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
case SignInStatus.Failure:
default:
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
}
I think this is the right approach, but the call to User.Identity.GetUserId()
throws an exception. It looks like User.Identity
is not updated by the successful signin. In lieu of this reality, what is the best way for me to get the newly signed in user's id so that I can add a claim?
Or am I doing this all wrong?
Additional claims must be set before SignInManager.PasswordSignInAsync is triggered. This can be done by a custom ClaimsIdentityFactory:
public class ApplicationClaimsIdentityFactory : ClaimsIdentityFactory<ApplicationUser>
{
// This claim value is taken from Login View
public static readonly string MyClaimKey = "app:MyClaimKey";
public string MyClaimValue { get; set; }
public async override Task<ClaimsIdentity> CreateAsync(UserManager<ApplicationUser, string> manager, ApplicationUser user, string authenticationType)
{
var identity = await base.CreateAsync(manager, user, authenticationType);
identity.AddClaim(new Claim(MyClaimKey, MyClaimValue));
return identity;
}
}
Apply this factory before sign in step:
UserManager.ClaimsIdentityFactory = new ApplicationClaimsIdentityFactory()
{
MyClaimValue = loginModel.MyClaimValue
};
var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);
This will store claims to database UserManager.AddClaim(User.Identity.GetUserId(), new Claim("MyClaim", myClaimValue));
If you want to associated claims with the logged-in user when he logs in, You have to overwrite the SignInAsync
method of SignInManager
public override async Task SignInAsync(ApplicationUser user, bool isPersistent, bool rememberBrowser) { var userIdentity = await CreateUserIdentityAsync(user); // your code here userIdentity.AddClaim(new Claim(ClaimTypes.Gender, "male")); // AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie, DefaultAuthenticationTypes.TwoFactorCookie); if (rememberBrowser) { var rememberBrowserIdentpublic override async Task SignInAsync(ApplicationUser user, bool isPersistent, bool rememberBrowser)
{
var userIdentity = await CreateUserIdentityAsync(user);
// add your claims here
userIdentity.AddClaim(new Claim(ClaimTypes.Gender, "male"));
//
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie, DefaultAuthenticationTypes.TwoFactorCookie);
if (rememberBrowser)
{
var rememberBrowserIdentity = AuthenticationManager.CreateTwoFactorRememberBrowserIdentity(ConvertIdToString(user.Id));
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistent }, userIdentity, rememberBrowserIdentity);
}
else
{
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistent }, userIdentity);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With