Securing a specific route node.js - javascript

Hey I'm using basic auth for Node.JS to secure a route. I'm pretty new to Node.JS and don't understand what the next function does in this case. What I'm trying to do is to secure a the route: /admin/
Note: This is a project for learning purposes so the login part is not too serious and won't be used live.
authentication.js
var basicAuth = require('basic-auth');
exports.BasicAuthentication = function(request, response, next) {
function unauthorized(response) {
response.set('WWW-Authenticate', 'Basic realm=Authorization Required');
return response.send(401);
};
var user = basicAuth(request);
if (!user || !user.name || !user.pass) {
return unauthorized(response);
};
if (user.name === 'name' && user.pass === 'pass') {
return next();
} else {
return unauthorized(response);
};
};
and app.js where I imported the module authentication:
app.get('/admin/', authentication.BasicAuthentication, function(req, res){
console.log("hi u need to login");
});
So what I want to do is to route the user further if the authentication goes through.
Thanks in advance!

Try:
app.get('/admin/', authentication.BasicAuthentication);
app.get('/admin/', function(req, res) {});

This function is known as a middleware:
var basicAuth = require('basic-auth');
exports.BasicAuthentication = function(request, response, next) {
function unauthorized(response) {
response.set('WWW-Authenticate', 'Basic realm=Authorization Required');
return response.send(401);
};
var user = basicAuth(request);
if (!user || !user.name || !user.pass) {
return unauthorized(response);
};
if (user.name === 'name' && user.pass === 'pass') {
return next();
} else {
return unauthorized(response);
};
};
middleware is a function that you can define for various purposes:
using middleware
writing a middleware
In a simple way is a function that runs before performing another action, one general purpose is to protect certain routes for unauthorized access.
You can protect private routes calling then authentication.BasicAuthentication before function(req, res) {}
Some example:
app.get('/user-profile/', authentication.BasicAuthentication, function(req, res){
//private info
});
app.get('/foo/', function(req, res){
//public info
});

Related

Redirect if session is not available node.js

I am trying to write code for my route that if the session.user_id is undefined redirect back to the home page. For some reason the redirect doesnt execute and the mysql condition is fired and it crashes the server because the session.user_id is undefined and it cant load the game without that data.
Is there a way to use a universal redirect on all routes that if session is not available redirect back to login?
router.get('/game', function(req,res) {
console.log(req.session.user_id);
if (req.session.user_id === "undefined") {
res.redirect('/');
}else {
var condition = 'userId = ' + req.session.user_id;
projectX.allGameData(condition, function(data){
var hbsObject = {heroes : data, logged_in: req.session.logged_in, isUser: req.session.isUser, isAdmin: req.session.isAdmin}
res.render('game', hbsObject);
});
};
});
You should either use:
if (req.session.user_id === undefined)
OR
if ( typeof req.session.user_id === "undefined")
Apart from that, it's usually better to have a middleware function that checks for user session. This way, you can just insert the call to this middleware in all your routes, which require the user to be logged in:
router.get('/game', checkUserSession, function(req,res) {
// Your code here
});
function checkUserSession( req, res, next )
{
if( req.session.user_id )
{
next();
}
else
{
res.redirect('/homepage');
}
}//checkUserSession()
I assume the value is undefined, and not "undefined" (which is a string containing the word "undefined"):
if (req.session.user_id === undefined) {
...
}
//Inject authHandler as middleware
router.get('/my/route/', authHandler, (req, res) => {
//secure point, the authHandle went thru
});
function authHandler(req, res, next) {
if (req.session.user_id) {
next();
}
res.redirect('/login/');
}
Add a function to handle the Auth check and then inject is a middleware to your router.

Setting admin role using connect-roles & Passport.JS

I am currently trying to set up an admin role in order to access a simple admin page using the following documentation provided via : connect-roles
I ave been banging my head against it for a while and am still lost on how to set a role E.G As of right now am pulling a admin value out of the DB and storing it in a global var for the time being but I have no idea how to use that with connect-roles say to only allow access to my admin page for a specific user.
Can anyone clarify or show an example on how to do this/some guidance as I documentation didn't help me to ensure access to a web page only if the user is an admin?
Ave posted some of the code kinda showing what it looks like at the moment.
Code
var admin = 'Admin';
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
database : 'test'
});
var passport = require('passport');
var ConnectRoles = require('connect-roles');
var roles = new ConnectRoles();
var passportLocal = require('passport-local');
app.use(passport.initialize());
app.use(passport.session());
app.use(roles.middleware());
passport.use(new passportLocal.Strategy(function (username, password, done) {
connection.query({
sql : 'SELECT * from `userman_users` WHERE `username`= ?AND`password` = sha1(?)',
timeout : 40000, // 40s
values : [username, password]
}, function (error, results, rows) {
if (results.length > 0) {
response = "Success";
} else {
console.log('Error while performing Query.');
response = "Failed";
}
if (response === "Success") {
done(null, {
id : username
});
} else if (response === "Failed") {
done(null, null);
}
});
})
);
passport.serializeUser(function (user, done) {
done(null, user.id);
});
passport.deserializeUser(function (id, done) {
done(null, {
id : id
});
});
roles.use(function (req, action) {
if (!req.isAuthenticated()) return action === 'access home page';
})
roles.use(function (req) {
if (req.user.role === 'admin') {
return true;
}
});
app.get('/', redirectToIndexIfLoggedIn, function (req, res) {
res.render('login');
});
app.get('/index', checkLoggedIn, function (req, res) {
res.render('index', {
isAuthenticated : req.isAuthenticated(),
user : req.user
});
});
app.get('/admin', user.can('access admin page'), function (req, res) {
res.render('admin');
});
function checkLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/');
}
this is an example:
var express = require('express');
...
var passport = require('passport');
var LocalStrategy = require('passport-local');
var ConnectRoles = require('connect-roles');
...
var app = express();
//===============PASSPORT=================
// Passport session setup.
passport.serializeUser(function(user, done) {
console.log("serializing " + user.username);
done(null, user);
});
passport.deserializeUser(function(obj, done) {
console.log("deserializing " + obj);
// simulate an admin user
obj.role = obj.username == 'admin' ? 'admin' : 'user';
done(null, obj);
});
...
//===============CONNECTION RULES=================
var user = new ConnectRoles({
failureHandler: function (req, res, action) {
// optional function to customise code that runs when
// user fails authorisation
var accept = req.headers.accept || '';
res.status(403);
if (~accept.indexOf('html')) {
res.render('access-denied', {action: action});
} else {
res.send('Access Denied - You don\'t have permission to: ' + action);
}
}
});
...
app.use(passport.initialize());
app.use(passport.session());
app.use(user.middleware());
//anonymous users can only access the home page
//returning false stops any more rules from being
//considered
user.use(function (req, action) {
if (!req.isAuthenticated()) return action === 'access home page';
});
//users logged can access to public pages
user.use(function(req, action){
if(req.isAuthenticated() && action != 'access private page' && action != 'access admin page')
return true;
});
//moderator users can access private page, but
//they might not be the only ones so we don't return
//false if the user isn't a moderator
user.use('access private page', function (req) {
console.log('access private page');
if (req.user.role === 'moderator') {
return true;
}
});
//admin users can access all pages
user.use(function (req) {
if (req.user.role === 'admin') {
return true;
}
});
...
/* GET home page. */
app.get('/', user.can('access home page'), function(req, res, next) {
res.render('index', { title: 'Express' });
});
//displays our signup page
app.get('/signin', function(req, res){
res.render('signin');
});
//sends the request through our local signup strategy, and if successful takes user to homepage, otherwise returns then to signin page
app.post('/local-reg', passport.authenticate('local-signup', {
successRedirect: '/',
failureRedirect: '/signin'
})
);
//sends the request through our local login/signin strategy, and if successful takes user to homepage, otherwise returns then to signin page
app.post('/login', passport.authenticate('local-signin', {
successRedirect: '/',
failureRedirect: '/signin'
})
);
// Simple route middleware to ensure user is authenticated.
app.use(function(req, res, next) {
if (req.isAuthenticated()) { return next(); }
req.session.error = 'Please sign in!';
res.redirect('/signin');
});
//logs user out of site, deleting them from the session, and returns to homepage
app.get('/logout', function(req, res){
var name = req.user.username;
console.log("LOGGIN OUT " + req.user.username)
req.logout();
res.redirect('/');
req.session.notice = "You have successfully been logged out " + name + "!";
});
app.get('/private', user.can('access private page'), function (req, res) {
res.render('private');
});
app.get('/admin', user.can('access admin page'), function (req, res) {
res.render('admin');
});
app.use('/users', users);
....
module.exports = app;
With connect-rules you define the rules do you want to use (user.use in this case). If you pass an action as first parameter the strategy is only used if the action passed in the function is equal to it. Then you trigger the rules in the routes with user.can passing the action. In this example I define an extra filter strategy to grant access to users that are logged and request routes that are not marked with admin or moderator privileges e.g
/* GET home page. */
app.get('/', user.can('access home page'), function(req, res, next) {
res.render('index', { title: 'Express' });
});
After the user is logged, we need to have another strategy in case the user isn't admin or moderator.
U can use framework like sailsJS and npm module sails-generate-auth
And after setup, use your own middleware to block routes
//allow admin only localhost:PORT/admin at policies.js
'admin': ['passport', 'sessionAuth', 'isAdmin'],
'*': ['passport', 'sessionAuth'],
//isAdmin policy
module.exports = function(req, res, next) {
// User is allowed, proceed to the next policy,
// or if this is the last policy, the controller
if (req.user.role == 'admin') {
return next();
}
// User is not allowed
return res.forbidden('You are not permitted to perform this action.');
};
Using the following logic I was able to have admin functionality based on value within the DB:
app.get('/admin', function (req, res) {
connection.query({
sql : 'SELECT role from `auth_users` WHERE `username`= ?',
timeout : 40000, // 40s
values : [req.user['id']]
}, function (error, results, rows) {
if (results[0]['role'] === "admin") {
admin = (results[0]['role']);
res.render('admin', {
isAuthenticated : req.isAuthenticated(),
user : req.user
});
} else {
admin = "";
res.redirect('/index');
}
})
});

Passportjs not calling isAuthenticate

I'm running into an issue with my index.js file trying to call isAuthenticate() using passportjs with expressjs. When I make the function call req.isAuthenticated() never gets called and will always return false.
Brief explanation, I'm trying to authenticate the user so they can access pages that they are authorized to view.
Here is a link to the repo https://github.com/SpotOnSoftwareInc/web-app
note: this was code that I inherited from someone else and a lot of these tools are new to me.
'module.exports = function (passport) {
router.get('/login', login.get);
router.post('/login',passport.authenticate('local-login',{
//session: false,
successRedirect : '/registerprocess',
failureRedirect : '/register',
failureFlash: true
}));
function isLoggedInBusAdmin(req, res, next) {
//if user is authenticated in the session, carry on
if (req.isAuthenticated() && ((req.user[0].role === 'busAdmin') || (req.user[0].role === 'saasAdmin'))){
return next();
}
req.flash("permission", "You do not have permission to access that page");
// if they aren't redirect them to the home page
res.redirect('back');
}'
lib\auth.js
`function isAuthenticated(req, res, next) {
console.log('ENTERED IS AUTHENTICATED');
isValidToken(req.db, req.headers.authorization, function (result) {
if (!result) {
console.log('Not Authenticated');
return res.send(403);
} else {
req.mobileToken = result[0];
console.log('Authenticated PASS');
return next();
}
});
}
}`
Found the error in my app.js file
instead of calling
employee.find({_id: id}, function (err, user){
i was calling
employee.findById({_id: id}, function (err, user){

Selectively enable HTTP basic authentication on some REST APIs

I am using node.js restify to build a REST API server.
I have added HTTP Basic authentication to the REST APIs. However, I only want some selected APIs to have authentication. Currently, all the REST APIs have to be authenticated.
Code for enabling HTTP Basic authentication;
server.use(restify.authorizationParser());
function verifyAuthorizedUser(req, res, next)
{
var users;
users = {
foo: {
id: 1,
password: 'bar'
}
};
if (req.username == 'anonymous' || !users[req.username] || req.authorization.basic.password !== users[req.username].password) {
// Respond with { code: 'NotAuthorized', message: '' }
next(new restify.NotAuthorizedError());
} else {
next();
}
next();
}//function verifyAuthorizedUser(req, res, next)
server.use(verifyAuthorizedUser);
Here are some of the APIs I have;
var api_get_XXX = function (app) {
function respond(req, res, next) {
//action
};
// Routes
app.get('/XXX', respond);
}
var api_get_YYY = function (app) {
function respond(req, res, next) {
//action
};
// Routes
app.get('/YYY', respond);
}
var api_get_ZZZ = function (app) {
function respond(req, res, next) {
//action
};
// Routes
app.get('/ZZZ', respond);
}
api_get_XXX(server);
api_get_YYY(server);
api_get_ZZZ(server);
I would like to enable authentication for api_get_XXX(), api_get_YYY() but disable authentication for api_get_ZZZ().
You could maintain an array/object containing the exceptions:
function verifyAuthorizedUser(req, res, next) {
// list your public paths here, you should store this in global scope
var publicPaths = {
'/ZZZ': 1
};
// check them here and skip authentication when it's public
if (publicPaths[req.path()]) {
return next();
}
var users;
users = {
foo: {
id: 1,
password: 'bar'
}
};
if (req.username == 'anonymous' || !users[req.username] || req.authorization.basic.password !== users[req.username].password) {
// Respond with { code: 'NotAuthorized', message: '' }
next(new restify.NotAuthorizedError());
} else {
next();
}
next();
}
Or you can use an existing middleware for authentication: https://github.com/amrav/restify-jwt

How to secure a namespace with passport js?

Assume I have a route with the following namespace:
app.use('/logged', adminRoute);
Now, I have created the following passportjs function:
app.get('/logged/panel', function (req, res) {
if (req.user === undefined) {
res.redirect('/login');
} else {
res.render('/logged/panel', {
user: req.user
})
}
});
This function checks wether the user is authenticated on the /logged/panel pattern.
I want to modify this function so it will perform checks on each get/post url pattern from adminRoute. How can I do this correctly?
Consider using express.Router.
function ensureAuthenticated(req, res, next) {
if(logged) return next();
res.redirect('/login');
}
var loggedRouter = express.Router();
loggedRouter
.use(ensureAuthenticated)
.get('/panel', panelHandler)
.get('/other', otherHandler);
var mainRouter = express.Router();
mainRouter.use('/logged', loggedRouter);
app.use(mainRouter);
You can include checking if user is logged inside ensureAuthenticated function. This middleware function will always be executed before /logged/panel and /logged/other.

Categories

Resources