Best practice to check user permission in RESTful API - node.js

I am developing an internal Management System for my company. Some API route will be check for the user's role, and the rest of routes will check for the user's permission.
Currently, how am I doing is storing user's permission in JWT token
{
"user": {
"name": "Oyster Lee",
"role": "root",
"image": ""
},
"OMS": 2147483647,
"WMS": 4095,
"iat": 1566536007,
"exp": 1567140807,
"iss": "Test"
}
My permission is using a bitwise operator. But it can only use up to 31 types of permission in each system. I have more than 31 so the bitwise operator will need to be replaced.
Besides that, after I assign the user new permission or role, he has to log out and log in again and again.
I am thinking should I check the database for user's permission each time they are sending a request to the route. Will it cause the application heavier? Are there any pros and cons? By the way, I am MySQL as our database.
Front-end also need to render conditionally base on user's permission or role.
I am using Nuxt.js SPA as front-end.

The system you are building is suffering from multiple problems:
first of all it will lead to role explosion / permission explosion. Right now you've thought of several roles and permissions. But there could be more in the future. Would you have to redesign your permissions?
Secondly, you cannot elegantly handle relationships (what if access is based on the fact the user and the object are in the same department / region?)
Thirdly, you're hardcoding your own logic using My permission is using a bitwise operator. But it can only use up to 31 types of permission in each system. I have more than 31 so the bitwise operator will need to be replaced. That just won't scale
Lastly, you are forced to log in / log out for changes to take effect.
What you need is decouple and externalize authorization logic from the Internal Management System API. There is a pattern called attribute-based access control (ABAC) that achieves just that. With ABAC, you have an interception-based model whereby a Policy Enforcement Point (PEP) intercepts the call to your API and checks against a Policy Decision Point (PDP) whether the caller (Alice) should be allowed to get access to whatever they are requesting (a document, a record...).
The PDP is configured with policies that use attributes to describe what can or cannot happen. For instance:
A user with role == "manager" can do action == "view" on object of type == "record" if user.department == record.department.
There are two standards to write such policies: alfa and xacml. There are several implementations of the ABAC architecture both open source (AuthZForce, AT&T...) and commercial (Axiomatics). Do check them out. I've also written a lot on this issue in other SO posts such as this one.

Related

Suggestion required on how to implement a better permission system

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.

how to handle different rank authorization in a REST api

I am designing a REST API in which there are several user types:
disabled user
standard user
support user
admin
root
for each user, there are certain properties assigned to them in a relational database.
For example files, messages, payments, ...
Let's say I want users with higher ranks to be able to handle data related to lower ranks (e.g. an admin can modify a standard user's properties)
How can I implement it in a way that I make sure the authorization functionality is separated from the process (CRUD process).
I want something like this:
api.Get("/users/:id", authorization, processHandler)
I am using the echo framework and Golang, but I don't think that really matters. I am looking for a general solution independent of language.
Maybe you have Roles and Permissions problems, that problem has a solution when you control the access level by JWT token (for example).
You have a table with enabled system permissions and your users have associated or assigned permissions, this "association" can be managed through the Roles and Permissions manager (CRUD). So when you need to associate permissions to a user, you have to create a relationship between the permissions and the user. Then, send the new "state" in the token (JWT).
So finally you have a "middleware" on your routes like this
api.Get ("/ users /: id", authorization, processHandler)
And your authorization role has the responsibility to check if your user has the permissions to use the endpoint.

How can I implement user permissions on operations in Azure API Management?

I have created a .NET Core 2.0 API and published it to Azure. I have an API Management (APIM) instance fronting that API and doing all the wonderful things that it does. However, there is one thing I cannot seem to wrap my head around or find any documentation for. Authorization on operations. (Not to be confused with authentication, which I have working very well).
My API is a simple RESTful service with CRUD actions. Let's take a read operation for example:
GET /api/owner/{ownerid}/thing/{thingid}
In this case, what I want to be able to do is to grant users permissions to READ THINGS within a specific OWNER. The same user may not have read permissions with a different owner. If the user has permissions, 200 OK; otherwise, 403 Forbidden.
Leaving this completely carte blanche, what are some suggestions for implementing this? I assume an inbound policy for each operation within APIM is where the action will take place? If so, how?
Update 1
I was informed of the possibility of using the same validate-jwt policy at the individual operation levels to append to the validate-jwt policy at the root. The idea is that the root policy validates that the user is authenticated while the operation policy checks for specific claims. This appears to work well, but is that the correct method, or just a hack?
Update 2
For the validate-jwt option to work, the permission model would need to align well with roles and groups; otherwise, it's just as much work as setting up your own custom database wherein at least you benefit from your own rules. In the end, I put the permissions in an Azure Storage Account table (any database will do) and used a send-request (with appropriate caching) to gather permissions based on the current operation and user. It works well, but "feels wrong". I am happy to share details to anyone who wants. In the meantime, I'll leave this open for now in case someone has a better idea.
Ultimately the only way to do so is by using policies at operation level. you can use validate-jwt to check for specific claims, you can check some other credentials that are passed to you as a part of request. Or you can use send-request to call some other service and ask for user permissions. In APIM itself there is no place to store any user related data besides some basic info, thus it is required for such authorization information to come from outside of APIM.
In the end it appears that there is no built-in solution. Rolling your own permission model and then validating it yourself is the way to go.
However...
This can still be done in APIM. As I mentioned in my second update, I was able to make a custom solution work. The way it was done was to use an inbound policy at the "all operations" level to retrieve permissions. (A caching mechanism was used so as not to retrieve the permissions on every single call.) Then, each operation determines if the user has permission to that specific operation based on the parameters that were passed in. (That is also cached.)
The result is that the root API has no authentication or authorization built-in, but APIM does and the appropriate behavior is observed.
Still, the preference would be an RBAC approach. For example, imagine the individual operations being seen as services as in this role definition:
{
"Name": "{rolename}",
"Id": "{roleid}",
"IsCustom": true,
"Description": "{roledescription}",
"Actions": [
"GET {myapi}/owner/{ownerid}/*",
"POST {myapi}/owner/{ownerid}/*",
],
"NotActions": [],
"DataActions": [],
"NotDataActions": [],
"AssignableScopes": [
"/subscriptions/{subscriptionid}"
]
}
If that were possible, we could create roles, assign them to users/groups at the subscription level, then have the claims automatically passed to APIM where they can be evaluated like any other claim.

Entity-level access restriction in the microservice architecture based on user or group membership

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

Security Permissions Model

I am developing a desktop application and would like to lock down certain parts for certain users - admins, guests, users, etc. What sort of design patterns are there for implementing a such a permissioning system in a desktop? I can only think of three, but I don't know what they're named (or if they are),
1) Each action performs
it's own security checking, querying
a session or a database for the
appropriate user permissions (common among simple web apps)
Each
action checks with a centralized
permissioning system saying "Does
user have x permission", which
returns some status
Before an action is even attempted, it is intercepted by a dispatcher, which performs some lookup of the action to the applicable permission and user's permissions, and prevents the action from even starting when not allowed
I think you were looking for RBAC (Role based acess control). I think there is no clear difference between the concept of access control in desktop application and access control in web application. The difference is only in the implementation. You might want to check out Spring Rich Client Platform which are integrated to Spring Security.
Outside the Spring Security, the design patterns of RBAC that I could recall are :
Each user might be directly associated to one or many roles
Each role has one or more permission
Each user might belong to one or many groups
Each group has one or more roles
Other patterns that might be of interest is ACL (access control lists) that we accustomed to in Windows based systems :
Each object has an ACL, which shows which user or which group were given access to the object
A child object inherits the parent's ACL
I have already answered similar question for difference between ACL and RBAC, you can check it here.
What is the exact difference between ACL and RBAC in general?

Resources