Spring Security and ABAC (Attribute Based Access Control) - spring-security

We have a medium sized business app and we use Spring Security roles and permissions (RBAC) heavily with a big kludge to turn roles on and off for certain instances plus rules hidden in SpEL within #PreAuthorize tags.
I think what we have actually implemented (without knowing it is ABAC). XACML looks very complicated and bloated so I'm not keen on the answer here:
How to change Spring Security roles by context?
Has anybody done a light weight ABAC implementation without XACML? I have hopes that would give us separation of concerns as the domain objects just do #PreAuthorize(WRITE) etc and our authorisation policy would be decoupled from it.
From what I've read the basic principal of ABAC is very simple. You have an Action (very like a Permission) and a mechanism to resolve if the current Principal has that permission on a given Subject.
I'm aware of AccessDecisionVoter which is roughly the right sort of interface but I don't think it was intended for voting on permissions. However implementing our authorisation policy with instances of something like those seems very attractive.
Sorry for the rambling question! Basically I'm interesting in ABAC but would like to avoid home brew but worried what XACML is a jumbo jet when we need a Cessna.

There seems to be two things you are aiming for:
externalized authorization, where you want to move access control policies out of the code (or at least into a central place in the code and not scattered across the Spring code)
attribute based authorization, where you want to use richer attributes than roles and permissions
I am not very sure of (2) since what you say you want to do, "action and a mechanism to resolve if the current Principal has that permission", is still, in my books, RBAC. Do you have other conditions on which access grant decisions will need to be based on? Location of the user, time of day, value of certain data in a database, properties of the resource being acted on etc.? If so, we stray into the ABAC world. Either way, I would say that RBAC is a subset of ABAC since a role is just one attribute.
Now, as for (1), the general pattern would be to first centralize the authorization engine and use the Spring annotations to call this authz. engine for access decisions. You have two choices here:
embedded authz. engine: where a library implements the engine and is called by the code just as a Java function. Could be a XACML engine or could be your own RBAC/ABAC implementation
as a network service: where a network based (micro) service answers access control decision questions. Could be a XACML engine or could be your own RBAC/ABAC implementation
In order to get the Spring based code to call this authz. engine, one approach would be to write your own Spring Security voter. Another way, which I found much easier, would be to write your own Spring Expression Language based expressions that you can then call with the existing #PreAuthorize, #PostAuthorize, #PreFilter and #PostFiler, sec:authorize tags and even from intercept-url conditions.
This is what I used when I worked on our Spring Security XACML PEP SDK. The approach should work equally well even if you decide not to use XACML for your access decision policies or the request/response communication.

A pretty nice approach without XACML can be found here. It's basically what you wanted. A lighweight approach on ABAC without implementing XACML.
https://dzone.com/articles/simple-attribute-based-access-control-with-spring

I know this question is rather old, but recently we had need for similar ABAC permissions implementation. At first I tried to find something existing which would fill our needs, but everything seemed to be over the top and very hard to use.
So I came up with very simple library called jaclp which can be found on GitHub. It supports classical RBAC approach and more complex ABAC which can be used for example on JPA entities acting as resources. The integration and setup should be fairly simple.
One of the disadvantages is that for now, definition of permissions is programmatically only. I plan to introduce configuration file from which permission rules would be loaded. Also jaclp library for now supports only static permission rules defined in code, this means that you cannot load permission rules dynamically for example from database.
Example Usage:
// Applying permissions on REST endpoints
#GetMapping("groups/{id}")
#PreAuthorize("hasPermission(#id, 'group', 'viewDetail')")
public GroupDetailDTO getGroupDetail(#PathVariable long id) {
return this.groupService.getGroupDetail(id);
}
// Defining role with both RBAC and ABAC approach
Role userRole = RoleBuilder.create("user")
.addAllowedRule("group",
(UserDetails user, GroupEntity group) -> group.isPublic(),
"viewDetail")
.addAllowedRule("group", "viewAll")
.build();

Related

Is there a fundamental difference between claims authorization and roles authorization?

VS2013, MVC5
I may get some terminology wrong because I'm new to this topic.
What I've read has led me to conclude that claims can be used for authentication and authorization which are 2 very different concepts. Assuming this thinking is correct, my question relates to claims as they might apply to authorization, not authentication (or identity? - is it accurate to consider identity as a substitute concept for authentication?)
The Wikipedia article seemed as concise as anything else I read saying (1st line last section) the difference between claims and roles is a:
distinction between what the user is/is not and what the user may/may not do
If I use claims to determine what a user may or may not do, I don't see how that is different than what roles do. This article kind of implies it's different, but the example seems the same to me with the claims example merely a better role definition, yes?
This article suggests there's little difference but the explanation seems to suggest an absolutely fundamental difference because it begins to employ a value in the claim. But unless the value allows the claim to composite roles into a single claim, it's still just a role, yes? And if you do composite roles into a single claim value in a large application, while that scheme might be more space efficient wouldn't it also require a method to decode the composited roles later?
This previously linked article stated that while there is a data structure in MVC5 for claims, it's not tied to a data attribute, so wouldn't using claims for authorization require significant extra programming or more complicated references to the claims?
So that's what brings me to ask the question in the title of the post, is there a fundamental difference? Because if not, I don't see why I would use claims for authorization.
I'm not experienced enough yet to fully follow how claims are used for authentication, but I get it there is significant value for using a 3rd party to authenticate and also for things like single sign on, but that's not my focus in this question.
You are digging too deep. There is no fundamental difference between a role and a claim. To the point that roles are stored as claims in the authentication cookie. You can pretty easily create authentication attibute that will work with claims. Only roles have slightly more code around them in the framework. When you call IPrincipal.IsUserInrole("rolename"), the framework actually checks if user has a claims of type ClaimTypes.Role with the value "rolename".
I have played with these concepts for a while and my conculsion was that claims can give you more granular authentication levels. Also you can use claims as a containers for data to add on auth-cookie. Roles are pretty inflexible in this sense.
There is no fundamental difference. The advantage of claims is it could contains data. For example you may have claim with MaxAllowedOrderSum=1000 and use it for authorizing orders.
With role authorization you will need to invent Role=PriviledgedManager and somehow get the maximum sum of orders. Nothing impossible but more entities involved.

How can a user with same role access different posts with different permissions?

I use devise for authentication and have assigned a role for each user. I have one more model posts which contain number of posts. I want to restrict one user of the role employee to view the specific post and the same user to view and create the different post. How can I do this?
I realize I am late to the battle here.
What you are looking for is an extension to role-based access control. RBAC cannot cater well for your scenario. You need to consider attribute-based access control. CanCan and Devise are two language-specific frameworks that address attribute-based access control.
If you want a broader, more generic ABAC solution, then consider XACML, the eXtensible Access Control Markup Language, which is a standard defined by OASIS much like SAML is.
XACML gives you:
attribute-based access control: attributes can be used to describe pretty much anything (users, objects, resources, context, time, actions...).
policy-based access control: policies bring together attributes to define authorization. For instance employees can view the posts of employees in the same team and can edit posts they own.
fine-grained access: it is possible to define very specific and granular authorization policies
support for segregation of duty
language-independent authorization: it works for Java, .NET, Ruby, Python, and more...
centralized policy management
Here are some interesting resources to learn more:
NIST RBAC model
NIST ABAC model
OASIS XACML website
Check out this tutorial which specify the ability to define logic to control the user activity
https://github.com/EppO/rolify/wiki/Using-rolify-with-Devise-and-Authority

WIF: Custom Claims

I'm having a hard time understanding how a Claim should be defined. There is a lot of information on the web about creating claims but none of it seems to agree. I have found four attributes of a claim in different posts:
ClaimType
ClaimValue
ValueType
Right
Given a scenario where you want to create a claim the denotes a user has the right to edit a User object, what is the correct way to set these attributes?
Also, in WIF there doesn't seem to be a property for the "Right" attribute. Is "Right" only used in the context of WCF?
Im confused, help!
EDIT:
Thanks for your responses. To make this a little more concrete, I am currently seeing two options for my custom claim:
1-ClaimType=Edit,ClaimValue=User
2-ClaimType=Action,ClaimValue=EditUser
Option one seems to be more "claims-based" and option to seems more "role-based". Thoughts?
There are two different Claim types in .Net. One in WIF (Microsoft.IdentityModel.Claims) and one in System.IdentityModel.Claims that was used in WCF pre-WIF (it's not really part of WCT though). Only the System.IdentityModel.Claims.Claim has a Right property as you mention.
I've used the claims approach with WCF and ASP.Net with and without WIF and the WIF programming model is definately the simpler of the two.
For the User editing scenario that you describe, I would define a role with a suitable name. UserEditor could be OK but it sounds very specific. You should look at the collection of all the permissions that you want to grant to those users and come up with a suitable summarising name (maybe UserAdministrator?).
For those users, you should add a role claim (i.e. of type http://schemas.microsoft.com/ws/2008/06/identity/claims/role or Microsoft.IdentityModel.Claims.ClaimTypes.Role). If your identity provider is external to your application and you can't control the claims it issues, then you will need to implement a custom ClaimsAuthenticationManager to transform the issued claim set by adding the new role claim.
Then you can decorate the operations you want to grant access to with a PrincipalPermissionAttribute something like this:
[PrincipalPermission(SecurityAction.Demand, Role = "UserAdministrator")]
This framework is fairly flexible and can be used in a number of different ways in ASP.Net, WCF or just regular .Net development. Your question doesn't give a lot of context to allow a very specific answer with examples.
I'm not sure where you read that claims should have a right property, I think that's misuse of the concept.
A set of claims on their own don't convey user rights. Rather:
claim set + policy = user rights.
Typically, claims based applications apply a policy to the set of incoming user claims to make authorization decisions. Role based access is the most common, so these decisions might be as simple as User.IsInRole("Manager"), which simply checks to see of the user has a claim of ClaimType="http://schemas.microsoft.com/ws/2008/06/identity/claims/role" and ClaimValue="Manager".
An online liquor store might require users to be over the age of 21, in which case you check the age claim. However you would have a different policy for the Canadian version of this website, where the age limit might be 18. If such "rights" were communicated via the claims themselves, then this kind of policy flexibility wouldn't be possible.

How should I do authentication in a ASP.Net MVC site?

I have a site which has an area that requires authentication. Right now I use the roles attribute on all the controllers in that area, and I run a query to retrieve that users ID, and all their settings.
It seems like a code or design smell to me that I am retrieving the userid and settings each time a controller in that area loads up? I'm not sure if I should be using sessions, or if ASP.Net MVC 2.0 provides some unique way to handle this. Another concern is security.
Overall, I don't really know which way to turn. Design wise I would like the userId and settings retrieved only once when the user logs into the area. Right now I grab the userId each time a controller loads up, and then if required, I query the database for their settings each time as well.
One of the rules about security is that you shouldn't try to do it yourself. There are many pitfalls in doing an authentication system correctly without leaving loopholes or backdoors. Thus, in that regard, you might consider the SqlMembershipProvider that comes with .NET. It can be used with MVC and provides the means to get roles and the current security context, is easy to setup and configure and will be more secure than rolling your own.
If you are not using SQL Server, you have a couple of choices. One solution would be to use something like SQL Server Express or SQL Server Compact Edition to maintain the credentials. Another solution would be to mimic the SqlMembrershipProvider database schema and then write a custom provider that communicates with that schema.
The last choice would be to write a custom MembershipProvider class. While this is still rolling your own, it forces you into the structure of the MembershipProvider so that you can swap it out at a later date for a different one (e.g. ActiveDirectoryMembershipProvider) and provides a common interface for interacting with credentials and logins which for example enables easy use of the built-in Login control.
If you are already using a MembershipProvider and are asking about storing additional user-specific data, then I would suggest the SqlProfileProvider with all the caveats I mentioned above about the SqlMembershipProvider. the ProfileProvider provides a structure for maintain user-specific data with the currently logged on user.
For more information:
Introduction to Membership
Implementing a MembershipProvider
ASP.NET Profile Providers
You could also implement a custom identity. They are very easy to implement, and they let you store whatever user information you want in Identity, which is then stored in the cookies that Identity puts down, so you're not hitting the DB every time to get that info.
Just create a new class that inherits from GenericIdentity, and you'll be on your way.
You of course have to be careful how much info you put there since it's in a cookie, but usually user related information in the case you're talking about here isn't so big.
We use a custom identity to store a few bits of info about the user, and it works out pretty well.
You could store an object in session that holds all the required user information. You will just need to add a property in the Controllers, Views or other base classes where you want to retrieve the user information/profile. This would be the authorisation info as opposed to any authentication info (eg Forms authentication)
You might try "Windows Identity Foundation". I've been using it on one of my projects for a while. It allows for "claims-based authentication", which basically means that you get to designate "claims", strings of information that describe the user when she logs on.
Once logged on, the user's claims can be read from the HttpContext.Current.User field. You can also use "Role" claims that seamlessly integrate with a role-based authentication schema; meaning that you can give the user a "manager" role claim and then use `if (User.IsInRole("manager")).
As an added bonus, WIF makes it very easy to re-use your login screen in other applications.
All in all, it's very flexible, but the documentation is very poor. I've asked and answered a number of questions about "Windows Identity Foundation" on StackOverflow.
We have done this quite a few times in the past. Similar to what Thomas mentions, what we have generally done is implemented a new Membership provider based on the Microsoft SQL Memberhsip provider to do this. We inherit from the base MembershipUser class and add any custom properties we would want to have on the user object. You have to implement a database read for the Membership provider on the GetUser implementation, so you can consolidate your extra properties you need into that database read.
If you are using SQL server, Microsoft has release the 2.0 code for it. You can get more information at Scott Gu's blog.
http://weblogs.asp.net/scottgu/archive/2006/04/13/442772.aspx
If you want to start from scratch, they also have good resources at MSDN.
http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx
and
http://msdn.microsoft.com/en-us/library/6tc47t75.aspx
Once you have implemented your provider, you can then add the Membership user to the Items collection of the current web context to get access to it from your code. The non extended properties from the base base user class are also available on the Request thread like normal.
With the Microsoft release of the 2.0 version of the source code , we found it helped us alleviate some concerns that exist about reinventing. Another thing to consider for your implementations is based on your scenario, you can bypass implementing some of the code. An example of this would be the CreateUser code if you are hitting a back end system that already has the credential information.
It seems like you're relatively happy with your authentication process but you want to explore other options for session/settings.
My suggestion has to do with settings only (roles, preferences, etc.)
In my opinion, having to traverse the whole technology stack from UI to Business Tier to DB tier to DB is sometimes a bit overkill.
For data that isn't likely to change during a session, this adds a lot of overhead... There are potentially several data transformations happening (DB (Relational Format) -> ORM -> Web Service XML Serialization -> Web Tier deserialization).
You might consider a session system that doesn't rely on a heavy RDBMS system or on the ASP.NET Caching / Session model. There are options that are very performant and that scale well.
You could use RavenDB by Ayende Rahien (Built for .NET). Its main goal is to provide low latency, high performance access to schema-less JSON documents.
Using this solution, you would set up ravenDB in the web tier so that access to data is very quick.
The first time you authenticate and retrieve settings, you would store the userID and settings information in this session DB.
Every time you load your controller after that, the settings data is accessible without having to go back to the RDBMS.
This DB could also be used to cache other web related data.
As for security, the settings data makes it to the web tier regardless of the method you use. This solution would be no more or less secure than the other options (more secure than an unencrypted cookie). If you needed to, you could encrypt the session data - but that will increase your overhead again.
Just another one of the million options to consider.
Good Luck,
Let us know what you decide!
Patrick.

Am I wrong in wanting to roll my own Authenticate / Authorize system given the following requirements?

In my pet project I want to have a user system with the following requirements:
It needs to work with Db4o as a persistance model
I want to use DI (by means of Turbine) to deliver the needed dependencies to my user model
It needs to be easy to plug in to asp.net-mvc
It needs to be testable without much hassle
It needs to support anonymous users much like SO does
I want Authentication and Authorization separated (the first can live without the second)
It needs to be safe
I'm aware I'm putting a few technologies before functionalities here, but as it is a pet project and I want to learn some new stuff I think it is reasonable to include them as requirements.
Halfway in rolling my own I realized I am probably suffering some NIH syndrome.
As I don't really like how needlessly complex the existing user framework in asp.net is, it is actually mostly only all the more complicated stuff regarding security that's now giving me some doubts.
Would it be defendable to go on and roll my own? If not how would you go about fulfilling all the above requirements with the existing IPrinciple based framework?
It sounds to me like what you want to do is roll your own Custom .NET Membership Provider.
It will allow you to use the built-in ASP.NET Authentication/Authorization attributes on your Controller Actions while giving you complete control over the implementation inside the provider (which will allow you to code it to meet the requirements stated above).
Direct from MSDN...
Implementing a Membership Provider
I think you recognize where the thin parts in your consideration are: namely in that you've included how to do what you're doing as motive in why you're doing it and the NIH (funny: I'd never seen that before) issue.
Putting those aside, your provider is something that you could potentially reuse and it may simplify some of your future efforts. It should also serve to familiarize you further with the issue. As long as you understand the ASP.NET framework so you can work with it too if you need to (and aren't specialized such that you don't know what you're doing if you're not using your tool) then I believe you've already crafted your defense.
As DOK mentioned, be cautious that you're not rolling your own here to avoid a larger task at hand in whatever your other functionality is. Don't let this be a distraction: it should be something your application really needs. If it's not, then I'd lean towards focusing on your software's core mission instead.
If you go ahead and create your own custom solution, you will have a better idea of how difficult it is and what features you want. This will help you to evaluate off-the-shelf solutions for future projects.
OTOH, spending time developing functionality that is already readily available means you won't be spending that time working on the major functionality of your project. Unless authentication and authorization are a major component of your project, you might consider investing your time, and expanding your knowledge, in another area.
I too am working on a pet Project using ASP.net MVC and db4o and did the same thing, so you're at least not alone in going down that route :). One of the biggest reasons for me to start playing around with db4o as persistence layer is that especially authorization on field level (i.e I'm allowed to see Person A's first name but not Person B's first name) is though to achieve if you're forced into complex SQL statements and an anemic domain model.
Since I had complex authorization needs that needed to be persisted (and synchronized) in both db4o and Solr indexes I started working on rolling out my own, but only because I knew up front it was one of the key features of my pet project that I wanted 100% control over.
Now I might still use the .Net Membership provider for authentication but not (solely) for authorization of objects but only after i POC'd my authorization needs using my own.

Resources