how to handle different rank authorization in a REST api - node.js

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.

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.

Keycloak: Role based client log-in access restriction for users

I am trying to achieve fairly simple usecase of role based client application (VueJS multi-page applications) control using the keycloak.
As shown in image, I have three different roles and three different clients in single realm.
The arrow in the image represents which role can access which client.
So my main objectives are,
User with role Viewer should only be able to log-in to the Viewer Application. If the same user tries to access the Operator Application or Admin application then keycloak should simply deny this user from doing so.
The same rules should follow for users with Admin and Operator role. Users of Admin role should be able to log-in to any of these application by keycloak.
To achieve this usecase I tried following ways,
First by appropriate role mapping to users and role creation in the clients. In this case, I create realm level roles and then client level roles, then assigned appropriate roles to the users created in the user section.
Enabling the Authorization. In the policies, I removed default policy that grant all users access to the client. And create a User policy and Client policy to restrict the access to client application
Also tried with Group based authorization policy. In this case, I created a group with client role and then assigned user to these groups. And enabled them from the Authorization group policy.
But, unfortunately none of this works. Meaning my user with Viewer role can log-in to my admin application. Which is just strange.
You can do this without extensions.
Copy the desired flow (e.g. the browser flow)
Create a new sub flow (e.g. for the browser forms) and call it Access By Role and select generic as type.
For the new sub flow ensure that CONDITIONAL is selected in the flow overview.
For the new sub flow add execution Condition - User Role, make it REQUIRED and configure it:
alias: admin-role-missing
role: admin (or whatever your role is)
negate: true
Add another execution: Deny Access and make it REQUIRED as well.
The final result should look similar to this:
This will deny access if the condition "admin-role-missing" is true.
You an also learn more from the docs: explicitly-deny-allow-access-in-conditional-flows
Also, don't forget to go to your client and select the flow in the authentication overrides.
The solution proposed by #Stuck is a great start, but it has a significant flaw: When the user has already authenticated, e.g. via the standard flow of another client that did not require the role, the password form flow will never be triggered. Consequently, the user will be logged in via the cookie flow without ever checking for the role.
In other words: If there are other clients (such as the account console) that do not require the role, anyone can bypass the role check.
To fix this there needs to be an additional flow layer that includes all authentication executions, that is followed by the authorization step (no matter what authentication flow was used). The final result will look like this:
I managed almost the same problem using KeyCloak extension SPI. After the deployment you will have additional configurable "execution" in authentication flows available, named "Validate User Role".
The auth flow then look's like :
This execution must be placed after the "Username Password Form" (or other form which authenticates user) or the authentication will fail.
The source code is here :
https://github.com/ValentinChirikov/kc_user_role_validate_extension
Finally handled this at the application level as it wasn't working from keycloak end.
After the login, check for the keycloak object, inspecting on the same we can find some of the useful properties set during the configuration mentioned in the question above. The overall code looks like below,
let appName = 'your_app';
keycloak.init({ onLoad: 'login-required' }).success(function () {
// Confirm the role & authentication of the user
if (keycloak.authenticated && keycloak.tokenParsed.resource_access &&
keycloak.tokenParsed.resource_access.hasOwnProperty(appName)) {
// Continue with the app execution...
} else {
// Logout user
keycloak.logout();
}
}).error(function () {
keycloak.logout();
});
This way I managed to route unauthorized user out of the application.
The solution isn't what's required in the question asked, but it works. Although I think this should be handled at the keycloak level itself.
For anyone looking to do this in Keycloak version 20, see the screenshot. This is based on answer by #heilerich but for version 20.
NOTE: Create a new flow instead of duplicating an existing flow as it will not work.

how to implement permissions on routes and functions in sails.js?

I'm new in sails and I have a PostgreSQL database. I want to implement a user management. I have some users, each user can be assigned to multiple groups, each group can be assigned to multiple roles and each role can have some permissions! I checked document of sails permissions but I didn't get it well. for example, I want some groups not to be able to add or edit users or I want some roles not to be able to see user management menu. what should I do?
I may be a little late to post answer here, But there is a way available for access control in sails.
Sails has built-in policy based access control system.
Policy
Policies in Sails are designed for controlling binary ("yes or no") access to particular actions. They work great for checking whether a user is logged in or for other simple "yes or no" checks, like whether the logged in user is a "super admin".
But for Dynamic permissions,
Helpers
Link for documentation of helper, access-control-and-permissions
For more complex permission schemes, like those in which a requesting user agent's access rights depend on both who they are and what they're trying to do, you'll want to involve the database. While you can use policies to accomplish this, it's usually more straightforward and maintainable to use a helper.
One can find example here,
Using helper for access control and permission
So you can use postgreSQL for storing roles and their respective permissions and retrive user role and check permission on need in policy/helper.
Sails.js has no ACL managment
You have to use 3rd party middleware like roles or role-acl
Sounds like what's most important is the association of the user to the permission (or role). So you could consider making models for each tier (user, role, group) or you can make a model for each kind of group and/or role (though that sounds like it could get out of hand) and then have the models associated with eachother. Then in the view action you can set what the permissions are (aka what groups or roles are allowed to see that page). Also in the markup you can set who is allowed to even see a button.
For example:
isSales could be a boolean on your group or roles model for a user that is in sales and they are allowed to see the edit button to change the price of something. So in your markup you have:
<div v-if="user.isSales">
<button> Edit price </button>
</div>

What's a good way to have ordinary-user segregation but admin-user access to the same pages?

I'm using ASP.NET MVC 5 and ASP.NET Identity. I have a site with multiple users, who should only see their own data. The ordinary users access the site via URLs such as "/orders", "/orders/edit/1" etc.
I also have some "admin" users, who should be able to access all the same stuff that ordinary users see, except that they can view the data for all users. What I want to do is allow them to "impersonate" a user, and see what that user sees. So, they might access the site via URLs such as "/user-foo/orders", "/user-foo/orders/edit/1", etc.
Currently, my controllers have two variants of each action: one with a user id parameter (for admin users) and one without (for ordinary users). In the latter case, the id of the logged-in user is used. Both of these then call some shared code to render the view.
However, when rendering the view, I need to ensure that any embedded links (e.g. to an order detail page) use the correct routing form (with/without user id). That means I need to constantly check whether the user is an admin, etc. Is there a better way to do this?
I would use the claims that are available in ASP.NET Identity. Just add a claim for the impersonated user ID that will only be used if the user is an administrator. The roles are probably already in the claims. You do not need the action that passes the ID, instead add some logic that looks at the claims to see if the person is an administrator. If they are an administrator and there is a claim containing the impersonated ID then use it instead of the logged in users ID.
Here is an article that shows how to use claims with ASP.NET Identity. This shows how to set the claims during the log-in process. If you need to add a claim after the log-in process just use the SignIn method again, like this.
var AuthenticationManager = System.Web.HttpContext.Current.GetOwinContext().Authentication;
var prinicpal = (ClaimsPrincipal)Thread.CurrentPrincipal;
prinicipal.AddClaim(new Claim(MyClaimTypes.ImpersonatedUserId, impersonatedUserId));
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = persistCookie }, principal);
I normally provide the same structure for both, but with an Authorize attribute with a role specified if i am blocking access by a certain role type. Alternatively you can check the controllers User property to find out the logged on user and perform your own logic to determine what data that user has access to view.

Securing a Symfony2 application

i'm developing a Symfony2 app which involves users with hierarchical roles. Right now i can register, recover and login into the application without issues as i've implemented roles and users as described in Symfony2 docs.
At that point, i've developed some CRUD's in order to be able to manage objects in the application but in the current implementation i must check current user roles in order to let him or not run "selected" actions. I mean, in each controller i get security context, then user object and check permissions then sometimes i need to check the current user is the owner of the data - i.e if an user has clients i need to check url passed variables/id/whatever are owned/belongs the current user - and then deny access or not.
So, as far i'm used to and feeling comfortable developing the application as mentioned above i'm wondering is there is a better approach or a Symfony2 approach where i can manage roles and data in standard or more understanding way so future developers doesn't need to go through each if or check inside controllers+actions. I also would like to note i would be able to customize how data or objects are fetched or loaded so i can optimize sql's run in background.
Symfony ACLs is exactly what you need. You can assign access rights (i.e. OWNER, EDIT, VIEW etc) to a single user or assign to all users with a certain role (or both).
If ACL is too complex for your needs, than an alternative approach would be to use a custom Security Voter.

Resources