I want to go one step further than simple roles based authorisation (Admin, User, Super User etc)
and instead do Activity based authorisation .
My thinking was to assign activities to logged in users which related to whether or not they could perform a action.
For example
CreateUser
ReadUser
UpdateUser
DeleteUser
I would create pages that relate to the above activities
i.e
CreateUser.aspx
on each page i would do a check to see if the authenticated user does in fact have rights to access the activity.
i would do this by making use of Roles.
for example
IsInRole("CreateUser")
Previous to this i could assign the Activities (Roles) to the authenticated user after successful login
My only real concern with this is that by doing this when i authenticate the user and build the authentication cookie it will include alot (potentially) of Roles for each user.
for example i currently have 60 activities in my system (but this could increase as we add more features - each feature is in itselve a new activity)
If the authentication cookie has to carry approx 60+ roles (activities) would that cause any known issues?
Can anyone suggest an alternative approach ?
You may want to look into IdentityModel framework. It has the base class for building a custom Authorize module to verify permissions based on Resource-Action pattern. But this is built for .NET 4.5, not sure what your platform is.
.NET 4.5 also includes SessionAuthenticationModule (SAM) for web authentication. SAM can cache the roles between user calls, so that you don't have to send them back and forth in a cookie. Here is some more information on how it works.
Use Operations and Permissions, as described in Ayende's blog. He has lots of articles on the topic.
http://ayende.com/blog/3109/rhino-security-overview-part-i
http://ayende.com/blog/tags/rhino-security
What you want is a capability list approach.
The solution to this is a mapping of roles to capabilities, similar to this:
>Online Anon User Admin
Article ReadOnly ReadWrite ReadWrite
Article.List ReadOnly ReadOnly ReadOnly
Article.Edit Hidden ReadWrite ReadWrite
Article.Delete Hidden ReadOnly ReadWrite
Article.Title.Edit * * ReadWrite
In practice, these will be your coordinates:
>(system state)
The system may be "Online, Offline, Maintenance" and maybe more.
Use the initial > to find the start of your matrix in the file (you'll have many of these). In C# you'll have an enum.
On the same line are the roles:
Anon User Admin
Then on the left side you'll have the capabilities scoped into namespaces and actions:
<item>
<item>.<action>
<item>.<field>.<action>
<item>.<field>.<value>.<action>
The cells will contain one of these values:
Hidden, ReadOnly, ReadWrite or *
The * will mean "inherit" from the parent item or field.
This way you'll be able to fine-tune the permissions based on items, actions, roles and the current system state.
A simple parser translating the list into an in-memory structure will do. Don't put this on a DB, it will be a pain. Keeping it on the text-file/in-memory level is better. Add a FileSystemWatcher to read that file whenever it is changed for additional functionality and leverage lazy loading. Also, store it in Application state memory, not in a session.
Remember: the default will be Hidden (not even read access, the item/action will be completely inaccessible to that role.
Your real concern will then be which roles you'll really need (in my experience a role pretty much maps to an UML actor, maybe with some slight variances), and what the items/fields/values and actions really are. When you write an item you can really mean a group of items. There is no need to map the capability list directly unto a database/entity or code structure. The capability list is on a higher language level, it is semantic and bound to the domain, not to the code (I want to stress this because it's the real power behind this approach).
Once you have implemented this approach with a simple parser and helper object (Information Expert Principle is well advised, avoid Singletons) you'll be able to reuse it in many applications.
Related
I have a C# project called Authentication that allows users to login and get their login credential checked and if passes, returns the token.
I want to reuse that C# Authentication project for other Applications that I am designing. Is it a good practice to store all the users from different Applications in one table or is there a better way to go about coding for One Authentication project for many Applications?
It depends.
There is a difference between code reuse and infrastructure reuse. The former is OK as you get a clean separation between the applications. Sharing a database is not recommended as it can introduce security vulnerabilities if you do not design it carefully.
I would also separate the notion of users and accounts. An account is used to log into an application and load the correct permissions. i.e. the account controls what an user can do in an application while the "user" object describes the user itself.
If you separate it like that, it's much easier to create a reusable library as everything related to authentication/authorization is in its own part. That's because the authentication design rarely changes. What differs in applications is typically the information that describes the user and the kind of customization that every user want to have.
Short answer:
Separate everything related to authentication and authorization into an "Account" object.
Collect everything describing the user into an "User" object.
Reuse the account part, but build the "user" part in every application.
Never, ever share the database between services. It will create a maintenance nightmare.
Every DB should be designed around (and after) the Bounded Context handled by the relative microservice.
In your case this means one DB to store the authentication data, then another DB per-service, with the relative data.
It is perfectly fine to have a Users table in separate DBs holding some duplicate data. As long as you're diligent enough and have a good strategy for keeping that data in sync.
I am in the process of creating a web application that allows users to add, edit and share content and need some help understanding how to set permissions for the content. Here is the setup:
There are multiple users.
Each user can add content (an object created from a class called Project)
For each project, the user who added it can set the permissions that restrict what other users can do. To keep it simple, let's say there are two permissions: view and edit.
Item 1 is very straight forward and ASP.NET provides user login and identities. 2 is also simple. What about 3? What is the best way to store and enforce these permissions? One way to do this with code is to have a list in the project class that stores user IDs and the associated permissions.
But are there built in features in ASP.NET to facilitate 3? I am familiar with roles, but I don't think that they would work because each project might give users different permissions. I have also been reading about policies, but I don't understand it well enough yet to figure out if I could use it to handle the permissions.
Please let me know if existing ASP.NET features can be used to manage the permissions. If not, is the approach that involves storing the User IDs and permissions the way to go or is there a better (safer) way to do it?
Background
What is the best way to apply granular right level restriction in ASP.Net core. I've have already set up authentication and my application issues tokens that that expire after a certain amount of time.
My web app also makes use of roles and rights, where a certain role is can be associated with a set of rights. I've seeded the rights and restricted access to them in that even admin users cannot change, create or deleted any (i.e. read-only). The roles on the other hand are dynamic, though the super-admin and admin are fixed. Any user with a super-admin access role has the power to create new roles and assign rights to that role.
What I am trying to do is to restrict access to all the other controllers in my application based on these rights.
I am considering using Policy-based authorization where each right will be associated with a specific policy (i.e [Authorize(Policy = "delete users")]). Then I would embed all the rights the user has in the token I issue out on login.
I am reluctant to implementing it this way since, though the rights may be hard coded, they may/will increase in time, if I have a very large number of rights then I may be a bit inefficient to be embedding all of them into the token.
Is there a better to achieve this level of security???
If you need, in your own words,
granular right level restriction in ASP.Net core
You need to externalize your authorization rather than build it inside your code. The challenge is that existing frameworks (within .NET, Java...) give you roles and at times claims you can use in your code to determine whether a user should have access to a given function / transaction / data set.
But that forces you to write that code (in C# in your case) every time. And, of course, if your use cases change, you need to rewrite your code. it also forces you to create an data model / information model in your database where you create links between users and roles and maybe one day permissions. And then you end up wondering how to handle segregation-of-duty or delegation or other scenarios which neither your code nor your information model allow for.
An alternative is to externalize your authorization to an externalized authorization manager / API that will process authorization requests for you. This is called ABAC (or attribute-based access control; abac). ABAC gives you:
an architecture (see below)
a policy language (xacml or alfa)
a means to query the authorization engine
either via a Yes/No Permit/Deny request/response flow e.g. "Can Alice view item #123?" "Yes, permit"
or via an open-ended interface e.g. "What can Alice view?" "documents in sales"
The Architecture
In ABAC, you choose to build your apps / APIs / solutions in a way that they only focus on the core business logic of the app e.g. serving medical records.
The app itself will not do any decision making as to who can view which medical records. You delegate the decision making to an external authorization engine known as a Policy Decision Point (PDP).
To delegate the authorization, you use an interceptor called a Policy Enforcement Point (PEP). That interceptor can be within your app code or - better yet - sitting in front of well-known interfaces so that it can intercept your transactions / data flows. For instance, if you have an API e.g. /myservice/records then you would have the PEP sit in front of the API intercepting the flow (JSON, XML...)
The PEP sends requests to the PDP e.g.:
Can Alice view medical record #123?
Can Bob edit the SSN field of medical record #34?
Can Carol print record #123?
The PDP replies with Permit, Deny based on policies that use attributes. And this brings us to the second part: policies.
Attributes & Policies
In ABAC (and XACML), you can write any number of policies you like that use any number of attributes you can think of. Attributes are, simply put, key-value pairs e.g.
role=="manager" (yes, role can be an attribute).
dateOfBirth = 1901/04/01
citizenship = "German" and "Canadian"
Attributes can be about users (as above) or resources or actions or even contextual information e.g. time.
record owner, size, classification, department are all attributes of the resource.
Once you've defined your attributes, you can start defining your policies. Assuming the use case is to control access to medical records, you may have authorization requirements e.g.
Doctors can view the medical records of patients they are assigned to.
Other medical staff can view medical records of patients in their unit.
A patient can view their own medical record
A patient can view the medical record of another patient if they are the legal guardian for that patient.
A doctor A can view another doctor (B)'s patients' medical records if B is on vacation and A is on B's delegate list.
No one can view a medical record if they are outside the hospital.
As you can see, you can write any number of policies and you don't need to touch your apps at all. All you need to do is edit your policies.
It gets better: this approach is not specific to ASP.NET. You can use the same approach and architecture for other languages (Kotlin, Java...), layers (API, data, UI...), and so on.
HTH,
David.
Further Reading
Benefits of ABAC
ABAC on Wikipedia
XACML on Wikipedia
I'm also searching for granular right level restriction in ASP.NET Core. Found Casbin library. It supports RBAC and ABAC and PERM instead of XACML. Simple and fast.
My website has forms authentication, and all is well. Now I want to create a subdirectory and have it also password-protected, but! I need the subdirectory to use a completely different set of logins/passwords than the whole website uses.
Say, for example, I have users for the website stored in the "Users" table in a database. But for the subdirectory, I want the users to be taken from the "SubdirUsers" table. Which probably has a completely different structure.
Consequently, I need the logins to be completely parallel, as in:
Logging into the whole website does not make you logged into the subdirectory as well
Clicking "logout" on the whole website does not nullify your login in the subdirectory
And vice versa
I do not want to create a separate virtual application for the subdirectory, because I want to share all libraries, user controls, as well as application state and cache. In other words, it has to be the same application.
I also do not want to just add a flag to the "Users" table indicating whether this is a whole website user or the subdirectory user. User lists have to come from different sources.
For now, the only option that I see is to roll my own Forms Auth for the subdirectory.
Anybody can propose a better alternative?
I think you can use this code to validate user with any provider
if (Membership.Providers["myprovider"].ValidateUser("USER", "PWD")) {
//your code
}
You can have a separate web.config file in the subfolder that includes only the validiation settings for that subfolder. Note that you must remove all the other settings, as there are some settings that can only be on application level.
<authorization configSource="alterativeSource.xml"/>
You will simply not be able to achieve this with FormsAuthentication only.
This problem scenario is perfect candidate for using HttpModules. HttpModules can intercept the Request and Response pipeline. You will need to write 2 HttpModules.
HttpModule for Authentication
HttpModule for Authorization
You can merge these modules into one later once your solution reaches in stable state and you are fairly able to manage the complexity.
In your solution, you will need to have a database mechanism that stores the subdirectory and user authorization and authentication mapping data. Your HttpModules can read these data take decision about the Requesting user.
You can start from here.
I could see a better answer if your users were in the web.config file, but since you're using users in a database you're pretty much going to have to use something besides forms Authentication. You'll need to set the sub directory to allow any users and then basically rebuild forms Authentication with sessions. You could make a sub class of the page class and use it to hold your all your routines to authenticate and redirect. Then you won't need to add anything to every page in the sub directory.
I know this is the answer you were probably hoping to avoid but forms Authentication is too simple a solution for this kind of complicated situation.
This can help you - numina.codeplex.com
Usually "authorization" is used after login to determine which directories, resources, etc can be used by the given user.
Have you looked at creating a role for the "main" directory and a second role for the "sub" directory and then applying the authorization tag (i.e. in the web.config)? You will need to implement an authorization provider, but that sounds like it might be a better long term solution than having multiple user tables.
Clarification Regardless of authorization (i.e. credential check or password, etc) you would still need to define the user roles somewhere, so for the sake of argument lets assume a "user table". (Nothing stops this from being an XML file in isolated storage if you wish.)
NB It doesn't actually matter that the users come from different sources. This should be reflected in the schema for the user table (i.e. a flag or another column, etc). If you fight this common pattern you will likely end up doing more work in the long run.
When there is one exception, there is likely to be another in the future....
I've not tried this but I think it would work.
You can have two membership providers (i.e., ASPNETDB_1 and ASPNETDB_2.)
These are specified in the membership provider section of the web.config. So you need a separate web.config in each subdirectory, which I know you can do.
In the root of the site I guess you would not have forms authentication. You could have just a start page that asks the user to choose which subdirectory (or you can just use subdomains (firstdir.mysite.com, secondir.mysite.com) or http:/mysite.com/firstdirectory or http:/mysite.com/secondirectory.
I am not sure of the advantage of this method over virtual directories, though, except that the root can contain some ASP programs that don't require authentication.
I understand you are looking for an "out of the box" solution and don't want to "roll your own". However;the standard membership provider does allow you to establish a profile for each user -- then it is really easy to setup one user maintenance form with a listview for each of your separate users maintenance functions and filter by role or by profile value (e.g., organizational ID). Using the membership provider classes, I personally found this very easy to do out of the box (maybe an hour of creating maintenane forms if that using all drag/drop controls, SqlDatasource + listview -- no VB or C coding required). But, separate providers and webconfigs would do the trick as well.
I'm building a SaaS app and have some issues in dealing with authorization and ASP.NET MVC. I have a previous question and this is kind of taking a cue from comments there. I need to provide somewhat granular security (e.g. lots of permissions) for each user. I realize that any discretionary system can be modeled as a roles system by just creating more roles. But that's a lot more roles than I want to deal with. I don't think roles is going to work for me and would like to work more at the permissions level.
I know the standard response to any question dealing with ASP.NET and authorization is create all your application users as Windows users and implement the ASP.NET Membership Provider. One issue, I'm not going to create Windows users. My question is can the standard ASP.NET MVC AuthorizeAttribute and AuthorizeCore be made to fit with a permissions model?
Also, apparently, the impetus here is really that ASP.NET MVC Caching will break a custom security implementation. Obviously, I don't want my pages to run slowly but I'm not sure I want this caching at all. I'm building a business application; is caching everything really appropriate? It seems that caching would just make concurrency problems much more difficult than they already are. For example, if I am caching all of my customer info pages, including the edit pages, then won't I be defeating any concurrency controls I would have in place (say, timestamp checking)?
If I were you I wouldn't create the users as Windows users, but rather store them in a SQL database. So you now have complete control over how you want to associate your security needs with your users.
Once you do that you can then create a custom security filter by creating a class that implements IAuthorizationFilter. That way you have the control you want to do whatever validation you want, roles based, permissions based, day of the week based, whatever.
You then just attribute your service methods with your new custom security filter, and pass along whatever info you need to ensure that the calling user has the appropriate rights/roles to execute the method.
First of all, you do certainly not need to make application users windows users. the default out of the box MVC has them as users stored in a sql database.
Edit Pages typically should not be cached as they will not really be loaded multiple times with the same data within the cache lifespan. my thought process is that MVC is easy enough to add caching that I would build it out first then performance test to see if it is even a necessary step. (Remember that unless you are looking at large large numbers of client connections then it is typically more economical to make a slightly less performant code and beef up the server hardware.
You do not need to create Windows users to use the ASP.NET Membership provider, it uses SQL tables to store the membership objects. Yes, you can use the Authorize attribute with the membership provider, for example, in a page that only "admins" can edit, you'll use the authorize attribute as follow:
[Authorize(Users = "Admin")]
Also, you don't want to be caching pages where users are going to be editing data, use caching (and you can do it a lot) in areas designated for anonymous users - users with no edit rights.
Hope this helps.