Extending Role / Role Group in ASP.NET Identity - asp.net

I have an MVC application where ASP.NET Identity 2 is used and I can properly manage the Laboratory parts by giving permission to the corresponding role group i.e. giving read permission to Lab1 students by Lab1Group. However, I want the application is flexible so that the admin can create new laboratory lessons i.e. Lab2 and add it to the corresponding role group i.e. Lab2Group that will be created after creation of new laboratory. As far as I know creating a new Laboratory role group requires creating a new Controller having CRUD operations, but I want to use the same Controller with the newly created lab lessons. Is it possible? Because normally we need to define the access permission to a Controller by using [Authorize] attribute and I am not sure if it is possible to add the newly created role(s) to this attribute? Any idea?

If you want to put dynamic behaviour in role authorization, you can create route and role mapping in your database, which you can also cache in your application if required. Second, you have to create a custom authorize attribute, which can get required roles for the current route (controller or controller + action) and can access current user roles from current context. You have both the information and now you can authorize/ unauthorize user by overriding OnAuthorization method in your new attribute as per your application logic.
Lets divide the problem statement and then try to solve.
You have to create new role/ role- group and you need to assign them to appropriate users, which should be state forward and app admin can do that. Identity 2.0 is good for this.
As per your question, route for Lab1 and Lab2 could be something labcontroller/lab1 , labcontroller/lab2. I was trying to tell that if you want to make authorization process dynamic, you can have mapping of route and role in db.
When any user will access labcontroller/lab1, your custom authorization attribute's OnAuthorization method will read the current route from context and get its required role from above mentioned mapping.
If current user also have the required role, permission will be granted.

Related

Hardcode a role (outside database) for ASP.NET MVC and adding a Windows Authenticated Users

How would I go about hardcoding a role in ASP.NET MVC within the program itself, rather than through a database, for authentication (and then how could I add people to this role)?
What I'm trying to do is have 3 roles: Progammer, DatabaseAdministrator, and SystemsAdministrator. I'd like to be able to add people to those roles (also hardcoded), and then authenticate people based on role, rather than username. Right now, I am authenticating people like this:
If (#User.Identity.Name == "DOMAIN\\first.m.last")
What I want to be able to do is:
If (#User.Identity.Role == "ROLENAME")
However, I only have three roles and 8 people; I do not want to have to create a table in my database for them. So I'd create the role DatabaseAdministrator, and then add three people into as the string "DOMAIN\first.m.last". Then, I could have the action populate the view based on their rolename.
Everything I've seen so far has you do it through the database. Would appreciate any help. Thanks!
I am assuming that you are using Windows Authentication.
With that said you can easily authorize based on the users Active Directory Groups. This will keep you out of the database and all you have to do is add a user to an AD group if the users change.
Then you can authorize on the controller or action with this annotation.
[Authorize(Roles = #"DOMAIN\ADGroup")]

ASP.NET Core Identity and Identity Server 4 - [Roles, Claims and IdentityResources]

I would like to ask you for clarification when integrating IdentityServer 4 with ASP.NET Identity.
I am working with two database contexts.
Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityDbContext<IdentityUser> and IdentityServer4.EntityFramework.DbContexts.ConfigurationDbContext.
Identity Server 4 is using AspNetIdentity .AddAspNetIdentity<IdentityUser>().
So IdentityUser has assigned IdentityUserClaims and it's properly reflected in JWT token after successfull authentication.
Question now is, what is with the IdentityResource and IdentityClaim:UserClaim from IdentityServer4 ConfigurationDbContext? As claims are now used from aspnet identities, this entity is not used at all. Am I right?
Another question is how ApiScopeClaims are now in game? They are still used by the Identity Server because of ApiScope for which token is issued for. Right? But now it's up to me to keep in sync ApiScopeClaim and IdentityUserClaim which are from different db contexts.
Last Question is regarding IdentityRoles and IdentityRoleClaims which are not the same as IdentityUserClaims. What's the idea behind? In my idea, role is grouping of claims for specific business role for easier management, therefore role should not define new claims but reference set of IdentityUserClaims. Additionaly, I created role, assigned to user, corresponding claim types assigned to scope and result is that - claims which are assigned to role and user has this role are not included in JWT. Why?
Thank you for your answers.
IdentityResource is a category or grouping of claims. Each IdentityResource can have many IdentityClaims which are references to actual the claims held in AspNetUserClaims. The built in IdentityResources are openid and profile.
ApiScopeClaims are part of the hierarchy of Api Resources (as opposed to the identity resources mentioned above.)
ApiResource --has many--> ApiScopes --has many--> ApiScopeClaims.
Adding a claim type to an ApiScopeClaim will attach an AspNetUserClaim (if one exists) to the access_token when when the User makes a request to that ApiScope.
An IdentityRoleClaim (i.e. AspNetRoleClaim) is just a bit a information you can tack on regarding a particular role; it does not related to a User, but just to the role itself.
Sound like you want to create an IdentityResource for your logical grouping of claims, and then define those claim types in IdentityClaims. But you would need a way to first find out the user's role in order to request the appropriate IdentityResource in scope parameter. Or implement one of the IdentityServer interfaces like IProfileService to do this kind of work on the IdentityServer instance.

Symfony2 Role Confusion; how to NOT store them in the database?

I'm working on a Symfony app that will have some basic roles that can be assigned to users. Note, I'm not using the FOSUserBundle because I don't need more than half the features in it.
I have my users defined in the database, but I'd like to keep the role definitions out of the database. But several examples and other tutorials I've found keep the roles in the database, and use a ManyToMany relationship to assign them to users. This seems odd to me, since the actual use of the roles is hardcoded into the app.
For example, if I have a custom role ROLE_EDITOR, I have several routes and controllers that I may restrict to ROLE_EDITOR. Why would I "define" this role in the database? That means when developing my application and I add a new user role, I have to either write a script to programmatically insert a new role into the DB or do it manually, before the code is deployed that makes use of the role. I don't want admins to be able to add/edit/delete roles. It should be a design decision done programmatically.
In Drupal, there's a concept of Roles and Permissions. You define permissions in code and check against those, and then roles are defined in the database and are assigned permissions. But it seems that Symfony just has the concept of Roles.
I'm hoping someone can fill in a missing piece of information for me or something. How can I implement a system where the role assignments are done in the database, but the roles themselves are managed via code only?
My instinct is to just create a single entity that relates to User and has a string field for the ROLE_NAME. But this seems to go against the paradigm of having a real Role entity.

Another ASP.NET custom membership/role provider

ASP.NET 4.5 / C# / SQL 2012
I already have a well defined database with a users table and a roles/permissions column. The column contains a delimited list of roles. I was hoping to use ASP.NET's built in features on the back-end so I can be lazy and use things like the and filter by role. I'd like to read my roles from the database and tell ASP these are the roles my user is in. Custom...but hopefully simple. Here is what I have so far:
//create an identity
GenericIdentity objIdentity = new GenericIdentity("Matt"); //this would actually be the username/email of the newly authenticated user
//get roles for user
string[] strRoles = { "ADW", "USR" }; //this will get read from the database on authentication
//add identity and roles to a principal
GenericPrincipal objPrincipal = new GenericPrincipal(objIdentity, strRoles);
//add to current user
HttpContext.Current.User = objPrincipal;
//add the principal to the current context of the current thread
Thread.CurrentPrincipal = objPrincipal; //not sure what this does, doesn't affect my results/tests
If I execute the code above and then run the following:
Response.Write(User.IsInRole("ADW"));
Response.Write(User.IsInRole("xxx"));
I get a True/False as expected. However, this doesn't persist to the next page. I did a fair amount of reading on custom membership/role providers, but I can't find this specific use case. Most talk about setting up a DB specifically for this task. I also saw mention of the newer Simple Membership, but couldn't get any love from that end either. I'm hoping there is a solution that involves what I'm already doing. I'd love to execute this code when the user authenticates, but be able to reference this user in other pages. I could always call to the database for every page. I'm assuming that would suck, and that's not what the built in provider does.
Thanks all.
You are approaching it from the wrong side. You don't have to create identity and principal manually, assuming you are not creating a custom authentication module.
In any other case, you only choose the persistence mechanism and the corresponding authentication module sets the identity/principal according to the persistence.
A commonly used persistence mechanism is Forms Authentication, where you issue forms cookies. The forms authentication module makes sure the identity/principal is set early in the pipeline and takes the cookie as the source of information.
If you want to replace the cookie by your custom cookie (in other words - replace forms authentication with your own) - you have to think of a way to persist the security info, to the cookie for example.
Note, however, that this is probably not necessary. The very same forms authentication can be used with any custom membership and role providers. This is because these two have different responsibilities - membersip provider is for actual authentication whereas forms authentication module is for persisting the information for consecutive requests.
Edit: to add a role for a user so that it is persisted in the user database:
Roles.AddUsersToRoles( ... );
But first, you'd have to create users in the user database:
Membership.CreateUser( ... );
Note that Roles and Membership are facades for actual role and membership providers. While default providers use the membership database, you can easily create custom providers that persist the information anywhere at the server side.

ASP.NET Custom Role Provider - Additional Fields

I am faced with a security model problem when migrating my code to ASP.NET.
In the application:
There are multiple roles. (Role A, Role B etc)
There are multiple input/output fields. (Field A, Field B etc)
There are multiple permission levels controlling access to each field. (Read, Direct Edit, Edit With Approval, None)
Each role has its own permissions to fields. (Role A has Read Permission to Field A; Role B has Direct Edit permission to Field A etc)
Every role can be assigned to users and they are assigned by Geographic information. (User A is assigned to Role A for Continent: Europe - Country: Germany; User B is assigned to Role A for Continent: Europe - Country: France; User A is assigned to Role B for Continent: Europe - Country: France etc)
Users can have multiple roles
User identity is coming from Windows Authentication.
So my question/problem is: is it possible to represent this type of kind of multi-layered security model using ASP.NET internal membership/role providers?
If so, what should my starting point be? Creating only custom role provider with custom methods and fields be enough?
Even with the built in features of ASP.NET, the Membership Provider, and user controls, you will still have to write and manage the custom behaviors and interactions.
As example, the Membership Provider has easy ways for your to create roles and check for the existence of roles. But you will have to create the business specific dashboard call the features of the API that are appropriate to expose for your application. As example, at many of the organization that I have worked with role creation was a database only activity. User controls or site behaviors based on role were a code only activity. Managing which roles were assigned to users was a feature exposed via an admin page in the application. If a need for a new role was identified, it had to be first created by a DBA, then code/controls that were responsive to that role had to be written. After these items were deployed, application administrators could assign or remove roles to users.
To address you comment to your question, if you have Europe_Germany_RoleA, the Membership API provides methods for you to create that role, map it to a user, and to check for its existence on a particular user. like...
if(User.Roles.Contains("Europe_Germany_RoleA")) {
//your code here
}
but you would need to map that particular role to information or features specific to your application.
In retrospect, maybe what you really want to look at is the Profile Provider. Still part of the Membership set (Membership, Roles, Profiles), it is more designed to carry information. You could customize the Profile object to meet the needs of your application. For example, if you looked at this as Sectors (for lack of a better term) that could be loaded when the user logged in, you could do queries like...
if(Profile.Sectors.FirstOrDefault(sd=> sd.Name == "Europe_Germany_RoleA") != null) {
//bind to a grid, show a control, do something significant
}
and that might fit your problem better. Roles are truly only meant to act as flags (Does he have this role or not, then do something or dont), but the Profile object is designed to be customized to carry pertinent data for a user.
You can always extend it. The ASP.NET Membership model uses GUIDs as IDs for users and roles. You can add new tables that represent the added functionality and have them reference the original Membership tables.
Your problem is not in the role provider, or the membership system. This system is suitably flexible enough for your needs, and allows you to assign multiple roles to individual users. You can either use a SQL table to store these roles, or you can use Active Directory, AD is probably easier to manage the users with.
Your primary problem is going to be how you assign permissions to the fields and other objects. This means you can't just use standard drag and drop web forms, but will have to build your fields dynamically.
It's easy enough to check whether a user is in a role, this is a one-line call. But, your roles will likely not be hard coded, so you need a way to store fields and the roles associated with them, and a way to build the fields based on the users privileges.
EDIT:
Another option is to build the forms as if there was no security, then in your pre-render event go through and apply your security to each field, disabling and/or hiding fields you don't want the users to see. This may require relaying out the fields if you choose to hide them.

Resources