Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add Claim On Successful Login

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?

like image 805
itslittlejohn Avatar asked Jun 19 '15 20:06

itslittlejohn


2 Answers

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);
like image 90
Hung Ha Avatar answered Nov 06 '22 20:11

Hung Ha


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);
    }
}
like image 32
tmg Avatar answered Nov 06 '22 21:11

tmg