We have a multi-tenant (used by multiple organizations) application in Java Spring Boot. We have to implement authentication as well as authorization in such a way that;
There can be multiple users in an organization and a user can also be part of multiple organizations.
At a time user can view data of only one organization but he can simply switch between organizations.
In an organization, there can be multiple teams.
A user can have different level of access/permissions for each team. Like maybe a user A is manager of team 1 and same time he can be member of team 2 etc.
We are planning to use keycloak for IAM. So the question is, either this type of access management will be possible to achieve in keycloak or we have to manage these permissions on database level in code? And for multi-tenancy, a separate realm for each tenant will be good or we should go for single realm and multiple groups?
Looking for expert opinions.
Related
My application has currently two types of users: Admin or Normal user.
The application has several projects: 100 or more. Per project the user has a different role like project owner, client, etc...
I'm now figuring out the best way to put those subroles in place.
Because in my services I want to use PreAuthorise("hasRole('OWNER')") so that only the right people can execute an update or whatever.
What I was trying now was giving every project a list of users that are working on it with a roles (project owner, client, etc...) when I login via Spring Security I retrieve the user and fetch all the projects where he is part of and then I add roles as follows ROLE_PROJECTNAME_OWNER or ROLE_PROJECTNAME_CLIENT.
The thing is that I can't use the HASROLE because there are a lot of projects so I can't annotate in advance which projects there are to allow a method call in my service layer. I also can't just add OWNER because then I don't know in which project. So I'm a little bit stuck here how to do this properly.
Define your own service to manage access with user/project/role and call this service directly on your #PreAUthorize.
Have a look to : https://dreamix.eu/blog/java/implementing-custom-authorization-function-for-springs-pre-and-post-annotations
Why don't you separate your users and the groups they form part of, from the roles and services they can access.
There are various ways you can do this, but one approach is to have the central authentication framework provide you the groups of the user once he performs authentication.
Now within each service, there will be a mapping between groups and roles. The roles are application specific, the authentication service or the other applications do not care about them. You might store this mapping in the individual application's database, or in a simple configuration file (maybe simply in application.yaml of the specific application).
Your groups currently are Admin and Normal but you could have others. A user could also be a member of multiple groups. So in application 1 you could say that Admin users can do role 1, role 2, role 3, while Normal users can only do role 1. Again it is many to many. This is something your UserDetails instance would carry once it recognizes the authenticated user and his groups, which are then mapped to roles as part of your Spring Security configuration. You will then be able to do PreAuthorise("hasRole('OWNER')") etc. on your services.
This way, if you add more users, you just put them in the right groups to give them access to the individual services. If you want to create new profiles, instead of just Admin and Normal, or special groups, you just do it once and update the configuration of the individual application to recognise that group if it is relevant to it (remember the user can be a member of multiple groups, so you don't even need each application to know about each group).
I don't know what mechanism you are using for single sign on authentication. But in spirit of microservices and minimal sharing between applications, you could actually put the groups as scopes in your token (if you are using JWT for example). This way the application receiving the token not only knows that the user was authenticated but knows the groups of the user without even making a query to any other system.
This architecture you will have is shown in the picture.
Each use case (service method annotated with #PreAuthorise) will have a role.
Each user will be associated with a number of groups the authentication system will provide. (For example groups in Active Directory). Upon receiving the authentication information of the user, the groups will be mapped to the roles specific to the application and populated in the UserDetails Spring Security object. Each annotated method will then get the application specific roles (not the global groups).
This gives you the flexibility to add as many groups as you like that can have the same application role.
I need to create an application with authentication and authorization using Java EE 6 (Glassfish Server). I read a lot about Java EE 6 security and just wanted to ask if my concept is correct:
Every user in the company has an account according to "X123456". I want to use this for LDAP Authentication:
Application ---> LDAP
So, I can use the company's infrastructure to authorize the user.
However I want to be in control of the roles in my application. So, I want to define my own roles using JACC. Therefore I will create a database with a user-to-role mapping,
Example: "X123456 -> ADMIN".
The benefits would be:
I don't need to store any password
I can create a kind of admin panel in my application where I can set the existing roles to users dynamically
Do you think this would be technically possible and good practice?
Alternative: Would it be possible to define the roles (Admin, User) in Active Directory and query it via LDAP? So I could outsource my user-to-role mapping into active directory.
Update:
For authentication I currently use a LDAP-Realm (user, password).
For authorization I want to use a database (rolename, user). However I don't know how to tell my application to use the database for authorization. If I would use a JDBC-Realm, I could specify the Group/Role table and column. Is there a way to tell my application to just use the JDBC-Realm for authorization?
I am using Spring-Security in my project. I have a question about it because I have 3 roles in my IS. User, manager, admin. In my system is many rooms, which every room have one manager. But manager can manage only his own room. What is the best way for this? Now I have only basic security manager can manage all rooms. But this is correct only for administrator. My question are what is best and fastest way? (Because this solution seems to be little bit huge)
use role and permissions in controller
#PreAuthorize("hasRole('ROLE_FORUM_MANAGER') and hasPermission(#forum,'update'))
and domain ACL
and Domain ACLs
http://docs.spring.io/spring-security/site/docs/3.1.x/reference/domain-acls.html
or something else?
I am asking for purpose easiest and fastest way.
This is the most usual case for using the ACLs based solution, because the permission can only be determined depending on the domain object being used.
To do this in Acls, start by creating an Acl for each room. Then each user as a security identity on type principal in the SID table. Then grant to each user access to it's room by creating an ACE (access control entry) linking the room ACL to the users SID.
Role based authentication (RBAC) should not be applicable here, as it does not allow to give fine grained permissions dependent on the relation between the user and a domain object.
Its possible to combine RBAC hasRole with Acl hasPermission(#forum,'update') but since we will already use Acls, it's better to use only Acls in order to push the permission access to the data only.
If later we change ideas about who accesses a given room there is not code impact, only security reference data impact.
I'm new to web applications and security and I have a basic question.
Imagine a single java web application with a single database but multiple accounts. Let's think about a to-do list for simplicity where people can access only their own 'items' at /item/item-id. EG:
User1 creates items 1 and 2;
User2 creates items 3 and 4;
How do I prevent User2 from accessing /item/1 for instance?
This seems to go beyond Authentication (who is this?) and Authorization (what role does he/she have?) to me.
Should I keep a persisted map of user-items and check every time before returning a response?
Are there any Spring (or other) tricks/helpers for this problem?
Authorization isn't "What role do you have?". It's "Are you allowed to do this?". The role will play a part in deciding if the subject is allowed.
What you are describing is exactly the purpose of authorization.
User2 is trying to access (think of CRUD in HTTP GET,POST,DELETE,PUT) the resource at /item/1. Are they allowed? No. So deny them access.
Should I keep a persisted map of user-items and check every time before returning a response?
How you perform authorization is up to you. Spring security definitely offers some good tools to do it from a database while separating that logic from your application logic (if need be).
I'd also like to recommend another security framework: Apache Shiro. I think it's a little easier to configure than Spring security and I find its authentication/authorization logic more straightforward .
In addition to Spring Security and Apache Shiro, you want to consider XACML-based authorization frameworks e.g. SunXACML, WSO2, Axiomatics (disclaimer: I work for Axiomatics).
XACML is the eXtensible Access Control Markup Language. It's the de-facto standard for fine-grained authorization. Much like SAML is great at identity federation / SSO, XACML helps you achieve authorization.
XACML gives you an architecture (see picture below) as well as an authorization language which you can use to express specific authorization scenarios e.g.
doctors can view medical records of patients they are assigned to
nurses can view medical records of patients that belong to the same clinic
patients can view their own records and that of patients for whom they are the guardian
You can have as many rules as you like. There is no limit.
I have an application built on Spring MVC that uses Hibernate for all of it's DB interaction needs. There is now a need to update the application to use our LDAP infrastructure to drive the user information, including basic user data, such as name and email, as well as authentication and authorization needs as well.
Since everything has been in one spot (the DB) up to now, the reports are all fairly straightforward, since Hibernate is managing retrieval of information as needed when starting with the required queries. Grabbing the users' name, etc. is very simple, since Hibernate loads the data lazily.
With the desire to drive the user information with LDAP, Hibernate will no longer be able to populate the user information on the fly, since it won't be managing the users' data. How should we use LDAP to drive the user data and deal with authentication / authorization without causing to much pain when we need to grab user data like Name, etc.?
We have considered using a hybrid approach where LDAP is treated as the "source" for the data and the current system is left as-is. This would require changes to the transaction processing code to update against LDAP so that the live transaction is using up-to-date information, and also a periodic sync against LDAP to keep the application DB up-to-date for reporting purposes.
This solution seems a bit hacky, and seems to have a lot of moving parts, but I could not find much on this subject elsewhere on the web.
How should user information be handled / how should the app be structured so that all of the user information is still easily accessible and can be easily tied to the rest of the system for reporting purposes? Is there a way to integrate Spring LDAP and Hibernate so that layers above the data layer don't have to know? Or is pulling the info from LDAP into the existing database the easiest way to go?
If you can not drop the user table at all, because it is used from other entities, then my suggestion is to separete the security stuff from the business stuff.
This mean remove the only for security needed information from the user table (login, password, ...), so that only the stuff remains that is needed to implement the buiness cases.
Then rewrite the security stuff so that is is based on the LDAP. I guess you find a way to get the user data base object for an given prinipal.
Only one thing will remain, how to create new user database entities if a new person get a new login. You have 3 choices, what is the best one strongly depends on your application:
Create the database entity if the users first login
Create the database entity if you first need it
Create the database entity when it is created in the LDAO (or some minites later) for example with an cron job, or some Spring Scheduling service.