Instance level access control in Apache Shiro - java

I found really a flexible security framework Apache Shiro. I successfully implemented authentication and authorization using Shiro.
One of appealing features of the framework is instance based security. I just copied example from Shiro website.
The following permissions are stored in the database.
printer:query:lp7200
printer:print:epsoncolor
The following code check if for a given printer instance, the current authenticated user has permission or not.
if ( SecurityUtils.getSubject().isPermitted("printer:query:lp7200") {
// Return the current jobs on printer lp7200
}
My question is that "Is this how permissions are stored in database?"
Is there a better way to store instance based permissions?
Please let me know.
Thanks

How you store this information is entirely up to you. Your Realm implementation is responsible for querying whatever datasource you're using and extracting permission data in the format you prefer.
Some people store them as strings directly (like those shown in your example), other people store them in a dedicated table (e.g. if using an RDBMS) (e.g. permission_type, target, action columns). You can associate the permission entities to roles or directly to users or to groups which are assigned to users, etc - however it makes sense for your application.
Your storage options are entirely up to you. You materialize the data however you wish to ensure the Realm.isPermitted(...) operations function as expected.
Instead of implementing the Realm.isPermitted(...) methods directly, many people find it more convenient to subclass the abstract AuthorizingRealm class and override the doGetAuthorizationInfo method and return AuthorizationInfo instances that support permission representations.
In that method, you could query your datastore, translate the data returned into AuthorizationInfo instances, and you'll be done (don't forget to enable authorization caching - you'll see a big performance benefit).
Overriding the Realm isPermitted methods is only necessary if you want very specific control over queries, etc.

Related

How do I limit a user's scopes when granting an OAuth2 token?

In Spring Security OAuth2, I can limit the scopes that a client is permitted to request by configuring the ClientDetails. However, in addition to limiting by client, I also want to limit the scopes available to individual users; for example, a user should only be able to access the admin.forceLogout scope when holding ROLE_ADMIN.
I don't want to directly map user authorities to scopes, as checkUserScopes does; instead, I want to run custom logic to inspect and modify the scopes associated with a particular token grant. What's the best way to do that?
I see two possibilities, neither of which looks ideal:
Provide a TokenEnhancer that modifies the token after issuance. This seems like it's intended more for including additional information, such as audience claims, than for rewriting the already-available scopes. In particular, this runs after the confirm_access step.
Provide a custom OAuth2RequestFactory. At a minimum, this involves duplicating a lot of security-sensitive logic. Overriding checkUserScopes() seems like the perfect place to put the custom policy, but it's private, and the only override point is on the entire createTokenRequest().
Is there a better way to do this sort of "intersection" filtering, or are these the two options?

Multiple users using same Servlets will they override eachothers variables?

I'm making calls to the Java backend through servlets and for each call to the API im using i need to supply password and username. Can I save the users password/username in a variable so I can use it every time the user makes a call to the API?
Or will the variable be overwritten if there are multiple users?
The overall question perhaps is: Does every user get new "fresh" servlets or is the data saved from the users before?
Servlets are shared for performance reasons, so they should be stateless (or thread-safe, but then you'd just be reinventing the wheel). If you need to keep state with a user, put it into HttpSession.
If you use static variables then the variables got shared across the users. Also, it's a concurrency issue and you need to handle it. If the variables are not static then each user would have an excluded instance.
Anyway, If you want to store some information and you want to retrieve them in the future when a specific user call the servlet then it's common to use HttpSession. Also, consider that you need to grab the http cookie in your client and send it to the server for the further calls.
Also, it's a common scenario that server provides an API key for each client. Then whenever the client wants to call an API; it's necessary to send the key through a specific http header.
The above scenario would have some security issues if you don't use a secure connection like HTTPS between server and clients.
Does every user get new "fresh" servlets or is the data saved from the
users before?
Servlet instance will be created only once (unless you are doing something differently like using SingleThreadModel) & maintained by the container (like Tomcat, etc..), i.e., one single servlet instance is going to be used/shared by all requests.
So, don't use the servlet's instance variables to store any data.
Can I save the users password/username in a variable so I can use it
every time the user makes a call to the API?
You shouldn't be saving userids and passwords into JVM (RAM) memory because you will loose all of the data when the JVM shuts down, so you need to use some persistent store like a database (prefer this) or file system.

PreInvocationAdvice for authentication

Recently I've been dealing with Sring Security trying to customize it in my own way. For instance, I managed to introduce my authorization logic into a request's execution flow to tell whether the current user is authorized to call some method or not. I've done so by injecting a PreInvocationAuthorizationAdvice object where its before method is called and I can tell if the process should continue or not.
Now I want to do the same for authentication. I would like to inject my code (somehow, somewhere) where I'll be asked if some specific method needs authentication or not. I know I can do this in WebSecurityConfigurerAdapter.configure by calling antMatchers, regexMatchers etc. But I would rather do this case by case, instead of grouping URLs.
Is there anyway to do this?
It almost sounds like you are treating the ACL like an aspect that can be reused on different data sets, and if that's the assumption I'm not sure it holds up.
Last time I built a large system that included permissions, the model was something like this.
You have a number of users
You have a number of resources
You have a number of operations that can be performed on resources.
You can define roles that define different permission-sets (set of operations)
You have a number of projects
The resources are scoped by projects (they have a projectId)
A user is assigned zero or more roles in each project (mappings)
A user's access to a resource depends on the user's roles in the project which owns the resource (this could be changed at runtime).
If user U wants to delete resource A, you therefore need to find out what project resource A belongs to, and if the effective permission-set of U (join all roles U may have in the project) contained the "Delete Resource" privileged.
You need to be extremely careful on the backend when writing your SQL/JPA queries, because you can never trust the client. This means that you can't POST the projectId and resourceId, you always have to start with the resourceId, see which project it belongs to and then check if the operation is allowed.
If you have a View All feature, allowing a user to see all resources across projects, and a user can see resources in 3 of 5 projects, you need to ask your security model for a list of projects where the user has the View Resource privileged, and then add those projectIds to the query for loading the data. The projectIds needs to go into the query, just like sorting and pagination parameters. Typically you will need two queries since you also need a count query to calculate the total number of pages.
In my experience, the data model and the ACL are completely intertwined. If you want to make the ACL implementation independent of the data model, I fear you will either end up with an inefficient system that needs to load too much data and then filter away resources based on permissions afterwards. Or you will end up with a system that is overly complicated, because you need a generic way to transfer your ACL logic into the resource loading queries (and in the system I described, they are not simple to begin with).
There may be simpler systems than the one I described where a generic ACL implementation would work, but not on the enterprise stuff I have implemented over the last 8 years.

Provide data to a method using aspect oriented programming

I'm learning AOP and am comfortable with Pointcuts, Advices etc.
What am going to ask, am pretty sure is not possible, but want to ask anyways.
I have a method which takes a userId, fetches the user's record from a database and then does something to the record. I have like twenty different methods that do different things, but all of them take the userId as input and fetch the record from database. This to me looks like a cross cutting concern that can be pulled into an aspect.
But how? I know I can access the arguments (userId in this case), access the return value of the method and catch the methods exception. But how do I give the method something to work with (record in the database in this case?)
public String printUserDetails(String userId)
{
Record record = Database.fetchRecord(userId);
System.out.println(record.getDetails());
return record.getTitle();
}
So, is there a way to pull that database accessing code into an aspect?
One way I can think of is declare something like the following for input
class RequestObject
{
String userId;
Record record;
}
and inject the record in the Aspect and then call proceed(). But this somehow feels wrong.
IMO, resolving a user, using the userid, is not a cross-cutting concern and hence aspect is not the right way. The first landing page that receives a userId should actually resolve it to UserRecord and from then on, the userRecord should be the one moving around in the application.
A simple analogy I can draw to your scenario from one of my applications is, all authenticated servlets expect the servletRequest.getRemoteUser() to return the valid user login corresponding to the user sending the request. We decorated the HttpServletRequest to resolve this to a User object in our application and all the authenticated servlets downcast the HttpServletRequest to AuthenticatedServletRequest and extract this object. No one else within the application tries to resolve a user login anymore.
You cannot access a method's local variables from AspectJ if this is what you wanted to know.
The rest of the question is rather about design and the answer dependent on what you want to achieve. You can avoid code duplication in multiple methods using a template method design pattern. You can inject real or mock objects into classes if you refactor them to have a member instead of local variables. It is another question if you create the member by directly refactoring your classes or via AspectJ's (ITD)[http://www.eclipse.org/aspectj/doc/next/progguide/starting-aspectj.html#inter-type-declarations] mechanism. A third question would be if you possibly want to use an aspect for caching in order to avoid fetching the same object from the database multiple times.
I am not sure what exactly you want to achieve, so I cannot answer more specifically.

Suggestions to implement Role based authorization for an existing application in Flex

I have an application that is coded using Flex 3 on UI side and java # the service layer, along with BlazeDS. Now we need to authorize the users accessing the system based on the roles that are defined for them in the database, eg : say a user with role guest should not be able to access Admin tab on ui and also should not be able to do any operations other than viewing the data displayed on dashboard.Also the point to note here is that roles can be created dynamically by Super users from UI.
I came across this link which describes how to perform Role Based Authentication & Authorization
With this approach i need to define the roles in service-config.xml but since my roles are not pre-defined i cannot go with this.
Has anybody encountered a similar situation. Any pointers will be of great help.
Yes, I don't like the service-config idea either, don't blame you.
As far as the flex side, all you need to worry about is defining permissions, not roles or users of course.
Good form roles based security involves defining users, roles and permissions. You probably know this, but good to say it out loud anyway with the question.
Users are assigned one or more roles
Roles are assigned one or more permissions
Permissions secure functionality
So, in your application, you define specific permissions - pieces of the app that are dependent on security - visible / invisible / can or cant execute, etc. The way I normally do this is with a string constant. So, in an order management situation, I might have CanCreateOrder, CanViewOrder, CanCancelOrder, CanFlagOrder.
On the server side, a role will be tied to those permissions. Lets say:
Admin can do all
CustomerService can do view, and flag
Customer can do view
So on your server side, user A who is an admin, gets a list of all the permissions tied to the roles they are assigned, so the server sends back a string like this CanCreateOrder,CanViewOrder,CanCancelOrder,CanFlagOrder
Inside your application, when the user is authenticated and gets that list, its stored into a static global variable somewhere (or you .split() it into an array etc).
Then, when checking visibility or access to individual items, you simply check that array or string of values.
This offers a lot of flexibility as the items you are defining, most importantly, the permissions you're basically hard coding - are specific to the functional code they exist in. Therefore, there isn't a need to adjust them.
So, if you want to make customer service reps the ability to cancel orders later, you simply tie that permission to that role. Done. No code needs to be changed because the permission it simply tied to that functionality, not users, not roles.
I've done this in numerous applications, its a solid design. If you need permissions tied off other keys, that's a mildly different story, but this is a good starting point regardless.
Make sense?
**Naturally you may encrypt the security exchange and send over SSL, securing that transaction is out of scope of the discussion ;)

Categories

Resources