Node.js User Authentication - javascript

I'm new with nodeJs and i'm actually following a tutorial about it.
In the tutorial, a code was used:
In a verify.js file the following function was written:
exports.verifyOrdinaryUser = function (req, res, next) {
// check header or url parameters or post parameters for token
var token = req.body.token || req.query.token || req.headers['x-access-token'];
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token, config.secretKey, function (err, decoded) {
if (err) {
var err = new Error('You are not authenticated!');
err.status = 401;
return next(err);
} else {
// if everything is good, save to request for use in other routes
req.decoded = decoded;
next();
}
});
} else {
// if there is no token
// return an error
var err = new Error('No token provided!');
err.status = 403;
return next(err);
}
};
and in another file, the function was called so :
/*****........****/
.post(verify.verifyOrdinaryUser, function(req, res, next){
/******.......*****/
everything is working fine without problem.
1- I don't understand why the function verify.verifyOrdinaryUser is not called so :
verify.verifyOrdinaryUser(req, res, next)
with his parameter (how is it possible that we call a function without his parameter .?
next , i've written a function :
exports.verifyAdmin = function(req, res, next){
if(req.decoded._doc.admin == false){
var err = new Error('You cannot access to this ressource!');
err.status = 401;
return next(err);
}
else {
next();
}
};
in the same file, to verify if a user is a admin or not, i have to call this function after the verifyOrdinaryUser function,
my problem is i don't know how i can make call of this function, with or without the parameters.
Thank you.

1- I don't understand why the function verify.verifyOrdinaryUser is
not called so : verify.verifyOrdinaryUser(req, res, next)
In simplest terms, That's because Express takes care of sending those parameters to the specified middleware instead of you specifying it here
And in function verify.verifyOrdinaryUser, The function is requesting for 3 parameters req, res, next and it receives those three parameters, if it requests for a parameter that doesn't exist, That parameters value will be undefined.
my problem is i don't know how i can make call of this function, with
or without the parameters.
Just call it like
/*****........****/
.post(verify.verifyOrdinaryUser, verify.verifyAdmin, function(req, res, next){
/******.......*****/
And in the functions code you can request for the parameters you need
exports.verifyAdmin = function(req, res){
if(req.decoded._doc.admin == false){
...
Hope this gives you some sense on whats going on, You should google for Node JS Middlewares and simple tutorials based on Node JS and Express.

Related

function for catching errors by parameters we give it as argument

I need to create authentication function named "access" for my restful API and i want it to look like below for each time user wants be in interaction with server :
access(id , token ,function(err){
if(err){
res.send(err)
}else {
res.send('you have all permissions')
}
})
how can i write this function to use in each authentication step?
For authentication you would typically have some middleware:
function isAuthenticated(req, res, next) {
// determine here if user is authenticated (and/or authorized)
if (user) {
next(); // user is authorized, call next
} else {
const error = new Error('unauthorized');
error.status = 400;
return next(err);
}
}
app.get('/authenticated/route', isAuthenticated, function(req, res) {
res.send('secret information');
});
I would recommend using something like Passport.js. It removes a lot of the authentication middleware, and especially makes it easy to integrate with providers like Google and Facebook.
Better to use is as middleware, if this is for all your entries
function access(req, res, next) {
// verify token
if (isNotVerified) { return next('You are not verified') }
// otherwise do what you want to do
return next()
}
and add it to all your routes where you want the user to be verified, someting like this:
route.get('/api/private/reports', access, function (req, res) {
// do some stuff only when user is verified
})
route.get('/api/sensitive/information', access, function (req, res) {
// do some stuff only when user is verified
})
Hope it will help you!

Pass Parameter to Function Express JS

everything good ? I would like to know the best way and if it is possible to send a certain parameter to an express function in the NodeJS.
i wanna pass the string ('admin') or other string that i want to function 'RoleTolen', using my route.
function verifyToken
function verifyToken(req, res, next) {
// Get auth header value
const bearerHeader = req.headers["authorization"];
// Check if bearer is undefined
if (typeof bearerHeader !== "undefined") {
// Split at the space
const bearer = bearerHeader.split(" ");
// Get token from array
const bearerToken = bearer[1];
// Set the token
req.token = bearerToken;
// Next middleware
next();
} else {
// Forbidden
res.sendStatus(403);
}
}
function ValidToken
function validToken(req, res, next) {
jwt.verify(req.token, process.env.SECRET, (err, authData) => {
if (err) {
res.sendStatus(403);
} else {
next();
}
});
}
function RolesToken
function rolesToken(role, req, res, next) {
var decoded = jwt.decode(req.token);
if (!decoded.permissions.includes(role)) {
res.json("sem permissao");
} else {
next();
}
}
my route
router.post(
"/posts",
verifyToken,
validToken,
rolesToken("admin"),
customerController.posts
);
function rolesToken(role, req, res, next) is not a proper Express.js route handler, as you already know (and hence the question, I assume).
What you can do is to write your rolesToken as a function that returns the actual Express.js compliant handler (function):
function rolesToken(role) {
return function(req, res, next) {
var decoded = jwt.decode(req.token);
if (!decoded.permissions.includes(role)) {
res.json("sem permissao");
} else {
next();
}
};
}
from the docs
Define error-handling middleware functions in the same way as other middleware functions, except with four arguments instead of three, specifically with the signature (err, req, res, next)):
Therefore your RolesTaken function won't work as expected.
Secondly, you can create a middleware or modify existing one
(req, res, next) => {
//some stuff
if(req.path == '/posts') req.role= 'admin';
if(req.path == '/someOtherPath') req.role= 'someRole';
//some other stuff
}
Now you can get the get the role in req.someProp in the your controller middlerware as req.role
you would like to see this question also

Destroying JSON Web Tokens

This is something,that really confuses. me. Let us suppose you have a REST API where you want the user to logout. After login out,the jwt(json web token) should be destroyed,so the user can not have access to the server's resources(ie menu,dishes etc).
In my case the user can logout,but he/she can still perform all the requests(get dishes,post and delete),until the token is valid. Here is my code.
verify.js
var User = require('../models/user');
var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
var config = require('../config.js');
exports.getToken = function (user) {
return jwt.sign(user, config.secretKey, {
expiresIn: 3600
});
};
exports.verifyOrdinaryUser = function (req, res, next) {
// check header or url parameters or post parameters for token
var token = req.body.token || req.query.token || req.headers['x-access-token'];
// decode token
if (token) {
// verifies secret and checks exp
jwt.verify(token, config.secretKey, function (err, decoded) {
if (err) {
var err = new Error('You are not authenticated!');
err.status = 401;
return next(err);
} else {
// if everything is good, save to request for use in other routes
req.decoded = decoded;
next();
}
});
} else {
// if there is no token
// return an error
var err = new Error('No token provided!');
err.status = 403;
return next(err);
}
};
I am invalidating the token after a period of 1 hour.
And users.js where I set all the routes with their tasks. ie localhost:3000/users/login,localhost:3000/users/register and localhost:3000/users/logout. So.
var express = require('express');
var router = express.Router();
var passport = require('passport');
var User = require('../models/user');
var Verify = require('./verify');
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
router.post('/register', function(req, res) {
User.register(new User({ username : req.body.username }),
req.body.password, function(err, user) {
if (err) {
return res.status(500).json({err: err});
}
passport.authenticate('local')(req, res, function () {
return res.status(200).json({status: 'Registration Successful!'});
});
});
});
router.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) {
return next(err);
}
if (!user) {
return res.status(401).json(
err: info
});
}
req.logIn(user, function(err) {
if (err) {
return res.status(500).json({
err: 'Could not log in user'
});
}
var token = Verify.getToken(user);
res.status(200).json({
status: 'Login successful!',
success: true,
token: token
});
});
})(req,res,next);
});
router.get('/logout', function (req, res) {
req.logout();
res.status(200).json({
status: 'Bye!'
});
});
module.exports = router;
It seems that the logout method req.logout,doesn't work:(. Any ideas?
Thanks,
Theo.
You cannot log out a user that has a valid token if all the data is on the client side. You would need to store some state on the server to distinguish between users that you explicitly logged out and those that you didn't and check this state every time. If all of the data is entirely in the JWT token then you can't do anything to make it invalid (other than changing your secret that would invalidate all of the tokens, not just this one).
You actually discovered the main disadvantage of using authentication based entirely on the data that is included in the token itself. Those tokens cannot be invalidated. Once they're out then must be assumed to be active. You could only ask the client to forget it, but the client cannot be trusted to do that.
In theory you might have a fast data store like Redis where you keep all of the valid tokens and remove tokens from there to force logout, and check this storage on every request to know who is still logged in and who is not, but if you do that then you might store the session data in Redis in the first place and give only some random keys to that data store to the clients.
JWT is designed to be stateless. This means that all the information needed is contained in the token itself.
As the token has already been created, logout will have no effect on the validity of this.
This leaves you needing to keep a list of 'invalidated' tokens, which means you have once more introduced state.
If you are only concerned about subsequent users on the same machine, you could delete the token on logout, thus preserving the statelessness, but this will not protect against cases where the token has been captured.

Any way to conditionally skip middleware with next() in express?

So for example-
//Functions
var validationCheck = function(req, res, next){
if(req.session.userId && req.session.token)
next('validationCatch') //Is this possible to skip middleware if not needed?
else
next()
}
var getUserId = function(req, res, next){
req.session.userId = DB.getUserId
next()
}
var getToken = function(req, res, next){
req.session.token = DB.getToken
next()
}
//a catcher function to direct to next function depending on route
var validationCatch = function(req, res, next){
next()
}
//Routes
app.get(api + '/feature1', validationCheck, getUserId, getToken, validationCatch, feature1)
app.get(api + '/feature2', validationCheck, getUserId, getToken, validationCatch, feature2)
My goal is to skip unnecessary middleware if information is already cached from previous routes. So in above example, feature2 doesnt have to enter getUserId and getToken if feature1 has already been called, thus making response faster.
If not possible, please state a more efficient architecture to handle repetitive validation processes. Thanks
Instead of register the callbacks directly, just call them in validationCheck if needed.
Here is a simple example with getUserId:
var validationCheck = function(req, res, next){
if(req.session.userId)
next()
else {
getUserId(req, res, function(err){
next(err)
})
}
}

Expose Expressjs middleware in API Client

I'm working on an Nodejs API Client that takes this simple form:
//client.js
function Client (appId, token) {
if (!(this instanceof Client)) {
return new Client(appId, token);
}
this._appId = appId;
this._token = token;
...
}
Client.prototype.save = function (data,callback) {
return this_request(...);
}
Client.prototype._request = function (method, url, data, callback) {
//do stuff
}
module.exports = Client
I would now like to make an auth function available as middleware in Expressjs routes but I'm not sure how to integrate the function into client.js.
var myModule = require('myModule');
var thingy = myModule("12345", 'abcde');
router.get('/protectedRoute', thingy.auth, function(req, res, next){
}
For example, should the function be defined as part of the prototype like this:
Client.prototype.auth = function(req,res,next) {
//do stuff
}
Any pointers and recommendations much appreciated.
So the way middleware is implemented, is that you have to pass a function for it to then get called with req res and next. As you've taken the OOP approach and made auth a prototype method on an object, when that function gets called by express, it will have a different this scope, and would thus likely throw an error. You need to use bind to create a function that binds a specific scope to that function, and then pass that to express.
router.get('/protectedRoute', thingy.auth.bind(thingy), function(req, res, next){
}
Alternatively:
var authMiddleware = function(req, res, next) {
thingy.auth(req, res, next);
}
router.get('/protectedRoute', authMiddleware, function(req, res, next){
}

Categories