Permission control using apache shiro - shiro

I am new in apache shiro, and I read almost 60% of tutorials in apache shiro page.
It is a wonderful framework, however I wonder if it can meet my requirements.
I am interested in the permission-based authentication.
For example, to make sure if the user have the permission of delete resources, we can use this:
currentUser.isPermitted( "resource:delete" );
However in our application, even a user have the permission of delete resources, he can only delete some specified resources, not all of them.
For example(just an exmaple), the resource have an filed named createdby to record the one who create this resource.
Now user can only delete the resources created by himself if he have the resouce:delete permission.
In fact, the resources which can be deleted by the user(who have authenticated and have delete permission) will be calculated by more constraints.
Now how to make shiro work in this suitation?

You can do this in Shiro but you will have to write some code. Either create a subclass of Authorizer and inject it into the security manager or create a subclass of one of the realm classes such as JdbcRealm. Then override the isPermitted method. This will need to have access to your permissions model, for example the database table or a document in a NoSQL database.
Your call to isPermitted will need to specify the resource you are deleting so you can look it up in your overridden method.
If you override the isPermitted method in the AuthorizingRealm subclass you will have access to the logged in user's principals and the user's Roles: this gives you quite a bit of flexibility because you can have says: user (principal) Fred with roles: Manager, Administrator. Your permissions model can then decide if Fred, a Manager or and Administrator can perform the task on the specified resource.
Hope that gives you some ideas.

From the extent, I have explored Shiro, I don't think it gives that level of flexibility to have a customized check. It basically functions based on roles and permission defined in the config file.
For this functionality I would suggest that you display only those records the user is allowed to delete, by have this check at query fetch level. (or) add a condition at the UI level not display the delete button if logged in user is same as created by. This is just a suggestion.

Related

Keycloak user management

I'm developing a microservice (restful) project that uses kaycloak as IAM. I could create realm, client, users,... for authenticating but my concern is should I manage users only on keycloak or creating my own user table in my microservice?
is should I manage users only on keycloak or creating my own user
table in my micro-service?
First you need to check what can one do (or not) with Keycloak regarding user management and compared with your current (and possible future) requirements. If it does not completely fulfill your requirements then you can either extend Keycloak, adapt your requirements, or (probably the most straightforward solution) have your own user table in your micro-service.
You might want also to create your own user table for performance reasons. Depending on how slow it is to access Keycloak in your setup you might consider using that user table as caching mechanism for quick access of user-related information.
The problem of having that user table is that depending on the user information stored on Keycloak and on the user table you might have to keep them in sync. Moreover, if that information exists on the user table and not on Keycloak, and you need that information on the tokens, you will have to think about how will you handle such situations.
Personally, I would try to avoid creating the user table unless it is really necessary. So a complete answer to your question will most-like be highly dependent of your own needs.

Keycloak redirect fails when number of roles are in the hundreds

I have 2 users, one with less than 30 roles and one with 400 roles. When I login with the 30 role user, I can reach the redirect URL without issues. But when I log in with the 400 role user, the request to the redirect URL doesn't complete. If I reduce the number of roles in the 400 role user then it will work. So, is there a way to disable passing roles in the java access token or increase some limit somewhere that's causing the failure?
I would suggest to focus rather on roles reduction/optimization than forcing the transmission (raising limits) over the maximum number of roles inside tokens (or anywhere else).
Some interesting questions (among others) to start with:
Which protected resources am I going to serve?
What am I trying to protect? and what are the associated risks? (build a Threat Model)
How do resources are served by each application? and how are they distributed among my applications?
What kind of resources are they? How can I group them? Which sets are identifiable? or what are the relationships between them? What actions are possible against all sets of resources?
Who are the users of each application? How will they interact with my resources? Which flows are sensitive?
What roles can I define for all my resources?
Which role can apply to each application, resource type or set?
What kind of user groups can I create?
Do I need additional attributes or claims for each set of roles or users/groups?
I firmly believe that if you answer all these questions you will end up having a bunch of roles instead of hundreds. Think security by design and follow principle of least privilege.
Focus on your use case
Now as far as I understand, your blocking point is that you are assuming that each resource is unique, sensitive and requires its own permissions, and consequently a role definition. While it may be true in some cases, in most other cases it does not mean that you have to use the token roles/scopes/claims to secure your assets deep at the resource-level. I'll try to illustrate this sentence by an example.
RBAC and authorizations example for your use case
Let's assume that:
you have millions of sensitive resources to serve
each registered user of your application has access to a (different) set of these resources.
your resources are splitted into, say, 3 categories (e-books, videos, musics).
each resource can be downloaded, uploaded, deleted.
your application will meet unregistered users, registered users, contributors and administrators
registered users will always have read access to resources (not a single action will ever allow a modification)
contributors are particular registered users who can perform special actions including modification ('upload', 'edit')
contributors and administrators may have access to various administrative parts of the application
your application will evolve by serving additional categories of resources in the future and new actions will be available to users later (such as 'flag', 'edit' or 'share link').
Then first things first:
organize your resources accordingly by serving them behind categorized paths such as: .../myapp/res/ebooks, .../myapp/res/videos, .../myapp/res/musics
identify your resources via UUID such that a resource may look like: .../myapp/res/ebooks/duz7327abdhgsd95a
Now imagine that your business risks or at least the greatest risks you wish to avoid are:
unregistered users having gaining access or rights for any part of the application or resource
uncontrolled registration process (robots, spam, no mail verification, fake users, ...)
registered users gaining illegal privileges (unauthorized actions, access to other categories, illegal administrative rights)
discovery of available resources by any mean
You will note that I voluntarily didn't listed:
registered user having illegal access to certain resources. For example: maliciously pointed/provided by an existing user.
This is because it is not a high risk as you may hold contact information about registered users as well as log activity and actions, quota or requests throttling, and you may be able to ban them or start legal action against them. Your registration process is also assumed robust and secure. Nonetheless if its considered a critical risk you can address this with extra mechanisms (cf. suggestions at the end). But never will it result in adding extra roles, such as one per resource, as it does not fit in any security model.
That being said, finally, here are the roles and authorizations scheme you may come with:
SCOPE / AUDIENCE
MY_APP
ROLES
USER
CONTRIBUTOR
ADMINISTRATOR
CLAIMS / ATTRIBUTES
CATEGORIES
ACTIONS
--> POSSIBLE USER GROUPS
USERS
Roles: USER
Claims: CATEGORIES(variable), ACTIONS('download')
CONTRIBUTORS
Roles: USER, CONTRIBUTOR
Claims: CATERGORIES(variable), ACTIONS('download', 'upload', 'edit')
ADMINISTRATORS
Roles: USER, CONTRIBUTOR, ADMINISTRATOR
Claims: CATEGORIES(*), ACTIONS(*)
Following this model, assigning the correct group to each registered user will provide high-grade security by mitigating/controlling the main risks. As claims/attributes are defined in the token(s) (managed and signed by Keycloak) then you can trust this information in your application and serve your resources accordingly and safely. There is also no risk of illegal access or discovery of resources as you are using UUIDs, only registered users having had access once to a resource will know it and registration with appropriate category access will be needed for another user to access it (to only be able to read it basically). Of course you may store in a database the list of resources to which each user has access to, raising the overall security to a very high level.
However, if the latest is not enough you may also implement rolling UUIDs or temporary links for your resources when served to users. To go farther you may also define groups and masks for your categories, resources and actions.
In fine, in this example I made use exclusively of token claims to define roles (common claim), categories and actions (custom claims). In terms of security the authentication and identity will be the first-line security followed by roles then categories, actions and stored list of resources per user (db).
Other alternatives are obviously possible, its just an example. Still, I hope it helps!
To fix this problem you should start from defining client scope mappings for each of you applications (e.g. oidc clients). Main idea of this facility is that even if your user is super duper admin with all existing roles, all of his roles actually don't required for any particular application. For example client foo which defines following roles:
foo_user
foo_viewer
to perform its security logic need to know only whether currently logged user has foo_user or foo_viewer, but it doesn't care about has this user roles bar_user or bar_admin from application bar. So our goal is to make Keycloak return for any client access token with only valuable set of roles for this client. And roles scope mappings is you friend here. You can set for client foo scope like:
foo.foo_user
foo.foo_viewer
bar.bar_admin
and now even if logged user has role "bar.bar_admin" this will not go to access_token since client foo doesn't take this role into account. After applying some scope settings you can test them at 'Clients -> $CLIENT_OIDC_ID -> Client scopes tab -> Evaluate sub tab.
As for you case with 400 roles, i'm quite confident that none of your application requires all of 400 roles, so precise scope configuration for you apllications can drammatically reduce access token size.
But if i'm mistaken and you really have an application that rely on large amount of roles you should look into you runtime settings.
For example if you run keycloak behind reverse proxy like nginx large tokens may not fit in default HTTP parameters buffer size (afaik about 2-4kb) so you have to increase it via appropriate nginx configuration option. Another example is tomcat which has about 16kb as default HTTP header buffer, so if you send request with very large access token in Authorization header Tomcat may not handle this request properly.

Role Activity & Access Level

I have developed a web application with following architecture:
Frontend : Angular 6
Backend : Java REST APIs with Springboot
I want to add authentication and authorization to it. For that I'm looking for some open source application (e.g. KeyCloak, Gluu etc.). I would like to know in which tool the below scenarios are supported.
There will be predefined set of Activities on UI (e.g. Add, Edit,
Delete etc)
There will be predefined Access Levels (e.g. Read, Write, No Access)
I should be able to create Roles, then assign activities and access levels to those roles and assign those roles to user.
Can you please help me to find out a tool which supports my above scenario?
I tried something for KeyCloak, but i couldn't find a way to add activities, access levels and map roles to it. I think everything there is governed by Role only.
I just realized that I need Activity based authorization and not Role based authorization. Please help me find some tool for that.
I'm not sure what is meant by activity based authorization but i suspect you actually mean permission based authorization, in example: Grant permissions to users to perform certain actions.
Shiro offers you permissions and role based authorization out of the box.
You can create roles, add permissions to these roles and assign them to a user. Supported are implicit and explicit roles, whereas one role can hold any number of permissions. You can even work with wildcards and group the permissions.
For more information you should take a look at the official Shiro entry and especially the web documentation for your project in particular. Shiro offers full support for Spring-Boot applications, you can find a HowTo here.
Shiro fully supports your described scenario.

How to unable backend Customer Module for several users?

I'm working with Shopware.
I've added a new attribute "proxy" to the s_core_auth table for each user in order to show the ability to get access to the Customer Module in the backend, so that if a user is not selected as "proxy" he/she won't be able to make changes in that module.
I need help to understand what I need to write in my plugin's code (maybe having only a Subscriber file.)
I'll be very grateful!
Adding a custom column to the s_core_auth table is not a good idea. What you're trying to achieve can be done with user groups and group rights. From the Shopware Documentation:
With User administration you are able to create new users in the backend and control access rights to areas, modules and plugins in accordance with certain group policies that you define per ACL (Access Control List). Within the ACL you have the possibility to control precisely which user is able to perform which activity. Thus, it is possible to assign certain reader rights to an administration group without granting them authorization to edit or delete.
You can find instructions for User administration inside the Documentation.

Zend Acl in Service Layer/Navigation

Im working on a "what I thought would be simple" application using zend framework. This is my 4th application with zf, but my first with a dynamic ACL. Application uses standard MVC setup with Model/Domain Layer consisting of a Service Layer to access my Models(popo) which are mapped through Mappers. For each Model I have a corresponding Service and Mapper. I would like to have my UserModel implement the Role interface and then all my model based services implement the Resource interface. Also I would like to have specified predefined privileges based on static roles, but also be able to change specified privileges for each user based on the user's role(s);
So for instance:
I role of 'vendor' that by default has access to the 'invoice' resource with 'create', 'edit' and 'view' privileges.
So my InvoiceService I would would be the 'invoice' resource with methods create, edit, view, and delete(but by default only role admin could delete an invoice.
For a specific user with role of vendor I would like to be able to grant delete privilege, or for another user with vendor role I might like to be able to deny edit privilege. This im thinking would have to be persisted in some way and dynamically loaded.
So to my actual question(s).
Am I going about this the wrong way?
Also how could a solution like this be implemented with Zend Navigation?
Any ideas pointers lessons feedback would be greatly appreciated.
Sorry if I have done a crap job with my explanation been up all night.
Yes, as David said you are on the right track. Zend_Navigation plays very nicely with Zend_Acl. You can define your navigation in an xml or ini file, assigning each page a resource and required privilege, and then inject the ACL and the navigation container into the navigation view helper. You can also set the current role for the navigation helper to whomever is currently logged in, which will show or hide navigation elements based on the ACL.
I will say that defining all those pages in a navigation container is a bit tedious and verbose, but not difficult.
As for defining your ACL, you can do something as simple as defining all your roles and resources in a single php file, or you can have a more flexible approach and store this information in a database and build the acl. You'd definitely want to cache the ACL with the latter approach.