Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add claims on successful login and retrieve it elsewhere in the application

Please I need assistance in implementing a custom way of assigning claims to authenticated users. On successful login,

var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);         switch (result)         {             case SignInStatus.Success:                 //Get the user                 ApplicationUser user = UserManager.FindByEmail(model.Email);                 //Ends here                 ClaimsIdentity identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);                 AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = true }, identity); 

I use the userId to fetch the role and other information about the user from the datastore. Thereafter, I need to add claims about the user with those information such as email, role, firstName, Lastname, gender, etc. before redirecting to the user dashboard. This is the way I try to do it but the problem is that even after adding the claims at the login method, I am not able to retrieve it at the _loginPartial razor view

For instance when I want to display the email claim value at the login partial like this

var claims = ClaimsPrincipal.Current.Claims;     var principal = (ClaimsPrincipal)Thread.CurrentPrincipal;     var email = principal.Claims.Where(c => c.Type == ClaimTypes.Email).Select(c => c.Value).SingleOrDefault(); 

It returns null.

So, as a result, I can only access them on the same login method after adding them but I need to be able to access it from anywhere in the application. Please I will appreciate any assistance on how to be able to retrieve these claims anywhere else throughout the application.

Thank you.

like image 309
Josh Avatar asked Feb 02 '16 12:02

Josh


People also ask

What is a user claim?

A claim is a statement that an entity (a user or another application) makes about itself, it's just a claim. For example a claim list can have the user's name, user's e-mail, user's age, user's authorization for an action. In role-based Security, a user presents the credentials directly to the application.

What are claims asp net?

A claim is a name value pair that represents what the subject is, not what the subject can do. For example, you may have a driver's license, issued by a local driving license authority. Your driver's license has your date of birth on it.


2 Answers

You must add your claims before login not after. Consider this example:

public async Task<ActionResult> Login(LoginViewModel model,string returnUrl) {     var user = UserManager.Find(model.Email, model.Password);     if(user!=null)     {         var ident = UserManager.CreateIdentity(user,              DefaultAuthenticationTypes.ApplicationCookie);         ident.AddClaims(new[] {             new Claim("MyClaimName","MyClaimValue"),             new Claim("YetAnotherClaim","YetAnotherValue"),         });         AuthenticationManager.SignIn(             new AuthenticationProperties() { IsPersistent = true },              ident);         return RedirectToLocal(returnUrl);     }     ModelState.AddModelError("", "Invalid login attempt.");     return View(model); } 

Now since we have injected our claims while signing in, we have access to claims wherever we want:

((ClaimsIdentity)User.Identity).FindFirst("MyClaimName"); 

Also you could add your claims in ApplicationUser.GenerateUserIdentityAsync() method. By adding your claims in this method you could use SignInManager.PasswordSignInAsync() method to sign in users without any modification to default Login action method.

public class ApplicationUser : IdentityUser {     public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)     {         var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);         // Add custom user claims here         userIdentity .AddClaims(new[] {             new Claim("MyClaimName","MyClaimValue"),             new Claim("YetAnotherClaim","YetAnotherValue"),         });         return userIdentity;     } } 
like image 98
Sam FarajpourGhamari Avatar answered Sep 21 '22 11:09

Sam FarajpourGhamari


In identity 2, this is done very differently and simply by creating a claims principal factory and then hooking it up in your startup ConfigureServices as below...

public class CustomClaimsPrincipalFactory : UserClaimsPrincipalFactory<IUser, IApplicationRole> {     public CustomClaimsPrincipalFactory(UserManager<IUser> userManager, RoleManager<IApplicationRole> roleManager,                                                 IOptions<IdentityOptions> optionsAccessor)         : base(userManager, roleManager, optionsAccessor)     {     }      public async override Task<ClaimsPrincipal> CreateAsync(IUser user)     {         var principal = await base.CreateAsync(user);          // Add your claims here         ((ClaimsIdentity)principal.Identity).AddClaims(new[] { new Claim(ClaimTypes.Email, user.Email),                                                                 new Claim(ClaimTypes.Gender, user.Gender),                                                                 new Claim(ClaimTypes.GivenName, user.FirstName),                                                                 new Claim(ClaimTypes.Surname, user.LastName)                                                              });          return principal;     } } 

You would then hook it up in ConfigureServices just after calling AddIdentity like this...

         services.AddIdentity<IUser, IApplicationRole>()          .AddDefaultTokenProviders();           // Add Custom Claims processor         services.AddScoped<IUserClaimsPrincipalFactory<IUser>, CustomClaimsPrincipalFactory>(); 

Here is a very good article on the subject...

https://www.codeguru.com/csharp/csharp/cs_misc/security/asp.net-core-and-claim-based-security.html

like image 34
Hoots Avatar answered Sep 19 '22 11:09

Hoots