How to achieve authorize the pages in MEAN stack web application? - node.js

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.

Related

Correct security implementation strategy for multi-provider authentication and api route protection with Nodejs

We have a small React Web application with a Fastify backend (but can very easily apply the same concepts to Express js) that feeds the db data to the frontend clients.
Some of the API routes are protected by means of middleware checking the validity of the access token.
Our auth strategy used to be only credentials based, ie using Username and Password.
We have recently implemented authentication by Google and Facebook as well and for the most part, they seem to work well.
We now want to replicate our web application to a mobile application.
I have never written a mobile app and am currently busy learning React-Native.
I managed to implement Google Auth on the IOS app.
Here is the problem. I am not sure how to implement token validation for mobile clients on protected routes using the Google access token. I am however able to successfully implement validation if I use the id token.
My understanding is that validation on protected routes should be done using the access token, otherwise, what is the point of the access token in the first place.
Anyway, my understanding of the entire authentication flow is clearly flawed.
I just need some advice, samples or references to articles that I can read that can clarify the concepts to me.
Just the summary of what I hope to achieve:
a single backend with various (but not all) protected routes
the backend to support credential-based, Google and Facebook authentication strategies
backend middleware to check the validity of the access token
backend should serve both native mobile and web applications.
Sample of a protected route:
fastify.get(
"/protectedroute",
{ preValidation: [fastify.googleverify] }, //<--- Middleware only checking Google validity currently. TODO: Multi-provider middleware to be created
async (request, reply) => {
reply.code(200).send({ message: "authenticated", user: request.user });
}
);
Sample of middleware to check google id_token validity:
fastify.decorate("googleverify", async function (request, reply, done) {
if (!request.raw.headers.authorization) {
return done(new Error("Missing token header"));
}
const bearer = request.raw.headers.authorization;
const token = bearer.split(" ");
try {
const userinfo = await verify(token[1]);
request.user = userinfo;
return done();
} catch (error) {
reply.code(401).send({ message: "Not Authorized", error: error });
}
});

Single user is being logged in across all devices

I was building a project on node.js recently, I came across this bug of user authentication. The problem is that after I log in from one account, if at the same time I refresh the home page of the website from another device, it redirects to the dashboard of the first user account. In other words, a single user is getting logged in on all the devices over the network. If suppose I don't refresh the page, and I log in normally on the application, it works fine. This problem is happening, both on the localhost as well as after hosting it on Heroku. Technologies used- node.js for handling back-end views and URLs. HTML, CSS, JavaScript for the front-end. Firebase for the database and authentication. Here is the code for the login part-
const express = require("express");
const path = require("path");
//Create Router Object.
const router = express.Router();
//Main Login Page (GET)
router.get("/", (request, response) => {
response.sendFile(path.resolve("./views/html/login.html"));
});
//Main Login Page (POST)
router.post("/", (request, response) => {
let email = request.body.email;
let password = request.body.password;
firebase.auth().setPersistence(firebase.auth.Auth.Persistence.NONE);
firebase.auth().signInWithEmailAndPassword(email, password)
.then(r => {
let user = firebase.auth().currentUser;
if (user.emailVerified)
response.redirect('/dashboard');
else
response.send("<h1>Please Verify your email address.</h1>");
})
.catch(error => {
console.log(error);
response.send("<h1>Invalid Credentials</h1>");
});
});
Please can someone help me by resolve this bug in my project?
Calling firebase.auth().signInWithEmailAndPassword(email, password) signs the user in on the location wherever you call this code. Since you run this in an express.js app in Node.js, the user is signed in to that Node.js process, until you sign them out again. This is why the Firebase Authentication SDK you are using is only meant to be used in client-side applications, where this behavior is working as intended.
When integrating Firebase Authentication in a server-side process, you should use the Firebase Admin SDK. This Admin SDK has no concept of a currently logged in user, and no signInWithEmailAndPassword. Instead, if you need to know the identity of the user accessing the server-side code, you'll:
Sign the user in in their client-side app with the Firebase Authentication SDK.
Get the ID token for that user on the client, and pass that with your call to the server.
On the server, verify that ID token, to ensure the user is who they claim they are.
Then use the information on the user's identity to determine if they're authorized to access the information.
For more on this, see the Firebase documentation on verifying ID tokens.

express-session vs passport.js?

I am currently implementing email-password login functionality for a website using just express-session. Everywhere I look I see people using passport.js to authenticate requests. The below code is working for me.
app.post("/signup", function(req, res) {
var user = new userModel(req.body);
user.save();
req.session.userid = user.id; // I use this id to authenticate
}
Do I have any reason to use passport?
In NodeJS, you can authenticate in 2 ways:
Session-Based authentication
Token-Based authentication
Passport is a token-based authentication system. It uses JSON web token i.e jwt.
In your case, as you are using session-based authentication you need not use passport

Securing HTTP endpoint using service api

Below is the code, where I am trying to authenticate using third party providers. My authentication call is a service api which is running in different servers. How can authenticate users in my code
//app.js
app.use(passport.initialize());
// Create our Express router
var router = express.Router();
router.route('/test')
.get(**<first authenticate user using service api http://localhost:1000/authenticate>**, serviceController.getData);
app.listen(2000);
//authController.js
var app = express();
var router = express.Router();
router.post("/authenticate",function(req,res){
//Using third party providers like LDAP or Facebook using Passport
res.send("User authenticated");//Token will be send
});
app.listen(1000);
//authController.js - as function call it is working
var passport = require('passport');
var BasicStrategy = require('passport-http').BasicStrategy;
passport.use(new BasicStrategy(
function (username, password, callback) {
// Success
//return callback(null, true);
}
));
exports.isAuthenticated = passport.authenticate('basic', { session: false });
Is it possible to secure my api http://localhost:2000/test using LDAP or Facebook authentication. I am looking for something similar to SSO.
Expected result
When I hit http://localhost:2000/test, a request must be made to LDAP or facebook server running in http://localhost:1000/ to validate user and send the response from "User authenticated".
Any help on this will be really helpful.
there are couple of possibilities to achieve that using node.js
Passport Facebook; https://github.com/jaredhanson/passport-facebook
LDAP for node.js; http://ldapjs.org/
Passport provides plenty of different possibilities to login: twitter, google, facebook, linkedin, instagram. They are pretty easy to implement as well.
Check it here: http://passportjs.org/docs

NodeJS OAuth2.0 principles

Recently I was working on a nodeJS project and I was thinking how to go about and implement the security module of my mobile application. I had a previous experience from OAuth 2.0 protocol which I used in C# projects in the past.
In .NET there are two nice open source project
https://github.com/thinktecture/Thinktecture.IdentityServer.v3
https://github.com/thinktecture/Thinktecture.AuthorizationServer
The former is an Identity Provider supporting federated authentication and the later is an OAuth 2.0 provider.
So I decided to employ the same security infrastructure for my nodeJS app. But as far as I know, there is nothing equivalent to those projects.
I found some really nice project, which are not yet complete but are a good start:
https://www.npmjs.org/package/node-oauth2-server
https://github.com/domenic/restify-oauth2
In addition, I came across a nice article that suggests a nice way to deal with authentication in nodeJS. https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/ and a similar answer to a questtion on stackoverflow. Auth between a website and self-owned API
From what I understood, expressJwt guards our api's and basically will validate the access token sent by the user. But I'd like to go a step further, and associate a token with app specific scopes, in a similar way that one would do with the OAuth2.0 protocol. So for example, I would like to assign a write, read etc. scopes and have expressJwt check if the user's token has the required scopes to access as specific API endpoint.
I would be grateful if you could provide me with some suggestions about how to deal with this topic.
First, you need to generate a token with such claims. This could be in an API or some other place:
var jwt = require('jsonwebtoken');
var claims = {
name: user.name
can_write: true,
can_post_timeline: false
};
var token = jwt.sign(claims, 'my-super-secret');
Then, to validate you will do something like this:
var jwt = require('express-jwt');
app.use(jwt({secret: 'my-super-secret'}));
function require_time_line_access (req, res, next) {
if (!req.user.can_post_timeline) return res.send(401);
next();
}
app.post('/timeline',
require_time_line_access,
function(req, res) {
//do timeline stuff
});
express-jwt validates the signature of the token, expiration and few other things. If everything is okay it puts the decoded token in req.user, and if is not okay it returns 401.
require_time_line_access is a middleware that ensure the user has this claim, if it doesnt it returns 401. You can put this middleware in every endpoint that needs this claim.

Resources