How to write logic inside Nest js Middleware and Guard - node.js

I want to make Multiple role Access Project Where I have to allow user according to their roles , so for this I have to create multiple Middleware & Guard according to Roles but there is no documentation how to get current login user details inside Nest Middleware and also how to get current login user details from jsonWebToken inside Nest Guard & Middleware,
I have Users collection schema is Like that
UsersCollectionSchema: {
name: '',
email:'',
password:'',
roles: [ admin, editor]
}

Once the user has been authenticated, i suggest you to attach the user object to the request, it’s the common way, in order to have access to the user inside the middleware through the request and inside the guard through the request that you can get from the executionContext
Here is an example https://github.com/nestjs/nest/blob/master/sample/01-cats-app/src/common/guards/roles.guard.ts

Related

Role based authentication system fastify

I'm currently working on a fastify project, where I use fastify-jwt to create Bearer tokens to my users.
And in the routes I acces it with following:
fastify.get(
"/test",
{
preValidation: [fastify.authenticate],
},
Collection.functionX
);
So know I want some routes not accessible for "normal" users, only for "admin" users. Normally this information is within the token. I can grand access to only admins within the function, by I want to directly not give access to the route. So it directly calls "not allowed".
I found fastify Guard but it is not working.
you can use firebase authentication or any ,and put the user in a data base with a schema has property "role",then check this role in middleware,for example if role==0 its admin and so on .

What is the proper way to restrict API access based on user type?

Suppose I have two users, A and B.
A is allowed to access all the resources available, but B can access them only partially.
What is the proper way to prevent B from accessing resources to which B does not have permission?
Should I create some sort of whitelist that specifies only URLs B can access?
The following snippet is what I currently have.
It is a middleware which checks whether each request is allowed to access specific URLs.
const ALLOWED_URLS = ['api/resource1', 'api/resource2', 'api/resource3'];
const sessionCheck = (req, res, next) => {
const url = req.originalUrl;
// check whether accessing URL is allowed
}
Is there any better approach than this?
What you're asking about is called IAM (Identity & Access Management).
The roles, ownership, and permissions on specific resources is generally persisted in your database as business domain objects of their own. This is language agnostic and not specific to node or express. You should NOT build a white list of URLs. The resources you want to protect are in your database. You should map them to permission objects that in turn map to users. Your not protecting URLs, your protecting resources. Everyone is allowed to access any URL but the resources behind them are what you're protecting and those rules/permissions go in your database.
If your looking for industry standards then here are some common names/terms for those IAM objects that would be persisted in your DB:
Group
Role
User
Policy
User A's access would generally be determined by what role they have or what group they belong to. Whether you give user A a role, put them in an authorized group, or give them a direct permission doesn't really matter, these groupings exist to reduce duplication so you can pass around or take away multiple permissions at once. But the general idea is the same; your resources exist in a DB and you specify what is the required or allowed roles, groups, and users that can access those resources and you map users to groups, roles, etc as simple table entries. This means the real authorization logic is not in Node or Express or even in your webapp, its built into the resources themselves and tied to how the data is retrieved.
Resource Retrieval Code
When anyone makes a request for a given resource the query, regardless of your database type, should fail if the user is not authorized. This means the way you are retrieving data must be directly tied to how its authorized and not two separate steps; meaning you should not get the resource, then check if the user is authorized and you should not check if the user is authorized before getting the resource. The best practice is fuse/join the two so that you can not get the resource unless your authorized because we look for the resource using your role and if you don't have the right role we can't find the resource.
For example:
function getAccount(userId,accountId) {
makeSQLCall(userId,accountId)
}
SELECT *
FROM accounts a
WHERE a.accountId = accountId AND u.userId = userId
JOIN users u ON a.allowedRole = u.role
The SQL doesn't matter as the same can be done with other technologies but the last line is the most important (account.allowedRole = user.role). You literally pull the resource from the database using the users role so that if they are not authorized this fails and no data is returned. This is also your base/parent data retrieval function so other functions that don't know about authorization can use this function and authorization will be dealt with under the hood.
Express Pseudo Code
router.get('/api/resource1',function(req,res){
var user = utility.getUserFromRequest(req)
var resource = accountService.getAccount(user,req.body.accountId)
sendResponse(resource)
})
Looking at the code above the authorization is built into your domain model not your web application. If the user making the request above is not authorized they will get no data back. You have to figure out in your own business use case is it enough to return an empty result or do you need to return a 401 HTTP error code. If you need to inform your non-malicious users they are not authorized you can simply perform isAuthoriized(user,accountId) before running accountService.getAccount as a UI convenience. The strength of this approach is that if you or some other developer forgets to check isAuthorized 1st the call will still return no data since isAuthorized() is just for the users benefit and not security. The security is at the domain/db layer.
Typically you would build user resource routes and validate their ownership when you authenticate and their permissions on authorization.
E.g.
server.get('api/v0/products/:user', authMiddleware, (req, res, next) => {
// from the auth middleware comes a parsed token with payload
if (req.payload.user !== req.params.user) {
return res.status(401).send('not allowed')
}
// do action
})
An alternative would be to only access database objects that matches the payload of your authentication
The example would suggest using JWT middleware with a custom property user

Group authorization using Azure AD ADAL.JS - NodeJS, ReactJS

I've seen that when using ADAL.js, you cannot get group membership claims due to some URL limitation.
https://github.com/AzureAD/azure-activedirectory-library-for-js/issues/239
I am using oauth-bearer authentication from the frontend, that is, the frontend triggers a login via the AD login page.
The client then pass the access token to the backend.
What I want to do:
I want to filter some data in my backend endpoints depending on group membership.
e.g. if you are a member of group "London" in AD, you should only see things related to London in our DB queries.
Super simple using e.g. Okta or Auth0, not so much with Azure AD.
I also want to accomplish the same thing on the frontend, that is, show and hide menu items depending on group membership.
(All access is still checked on backend also)
The documentation is sparse and not very helpful.
"You should use Graph API".
How?, how do I talk to graph api using the token I get from the frontend?
This is the setup I have for my Node+Express endpoints:
app.use(
"/contacts",
passport.authenticate("oauth-bearer", { session: true }),
contacts
);
How, where and when should I call the graph API here?
Our system is super small so I don't mind using session state.
Can I fetch this information when the user logs in?
How should that flow be? client logs in, once logged in, call the backend and request the groups?
When you get the access token from Azure AD after the user logged in, you can find the group membership of the user by doing a GET request to https://graph.microsoft.com/v1.0/me/memberOf with the access token like this:
function getGroupsOfUser(accessToken, callback) {
request
.get('https://graph.microsoft.com/v1.0/me/memberOf')
.set('Authorization', 'Bearer ' + accessToken)
.end((err, res) => {
callback(err, res);
});
}
This sample assumes you are using the NPM package superagent.
And the required permissions to call this API are listed here.

How to achieve authorize the pages in MEAN stack web application?

I am being writing the schema for the Application in mongodb. Usually in asp.net with Sql, We have assigned the pages/UIs to each roles which means role have the permission (view/edit) to access the page or not. When the role login to the Application he can only view/Edit in assigned pages to that role, un assigned pages will not be shown for that role.
In c# i have restrict the role with write the code in pre_init event. In MEAN Stack application, the same I am trying with the mongoDB.
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var rolesSchema = new Schema({
role: { name: String },
accessPage: { pagename: String, view: true, Edit: true }
});
var roles= mongoose.model('roles', rolesSchema );
I'm new to MEAN stack, How we can achieve the authorisation related stuffs in MEAN stack web application.
I think what you want is the level of authorization based on the role of the user, you may want to look at passport js. With passport js you will be able to handle authorization, and you can use node middlewares to handle authorization based on user's role.
Try to store user's role in req.user. Read passport documentation to know more about req.user
Sample middleware:
var isAdmin = function (req,res,next){
if(req.user && req.user.role==='Admin')
next();
else{
return;
}
}
Use it in your node routes
router.post('/someRoute', isAdmin, function (req,res,next){
//Handle your route here
});
Hope this helps you get some idea on how to handle authorization based on role.
The simplest way to do it would be with Passport:
http://passportjs.org/
Passport is authentication middleware for Node.js. Extremely flexible and modular, Passport can be unobtrusively dropped in to any Express-based web application. A comprehensive set of strategies support authentication using a username and password, Facebook, Twitter, and more.
In the MEAN stack you're using Express, which supports any connect-style middleware like Passport.

Nodejs Connect Roles to db table

I have a node application written in express.js with passport for authentication and connect-roles for users. I also have a group table that I would like to connect to connect-roles. Is there any documentation on how to go about this. I want connect-roles to use my group table rows for assigning roles.
connect-roles doesn't define any storing mechanisms. it simply injects into the authenticated user you have in session object. Storing the strings equivalent to your roles you test for in connect-roles is up to you. You will normally authenticate the user first (which gives you the user object and his roles) and then do authorize (where connect-roles gets executed). Passport middleware should be used before connect-roles (as per connect-roles documentation)
In my case, I added a roles collection to my user model and took care of retrieving that from my database. You still need to implement the role test function and that's where you reference your User model roles property as you defined it.
Example:
roles.use(function (req, action) {
if (req.isAuthenticated()){
if (req.user.securityRoles.indexOf('admin') >= 0) return true; //admins can access all pages
else return req.user.securityRoles.indexOf(action) >= 0;
}
});
then you protect a route like this:
app.get('/offers', roles.is('offer.read'), offers.index);

Resources