I am working on adding a user manager module to an application. It has a database and this database has a table of users and a table of user claims so that each user can have mulotiple claims. However, when I use usermanager to get Users.ToList() each user has its claims collection set to 0 entries even if the user in question does have claims listed in the user claims table.
It appears obvious to me that for some reason just doing usermanager.Users.Tolist() does not cause the code to consult the user claims table to check what claims each user has.
So the question is where and how to insert code that does exactly that.
Some potential issues with the existing code:
1. They have made a subclass of the IdentityUser so the UserManager is defined to be a usermanager of that subclass. But there is no explicit subclass of the usermanager. I am contemplating creating a subclass of UserManager for that purpose and if so I could override the Users property so that reading the Users list caused it to populate each user entry with the claims for that user. Does that sound like a clean way of doing it?
In some other stack overflow question I saw a reference to a Startup.Auth.cs file. We have a Startup.cs file but no Startup.Auth.cs file, should we make one?
Thank you in advance for any input.
If you used the ASP.Net identity template when you created your project, you must have a Startup.Auth.cs, it could be hidden as a sub-file of Startup.cs, or in the App_Start folder etc.
If trying to bypass the UserManager, when you request your user from EF, make sure you .Include(...) the claims property. For example:
dbcontext.Users.Include(u => u.Claims).FirstOrDefault(...);
Better yet, you should be using UserManager:
var userManager = HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
var claims = userManager.GetClaims(userId);
Related
I was using Role-based authorization for asp since now. I wanted to learn Policy-based and claim-based authorizations. Then I realized I can turn claims into something like "Permission based api authorization" which I am using for NodeJs. I have 2 questions to understand the fundamentals, thank you.
Question 1: The scenario in my mind is this: Users have roles, and roles have claims. Then I will add Authorization policies which require claims. Is this a correct approach? Basically users won't have claims. (I have seen many approaches on net, that's why I am asking)
Question 2: To do that I created tables with switches. I will add a photo to so you can picture the scenario easily.
But when I use:
var role = await roleManager.FindByIdAsync(RoleId);
await roleManager.AddClaimAsync(role,new Claim("Permission 1", "perm explanation"));
List<IdentityRoleClaim<string>> allClaims = _db.RoleClaims.ToList();
this block of code doesn't check duplication check for Claim which will be added to database. We can use RoleManager and UserManager, but is there a Manager for claims? Thank you again.
There's many way to solve authorization problem, what you are asking tended to optionality, best solution would be difference based on various usecases and the developer, who implement them themself. Since I was use all role, claim and policy, I'll giving my answers as advises.
The scenario in my mind is this: Users have roles, and roles have claims. Then I will add Authorization policies which require claims. Is this a correct approach? Basically users won't have claims. (I have seen many approaches on net, that's why I am asking)
Think of role as A BIG CLAIM. Whenever you saw a role, you grant them permission to do some stuffs. Like a when you entering a building, the security would have the permisions to check your basic personal information. It doesn't matter who the security is, they have the permisions to ask for your paper as long as they performed in security role.
To do that I created tables with switches. I will add a photo to so you can picture the scenario easily.
Have you saw something in jwt token like
"someCustomClaim": ["ClaimOne", "ClaimTwo", "ClaimThree"],
Think of how this claim will be preserve in a relational database like sql, that's why there is not an unique index there.
But, you can always add one, and enforce each claim are unique, or each role+claim is unique,... all is up to your use cases.
We can use RoleManager and UserManager, but is there a Manager for claims?
Claims doesn't make any senses if they stand alone, it has to be attached with Role or User to be meaningful right ?
So UserManager(which have claims via UserClaims) and RoleManager(which have claims via RoleClaims) are good enough, even if you in a very-complex scenerio that require both Multiple Role - Claims and Claims that directly assign to an user.
And about Policy, that's the mixin way to solve complex authorization scenerios, like UserAuthenticated + Must have Internal Role + Must have Maintaination Claim + does not have fresher claim. If you need to authorize an endpoint kind of complex like this... you might consider to register those as policies.
I tried searching everywhere on the web, but I can't seem to figure out this important part.
Basically, if we do a DB call each time when checking if a user belongs to a role - this will have negative effect on performance.
I saw code examples listing all user roles, e.g.
var roles = ((ClaimsIdentity)User.Identity).Claims
.Where(c => c.Type == ClaimTypes.Role)
.Select(c => c.Value);
the code can be used in controller action, it is also possible to fetch claims the same way in an Attribute Filter.
From this example I infer that Claims come into play (seems to be most performant solution).
I tried to find out if Authorize attribute with Roles verifies user's claims, but the official Microsoft documentation doesn't cover this bit.
AuthorizeAttribute class
Specifies that access to a controller or action method is restricted to users who meet the authorization requirement.
Properties:
Roles - Gets or sets the user roles that are authorized to access the controller or action method.
And that's the extent of what we have.
Both the Authorize attribute as e.g. User.IsInRole look at the User.Identity roles claims.
By default the Authority (where the user logs in) will add the roles from the AspNetUserRoles table as claims of type 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role'. See WIF claimtypes members.
The client app will automatically take the information from the token / cookie and convert this as User.Identity. As the claim type matches, the role type claims are mapped as roles.
This means that the app doesn't need access to the user store. In most cases this is also not possible. So it is actually not about performance, but about accessibility. Usually apps don't have access to the Identity context. So UserManager is not an option.
There is however a drawback when using claims. The information is dated. When the user logs in a snapshot of the claims at that time are added to the Identity. If in the meantime claims (or roles) are updated in the database, then these changes are not noted. Only after the user logs in again, the changes become effective.
This means that claims are only suitable for pieces of information that do not (frequently) change unless you find a way to invalidate claims. But that would probably mean to access the database or call the authority.
That's why I wouldn't recommend the use of roles. As roles tend to be used for authorization, but you can't revoke access in the meantime. So until you solve that, you may want to consider an alternative.
Sticking to UserManager is not an alternative, because the context may not be available for all apps.
That's why resource-based authorization may be a solution for you. Please read my answer here for additional thoughts.
Open your Startup file and change this:
services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
to this:
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultUI()
.AddDefaultTokenProviders();
Then the Roles should start working.
I'm using external logins for my asp.net core mvc website, and when the login completes I want to store the social info they used to login (such as username, profile image, etc.) as claims in the user's identity...
So I run code like this in my account controller after a successful login:
var authClaim = user.Claims.FirstOrDefault(c => c.ClaimType == authToken.Name);
if (authClaim == null)
externalClaims.Add(new Claim(authToken.Name, authToken.Value));
else
authClaim.ClaimValue = authToken.Value;
if (externalClaims.Any())
await _userManager.AddClaimsAsync(user, externalClaims);
await _userManager.UpdateAsync(user);
however when I attempt to do this, the claims table is duplicating the claims rather than updating them as I expected, so every time the user logs in I get another collection of records in the table for that user that are identical to the last.
do I have to delete them and re-add them instead on every login? if not, how do I update existing claims without duplicating them?
I'm doing it on every login in case the user has changed their profile or other info (and to make sure I have the most up to date token).
I'm also curious why I add the claims to the main Identity of the user. The User has a property called ExternalClaims, but it is empty and there doesn't appear to be any way to update it. It seems to me this is a better place to put these third-party Claims, but I can't for the life of me find any way to modify it...
either way, I'm sure I'd have the same problem if I use this code, so is the proper course to delete the claim on login and always add it new, or should I be doing something differently?
I've added a couple of custom columns to AspNetUsers table for Identity 2. I'm using MVC5 with C#. There are a couple of columns that contain data that is important to how the site handles the user and there is a settings page which allows the user to change these settings.
Currently, if settings are changed the user must manually log out and log back in before the changes will take effect and this is proving to be undesirable.
What is the most straightforward way of refreshing a user's profile for their current session? If this requires logout/login to take effect how might this be coded using Identity 2? A couple of pages are not contained in the AccountController and I'm not sure how to access the ApplicationUserManager and ApplicationSignInManager in the AccountController. It doesn't seem right to duplicate these objects outside of the AccountController, maybe this is acceptable?
If the only person who can change those settings is a user itself you can automatically perform SignOut and SignIn for this user when he modifies those settings. Basically all this done by SignInManager.SignInAsync method
After user modifies it's settings, you can do something like:
var user = await UserManager.FindByIdAsync(User.Identity.GetUserId());
if (user != null)
{
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
}
A couple of pages are not contained in the AccountController and I'm not sure how to access the ApplicationUserManager and ApplicationSignInManager in the AccountController. It doesn't seem right to duplicate these objects outside of the AccountController, maybe this is acceptable?
In my opinion using ApplicationUserManager and ApplicationSignInManager outside of an AccountController is not a good idea. If you are forced to do so probably there is a problem with your application architecture.If you are using an Account controller, it should be responsible for all the functionality for user account handling (Single Responsibility Principle)
In Asp.Net Identity there is class called IdentityUserclaim. When should I assign one to user? What are the advantages of assigning IdentityUserClaim to a user?
Its just an easy way for you to store arbitrary claims in the user db that will automatically get added to the User.Identity ClaimsPrincipal that is generated for the user when they sign in.