I'm trying to solve security in my multi-tenant SaaS application with shared database (ie. every entity has a corresponding tenant_id field in database).
There are multiple levels of security that I'm trying to solve:
Authentication - solved by using JWT
Authorization - solved by using API gateway and RBAC policy repository
Relationship security - N/A
By Relationship validation I'm referring to a question - Can you assign A to B? if source of truth for A and B are in different services.
I know that the request is authenticated and I know that I can assign typeOf(A) to typeOf(B) but how do I know that I can assign an instanceOf(A) to an instanceOf(B)?
To give an example of GitHub - we have repositories, projects and issues, all in separate services.
I am authenticated so I have access to the repository.
I am authorized to assign an issue to a project due to my role.
In a single database I would check, by a way of SQL, if an issue belongs to the same repository as project. When issues and projects are separate they have no information to validate assignTaskToProject request. They know individually that they are part of a repository, but not what projects belong to what issues and vice versa.
Where and how assignTaskToProject request can be validated?
Related
I have a user permission system in place where i have a set of permissions within the database, for example
id
Permission
1
POST:CreateBooking
2
GET:AllBookings
And i have another table (junction table) where i put dependent permissions such as
if i want to create a Booking, i need to fetch Package details and so POST:CreateBooking requires the user to also have GET:AllPackages permission.
There's a template system in place as well, where the users can group multiple permissions together and once that template is assigned to any employee, that employee will get THAT set of permissions and it's dependent permissions.
What my nodejs system does is that when user logs in, it fetches all permissions from DB and puts it in a redis set from where on each request, the permission is checked against user id.
Is there any tool from where i can do exactly this but in an intuitive and better way?
I tried keycloak but i don't know how to cover my needs mentioned above.
Thank you
if I'm understanding correctly and trying to generify your scenario, you have a classical situation where:
You have groups which can have multiple permissions assigned;
groups can be created dinamically;
each permission correspond to a specific functionality.
So, implementing the OIDC (Open Id Connect) protocol might fit you needs. As you suggested youself you might be interested in a OpenID provider (do not reinvent the wheel) keycloak is good, you can give a look also to Vault Hashicorp.
So assuming that your backend have an already existing framework to handle security and permissions (eg. Spring Security) you can produce JWT token with the OpenId provider and check throught PreAuthorize claims (permissions) inside the token.
At the end your security layer it's just an annotation you need to insert before your method controller or before you class controller.
Behind the scenes, instead, this is what will happen:
Your user connect to your app;
User insert username and password -> the Open Id provider gives you a JWT
Your Front End app everytime it make a REST req will send also the JWT
The back end controller method called it's under authorization
Given the public keys of the OpenId provider, the validity of the token it's enstablished
If the specific permission claim it's found inside the token, the request can be elaborated else a 403 Forbidden it's returned.
OIDC - as the conceptual model/backdrop to any tool of choice, is certainly a popular/good choice, but as long as you're willing to deal with an element of complexity - the understanding required to implement an OIDC arrangement (- think of it as a possible investment - effort up front with hopefully the rewards tricking-in over time); e.g. OIDC is an ideal choice for supporting SSO (Single Sign On), especially when it comes to supporting/allowing for authentication/login via providers such as Facebook, LinkedIn & Google, etc (- as well as more Corporate OPs (OIDC Providers) including AAD/Azure AD).
Try to first step-back, and consider the possible bigger/future picture, before selecting a tool based upon only your starting/current requirements.
In the systems, there may be data that is restricted in nature.
Sometimes access to specific entities should be easily restricted or granted based on user or group membership.
What is the best way to implement this in the microservice architecture?
#1
Should access control, managing permissions etc. be the responsibility of the microserive itself? Developers will have to implement access control, store, and update permissions for every service. Seems like not very robust and error-prone approach.
#2
Create dedicated microservice handling permission management? This service will be called by other microserives to check access permissions for each entity and filtering entities before returning results. Centralized permissions storage and management is an advantage but microservice will have to make a call to "Permission Service" for each entity to check access rights what may have a negative influence on performance. And developers still have to integrate access checks into their services what leaves space for an error.
#3
Make access control responsibility of the API Gateway or Service Mesh. It is possible to think of an implementation that will automatically filter responses of all services. But in the case when the microservice returns list of entities permissions should be checked for each entity. Still a potential performance problem.
Example
Consider the following synthetic example.
Healthcare system dealing with test results, X-Ray images etc. Health information is very sensitive and should not be disclosed.
Test results should be available only to:
patient
doctor
laboratory
Attending doctor may send the patient to another specialist. A new doctor should have access to test results too. So access can be granted dynamically.
So each entity (e.g. test results, X-Ray image) has a set of rules what users and groups are allowed to access it.
Imagine there is a microservice called "Test Results Service" dealing with test results. Should it be responsible for access control, manage permissions etc.? Or permissions management should be extracted to separate microservice?
Healthcare system may also handle visits to a doctor. Information about patient's visit to the doctor should be available to:
patient
doctor
clinic receptionist
This is the example of a different entity type that requires entity level access restriction based on user or group membership.
It is easy to imagine even more examples when entity level access control is required.
I came to the following generic solution.
ACL security model is used. Each object in the system has associated set of permissions. Permissions defines who and what actions can perform on the object.
Microservices are responsible for entity-level authorization and filter objects in responses based on permissions of the objects.
Central Access Control Service is responsible for the creation, update, and deletion of permissions for all objects in the system. Access Control Service database is the primary store of objects' permissions.
Permissions stored in microservices databases are synchronized with Access Control Service database using event-carried state transfer. Every time, permissions are changed an event is sent to the message broker. Microservices can subscribe to these events to synchronize permissions.
API Gateway can be used as the additional protection layer. API Gateway can call Access Control Service directly (RPC) to check response objects' permissions or load recently revoked permissions.
Design features:
A way to uniquely identify each object in the system is required (e.g. UUID).
Permissions synchronization in microservices are eventual consistent. In case of partitioning between message broker and microservice permissions will not be synchronized. It may be a problem with revocation of the permissions. The solution to this problem is a separate topic.
Looks like security is a part of business logic here. In both examples.
Then security could be a part of data scheme.
For example,
Patient can see his tests:
select * from test_result where patient_id=*patient_id*
Doctor can see all test from his medical department:
select * from test_result where branch_id=*doctor_branch*
I believe that to have separate MS for access control is a really bad idea and could lead serious performance problems. Just imagine situation that somebody with zero entity access tries to fetch all entities each time :) You will always need to handle larger result sets than actually needed.
Firstly, this is very bad idea to have a separate (per microservice) security model. It should be single always cross-cutting all application, because it can lead to a hell with access management, permissions granting and mapping between entities in different microservices.
In second, I assume that you are wrong with understanding how to organize microservices..? You should dedicate the principle of splitting functionality into microservices: by features, by domain, etc. Look at Single Responsibility, DDD and other approaches which helps you to achieve clear behavior of your MS.
So, in best case, you should have to:
Choose right security model ABAC or RBAC - there are a lot of other options, but looking at your example I guess the ABAC is the best one
Create separate MS for access management - the main responsibility of this MS is a CRUD and assignment of groups/roles/permissions/attributes to the people accounts.
Create separate MS for providing only permitted health information.
In third, how it works?:
With ABAC you can setup hierarchical roles/permissions (based on groups/attributes) - it helps you to resolve a delegation path of who is permitted to the data
Setup authorization (via auth-MS) and store the list of permissions (in session, cookies, etc)
Check access for a given user for a needed data in health-info-MS. Here we have several options how to do this:
If you use memory-grids (hazelcast, coherence), you can easily create filters with predicates based on security attributes.
If you're using SQL (hibernate, plain SQL, etc.) you should generate queries to return only permitted data - add security specific criteria to the where clause
Few more details about SQL queries with security check in where: before the SQL execution (if hibernate & spring is easy to do with spring-method-auth hook) you should resolve all permissions assigned to a user - you can do this with call to auth-MS.
Example
We created CRUD permissions for TestResult entity - VIEW, EDIT, DELETE.
The role DOCTOR can see any TestResults - so, it has VIEW permission
The role PATIENT can see only his/her TestResults
So, you create a business rules which provide the correct where clause for each business role (DOCTOR, PATIENT, LAB, etc.) and at the end the SQL request would be like:
For patient who has assigned VIEW permission:
select * from test_result where id=*patient_id* and 1=1
For patient who hasn't assigned VIEW permission:
select * from test_result where id=*patient_id* and 1!=1
NOTE: In business rules we can add 1=1 or 1!=1 to permit/restrict query result
currently I develop a backend based on the microservice architecture.
Unfortunately, I have a problem how to realize the authorization.
So let me explaine my system - there are the following services:
OAuth 2.0 Service (issuing JWT)
Group Service
Some Ressource Services (e.g. ToDos Service)
Every user is in one or many groups.
Each resource (like a ToDo list) also belongs to a group.
That means if some user creates a todo list, that list gets stored in the name of the group.
Szenario:
User A is in group A
User B is in group A and B
User C is in group C
User A creats a ToDo list in group A.
User B modifies this ToDo list (he is allowed to do this since he is also in group A)
User C also tries to modify this ToDo list, but he shouldn't allowed to do this since he is only in group C.
Has any body a great idea how I could realize this in a microservice architecture and keep the dependencies between the services on a minimum?
Certainly, I could ask on every request the Group Service if the user is in the group to which the resource belongs to. But so I get a really hard dependency between the Resource Services and the existence of a Group Service - I like to avoid this dependency.
Another option would be to store all groups, to which the user belongs to, in the access token. But with this option the client has to ask every time the OAuth Service for a new token when the user gets a member of a new group.
So is there any other option how I could realize this szenario?
So, you have three domains:
Authentication: responsible for identifying the user
Authorization: responsible for restricting access to resources
Todos: your core domain
You have done well identifying three bounded contexts, one for each domain and implemented in three microservices (MS). You are conforming to the best practices regarding DDD.
No, your question is how could you integrate those three microservices in such a way that the system is resilient, i.e. its microservices continue to work even if some of the other microservices fail.
You have two options regarding integration (communication between microservices):
Synchronous communication: every time the Todos MS receive a request, it queries the Authorization MS to check if the user is permitted to do what it wants. This has the advantage that is simple to implement but it has the disadvantage that is susceptible to cascade failure: if the Authorization MS fails then this MS also fails. So, this option is not good for you.
Asynchronous communication: somehow in the background, there is some data that is replicated from the Authorization MS to the Todos MS. You have at least two options for this replication to be done: a) in cron or scheduled tasks or similar and b) using a event driven architecture. This has the advantage that provides more resilience but it has the disadvantage that is more complex, harder to implement. This option seems to fit your need.
Further reading:
Building microservices
I would suggest to put the authorisation handling into a API gateway. When there is an incoming request the following steps are executed
1.The API gateway hits the OAuth server to get a transparent token which contains the access roles and groups of the user
2.The API gateway then calls the to do services with the access token , which the to do services use to decide if a particular user is authorised.
The advantage of this integration pattern is that the individual services don’t have to call the group service to get the roles.
What Cross-Domain Single Sign-On implementation best solves my problem?
I have two domains (xy.com & yz.com) which already have their own database of users and are already implementing their user authentications separately. Recently there has been the need to implement CDSSO so that users dont have to log in each time they try to access resources from both domains.
Ideally the CDSSO implementation I hope to use should allow custom implementation of authentication, as I hope to call API's provided by both domains during authentication to confirm a user exists in at least one of the domains user database.
I've been looking at Sun's OpenSSO which seems to provide a means to extend its AMLoginModule class yet this seems to be a long thing and more annoyingly they seem to stick to GlassFish.
I've also considered developing a custom CDSSO to solve our needs. Is this advisable?
Is this achievable using Suns OpenSSO considering the disparate user database as I there will be no need to make use of the User db that OpenSSO requires?
Are there any simpler means of achieving what I intend to achieve?
In addition both applications which exist on the two domains were developed using PHP. How does this have an effect considering Suns OpenSSO is based on Java EE?
Are there any clearly specified steps on implementing OpenSSO and or any other SSO implementations from start to finish?
I suggest you to use simpleSAMLphp in order to deploy an Identity Provider and 2 Service Provider (for each app).
SimpleSAMLphp allows you to select multiple authentication source and is not hard to build your own authsource that consults the 2 databases.
My experience in SAML says that the fact of not consolidating the Identity of the user in 1 unique authsource is a bad idea due several reasons:
* identity conflicts: what happen if you have the same user registered with different mail (if that is the field yoy use to identify the user) and you try to access? You could be logged in different account each time.
* what happen if you add a 3rd service, do you gonna add a 3rd database
* what happen if user change its data in one app, the other gonna be no synched?
* what happen if user uses different passwords?
I recommend you to execute a migration process before adding the SAML support and build a unique database for all your identities and unify the registration/edit profile/password recovery process of both sites in one.
SimpleSAMLphp has good documentation, but I can provide to you any documentation related to the process that I suggested.
I am developing a web application consisting of different domains. I have tried to implement hierarchical RBAC for authorization. Each domain has some predefined operations in their bo implementations. The following is my bo package hierarchy.
com.mycompany.bo
...domain1
...domain2
.
...domainN
...rbac
I predefine the following role hierachy at first deployment, i don't want to maintain the rbac operations after the first deployment, i mean the domain rbac operations should be self maintainable by the domain admins.
Root
Domain1Admin Domain2Admin .. DomainNAdmin
The root role can authorize on all operations under bo implementations and also each domain admin can authorize on its all own operations and some rbac operations like create user, edit user, create role etc also.
Finally, I have developed the ui part of the project abiding by the facelet facilities, like include tag so that i can distinguish the ui fragments of a page. As a result, I can render a ui fragment with respect to whether the the user authorized to view the fragment or not. Any suggestion for the authorization design of the system will greatly be helpful.
Now, I came to authentication part of the project. In this system a user does not only authenticate over internally but also should authenticate over an external system via a web service or ldap, since the user may have been already created in there.
Spring framework provides some facilities authentication via ldap(statically configurable in xml). In my case, I want to add remove edit new LDAP definitions in runtime and can change a user authentication method(may be selecting the new LDAP from a combobox). How can I dynamically add new LDAP definitions in Spring, shall I continue with spring security or implement this feature own my own?