require method called by function not working - node.js

I ran into this while setting some middleware only for certain routes. In my application, I only need session and csrf on my contact page.
Here's the problem. When I require them outside and use the references in an array as a route parameter, it works all fine. Session works fine and expects the same cookie(sessionID) for every request and CSRF check passes as it should.
But, when I use a function to return an array of 'middleware', then it behaves abnormally. When I 'get' contact, I receive one sessionID, and when I 'post' to it, apparently the session restarts and I get an error thrown since I have the older sessionID. And weirdly the CSRF also expects another csrf token and not the one it sent me.
I get that it's something to do with the way I'm requiring in modules, but I'd love to get a clear explanation as to why this is happening. Do note that I am beginner, so go easy on me :) Thanks!
// MIDDLEWARE FOR CERTAIN ROUTES
// This works fine!
var session = require('express-session')({secret: 'i lit fire to the rain', saveUninitialized: false, resave: true});
var csrf = require('csurf')();
router.get('/contact', [session, csrf], function(req, res, next) {
});
router.post('/contact', [session, csrf], function(req, res, next) {
});
// but this does not work
var contactMiddleware = function() {
var session = require('express-session')({secret: 'i lit fire to the rain', saveUninitialized: false, resave: true});
var csrf = require('csurf')();
return [session, csrf];
};
router.get('/contact', contactMiddleware(), function(req, res, next) {
});
router.post('/contact', contactMiddleware(), function(req, res, next) {
});

Hi have you tried to do this instead :
router.get('/contact', contactMiddleware, function(req, res, next)
edit:
so you only need a static array as far as I can see, so why not just doing this
var array = (function() {
var session = require('express-session')({secret: 'i lit fire to the rain', saveUninitialized: false, resave: true});
var csrf = require('csurf')();
return [session, csrf];
})();
and then passing your array to the route?
router.get('/contact', array, function(req, res, next) {
res.send('contact');
});

Related

Have a cookie get deleted as soon as I leave the page on node

I am setting a cookie as soon as users access my node app like this:
app = require("express")();
httpServer = require("https").createServer(options,app);
cookie = require("cookie");
app.get('/site', function (req, res, next) {
res.sendFile(__dirname + '/index.html');
res.cookie('active', 1, {
httpOnly: true
});
});
the cookie is stored so that just works fine. However, I want the cookie to be destroyed as soon as the user closes the browser, window, tab, etc. but its not. Why is that?
Thank you.
As per cookie package example can you try following for your code ?
const app = require("express")();
const httpServer = require("https").createServer(options,app);
const cookie = require("cookie");
app.get('/site', function (req, res, next) {
res.setHeader('Set-Cookie', cookie.serialize('active', String(1), {
httpOnly: true
}));
res.sendFile(__dirname + '/index.html');
});

How to prevent routes from being called multiple time in express.js

I am new to node.js and I am trying to make a simple task list app using express.js and express-session. However, for a reason that I don't understand most of the routes are called two or tree times when I make a request and it shouldn't. For instance, if I send a request to /new the new task is sometimes added two (or three) times instead of one and this causes a problem...
I read in other threads that the problem could come from the browser trying to get a favicon, however if I log all incoming request url (console.log(req.url)) on the /new route, the duplicated requests are always /new and not a favicon...
Here is my code :
var express = require('express');
var session = require('express-session');
// Create a new express application instance
var app = express();
// Initialize session
app.use(session({
secret: 'secret',
resave: true,
saveUninitialized: true,
cookie: {}
}));
// Initialize req.session.tasks if needed
app.use(function (req, res, next) {
if (req.session.tasks === undefined) {
req.session.tasks = [];
}
next();
});
app.get('/', function (req, res) {
res.send(req.session.tasks);
});
// Create a Test Task
app.get('/new', function (req, res) {
console.log(req.url);
req.session.tasks.push("Test Task");
res.redirect('/');
});
app.get('/clear', function (req, res) {
req.session.tasks = [];
res.redirect('/');
})
app.listen(3000, function () {
console.log('Task Server is listening on port 3000!');
});
Do you have a idea of what could be the cause of this problem and how to avoid it ??
Thanks a lot !

Authentication on NodeJS

I've watched a video on YouTube about Authentication on NodeJS. I already have a project just with get requisitions. That's the code that involves the login:
var sessions = require('express-session');
var session = {};
app.use(bodyParser.urlencoded({ extended: true }));
app.use(sessions({
secret: 'aisdh2782782hjda82',
resave: false,
saveUninitialized: true
}))
Methods
app.get('/login', function(req, res) {
session = req.session;
if(session.uniqueId) {
resp.redirect('/redirects');
}
})
app.post('/login', function(req,res) {
session = req.session;
if(req.body.username == 'admin' && req.body.password == 'admin'){
session.uniqueiD = req.body.username;
}
resp.redirect('/redirects');
});
app.post('/logout', function(req,res) {
req.session.destroy();
});
app.get('/redirects', function(req, res) {
session = req.session;
if(session.uniqueiD) {
resp.redirect('/home');
} else {
end('Wrong. Try it again');
}
});
Tests
I'm testing the source with postman. For instance I've tried using post login method passing as parameter this JSON:
{
"username": "admin",
"password": "admin"
}
Then I got this:
resp is not defined
May someone help me? I have limited knowledge of node and I don't really know what's wrong in my code (I just copied). Obs: I'll use mysql to fetch user data.
I haven't yet implemented your code myself, but it comes to my eye that you pass in the parameters (req, res) and refer to the later with "resp" instead of "res". It might just be a simple typo.
Also you don't handle a correct login diffrent from an incorrect one. Implement an "else {}" case after you ceck for successful login.

Express session can't get stored session values for next request

I'm trying to learn how express session is used. I wrote the following code. When I visit the /session route from Postman, every time it shows following in console:
not set
vikaskumar
What I expect is vikaskumar only, after first request. I guess it is saving this string in session but not storing in memory store. But as per docs, the memory store is default, so it should save it automatically?
Here's the code:
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}));
app.use(function (req, res, next) {
var views = req.session.username;
if (!views) {
console.log("not set");
req.session.username = 'vikaskumar';
}
next();
});
app.get("/session", function(req, res){
console.log(req.session.username);
res.write(req.session.username);
res.end();
});
As mentioned in the comments, you need to use Postman Interceptor for cookies to work with Postman.

Disable csrf validation for some requests on Express

I'm writing a small web app with Node.js using the Express framework. I'm using the csrf middleware, but I want to disable it for some requests. This is how I include it in my app:
var express = require('express');
var app = express();
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.cookieSession({secret: 'secret'}));
app.use(express.csrf());
I want to set a POST route without the csrf control.
There are several possible approaches. You basically need to understand what is the simplest and most correct rule to decide whether or not to use the csrf middleware. If you want csrf most of the time, except for a small whitelist of request patterns, follow the example in this answer I have about conditional logging middleware (copied below for convenience).
var express = require("express");
var csrf = express.csrf();
var app = express.createServer();
var conditionalCSRF = function (req, res, next) {
//compute needCSRF here as appropriate based on req.path or whatever
if (needCSRF) {
csrf(req, res, next);
} else {
next();
}
}
app.use(conditionalCSRF);
app.listen(3456);
Another approaches could be only using the middleware on a certain path like app.post('/forms/*', express.csrf()). You just want to find an expressive way to make it clean when the middleware will or will not be used.
Since Express middleware executes in order, you could always put your statements above the csrf() statement in the code.
Like this:
app.get '/ping', (req, res) -> res.status(200).end()
app.use csrf()
Express will return before your csrf token gets set. For very small numbers of endpoints (I just have one that fits this category), I've found this to be a cleaner solution.
Also, as of this writing, the code for the above answer would look like this:
customCsrf = (req, res, next) ->
if req?.url isnt '/ping'
return csrf()(req, res, next)
else
return next()
app.use customCsrf
That extra (req, res, next) tripped me up for awhile, so hope this helps someone.
dailyjs.com has a good article about csrf and express. It basically works like this:
use the csrf middleware:
app.configure(function() {
// ...
app.use(express.csrf());
// ..
});
create a custom middleware that sets the local variable token to the csrf value:
function csrf(req, res, next) {
res.locals.token = req.session._csrf;
next();
}
use your custom middleware in every route you want:
app.get('/', csrf, function(req, res) {
res.render('index');
});
in your form create a hidden field that holds the csrf value:
form(action='/contact', method='post')
input(type='hidden', name='_csrf', value=token)
Use the middleware at express app level adding every HTTP method to the ignored list, to ensure that the protection does not verify by default.
E.g.
const ignoredMethods = [
'GET',
'HEAD',
'POST',
'PUT',
'DELETE',
'OPTIONS'
]
const csrfInit = csurf({ignoredMethods, cookie: true });
app.use(csrfInit);
This will inject the csrfToken() method into each request object allowing the setup of a hidden field or consumable cookie by the application.
Then add a protected version in your as middleware to desired routes, and ignore the ones that do not require it.
E.g. Protected
const csrfProtection = csurf({ cookie: true });
router.post('/api/foo', csrfProtection, (req, res, next) => ...
E.g. Unprotected
const csrfProtection = csurf({ cookie: true });
router.post('/api/foo', (req, res, next) => ...
That worked for me.
const csrf = require("csurf");
const ROOT_IGNORE_LIST = ["/api/authenticate"];
const csrfMiddleware = csrf({
cookie: true,
ignoreMethods: ["GET", "HEAD", "OPTIONS"],
});
// Create middleware to check request url
app.use((req, res, next) => {
if (ROOT_IGNORE_LIST.includes(req.url)) {
next();
} else {
csrfMiddleware(req, res, next);
}
}).use("/api", routes);

Resources