newbie.
I'm using ExpressJS/Node. Here's my config stuff:
var express = require('express'),
app = express.createServer(),
jade=require('jade');
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.use(express.logger());
app.use(express.cookieParser());
app.use(express.session({ secret: "secretive secret" }));
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(require('stylus').middleware({ src: __dirname + '/public' }));
app.use(app.router);
app.use(express.static(__dirname + '/public'));
app.use(express.csrf());
I found csrf.js in Express directories, and see that it should be generated and assigned to req.body._csrf, but I'm not sure how to access it.
Here's the csrf.js code
module.exports = function csrf(options) {
var options = options || {}
, value = options.value || defaultValue;
return function(req, res, next){
// generate CSRF token
var token = req.session._csrf || (req.session._csrf = utils.uid(24));
// ignore GET (for now)
if ('GET' == req.method) return next();
// determine value
var val = value(req);
// check
if (val != token) return utils.forbidden(res);
next();
}
};
Help? Thanks!
Dynamic helpers has been removed from Express since 3.x.
The new usage would be app.use(express.csrf());, which comes from Connect.
Add the token to dynamic helpers.
app.dynamicHelpers({
token: function(req, res) {
return req.session._csrf;
}
});
Reference it in your jade template.
input(type='hidden', value=token)
Source: http://senchalabs.github.com/connect/middleware-csrf.html
In Express 4.x this middleware is removed. For Express 4.x you can do it as follows
var csrf = require('csurf');
app.use(csrf());
Ah!! you need to register the csrf middleware after your session and cookieParser middleware.
Inside Route Or Ctrl
res.render('someform', { csrf: req.csrfToken() });
or You can set a local variable also like so
app.use(function(req, res, next){
res.locals.csrf = req.csrfToken();
});
Then in view
input(type="hidden", name="_csrf", value="#{csrf}")
You are done!! :)
If you also want to set a secure cookie for your CSRF token that can be read by your frontend (angular for example), you can do this:
app.use csrf()
app.use (req, res, next) ->
res.cookie('XSRF-TOKEN', req.csrfToken(), {secure: true})
next()
Related
Pug file:
...
- var paths = flatSitemap(sitemap);
app.js file:
var fsm = require('./routes/fsm.js');
app.set('port', process.env.PORT || 4109);
app.set('views', path.join(__dirname, 'src/pug'));
console.log(path.join(__dirname, 'src/pug'));
app.set('view engine', 'pug');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(path.join(__dirname, 'public')));
app.use(function (req, res, next) {
res.locals.flatSitemap = fsm.flatSitemap;
next();
});
app.locals.flatSitemap = fsm.flatSitemap;
app.get('/', function(req, res) {
res.render('./index', {flatSitemap: fsm.flatSitemap}); // works!!!
res.render('./index'); // Not working
});
So when I use the res.render using the options it works, but if I don't include the options and rely on pug reading res.locals it doesn't, and comes back with "flatSitemap is not a function".
The res object is not automatically passed to the view. Hence the message that flatSitemap does not exist or is not a function. You won't get around appending it as a parameter. You can make a condition with a binary logic OR operator.
app.get('/', function(req, res) {
res.render('./index', { flatSitemap: res.locals.flatSitemap || fsm.flatSitemap });
});
Once the user logs in, I am trying to serve static files. I applied the answer found here and I am having difficulty implementing it.
Upon log-in, I have this inside of routes.js:
app.post('/', function(req, res){
AM.manualLogin(req.body['user'], req.body['pass'], function(e, o){
if (!o){
res.status(400).send(e);
} else {
req.session.user = o;
if (req.body['remember-me'] == 'true'){
res.cookie('user', o.user, { maxAge: 900000 });
res.cookie('pass', o.pass, { maxAge: 900000 });
}
console.log(req.session);
res.status(200).send(o);
}
});
});
where I am setting the user in the request's session.
Inside app.js I have:
var http = require('http');
var express = require('express');
var session = require('express-session');
var bodyParser = require('body-parser');
var errorHandler = require('errorhandler');
var cookieParser = require('cookie-parser');
var MongoStore = require('connect-mongo')(session);
var app = express();
app.locals.pretty = true;
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/app/server/views');
app.set('view engine', 'pug');
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(require('stylus').middleware({ src: __dirname + '/app/public' }));
function isLoggedIn( req, res, next ) {
console.log(req.session);
if (typeof req.session.user == undefined) {
res.redirect('/');
}
next();
}
app.use(express.static(__dirname + '/app/public'));
app.use('/home', isLoggedIn, express.static(__dirname + "/app/server/docs"));
app.use(session({
secret: 'faeb4453e5d14fe6f6d04637f78077c76c73d1b4',
proxy: true,
resave: true,
saveUninitialized: true,
store: new MongoStore({ url: process.env.DB_URL })
})
);
require('./app/server/routes')(app);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
where I am conditionally trying to render the static files for /home.
The problem resides in isLoggedIn where req.session is always undefined even though it is defined in my router function. Why is this? My log statements show that is is being set, but somehow is lost inside isLoggedIn.
One potential problem I see is your app.use(session(...)); is placed after your app.use('/home', isLoggedIn, ...);. Hence, the session is not being properly loaded in when visiting the /home path. Try placing the app.use(session(...)); middleware before the app.use('/home', isLoggedIn, ...); middleware.
This is due the fact that the execution of middleware is determined by the order of loading (i.e. if it's higher in your code, it's executed first).
I am using Express "express": "~4.13.1" and "express-session": "^1.11.3".
I have set my server like this :
app.js :
var express = require('express');
var session = require('express-session');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var routes = require('./routes/index');
var users = require('./routes/users');
app = express();
// view engine setup
var engines = require('consolidate');
app.set('views', path.join(__dirname, 'views'));
app.engine('html', engines.mustache);
app.set('view engine', 'html');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
//Using express-session in app with secret key
app.use(session({
secret: 'mapdcs',
resave: true,
saveUninitialized: true,
cookie: {
path: '/',
httpOnly: true,
secure: false,
maxAge: null
}
}));
app.use('/', routes);
app.use('/api/users', users);
index.js :
// First call
router.post('/adduser', function(req, res, next) {
req.session.username = red.body.username;
req.session.save();
console.log('>>Session data From Add users');
console.log(req.session); //I got the username session here
}
// Second call
router.post('/check_auth', function(req, res, next) {
console.log('>> Session data From check_auth');
console.log(req.session); //Am not getting session here.
}
Am trying to solve this issue since last two days. Can any one help in this please. Thanks in advance.
You seem to have missing closing brackets ')' after the router calls, but I don't think that's the main issue. It has something to do with the request not sending a response / terminating correctly.
If you change the console.log(req.session)'s to something that sends a response e.g res.json(req.session), the second call works - see below for an example:
router.post('/adduser', function(req, res, next) {
req.session.username = red.body.username;
req.session.save();
console.log('>>Session data From Add users');
// changed console.log to res.json
res.json(req.session)
}); // Added the final closing bracket to router.post
// Second call
router.post('/check_auth', function(req, res, next) {
console.log('>> Session data From check_auth');
// Changed the second console.log to res.json
res.json(req.session);
}) // Added another closing bracket
Hope this helps!
Edit: You could also just use res.end(), res.send() or res.render() - anything that generates a response - see the Express response docs.
I changed the axios call and set withCredential to true to solve the problem.
I'm having some problems trying to implement some middleware in my app.
Specicially, the app.use() does not seem to catch and I don't understand why.
Below is roughly what I have.
routes/index.js
var Sessions = require('../events');
module.exports = exports = function(app) {
app.use(Sessions.isLoggedIn);
//app.use() does not catch but this does
//app.all('*', Sessions.isLoggedIn);
// Home Page
app.get('/', displayHome);
app.get('/:library/:books', displayLibrary);
}
events.js
module.exports = exports = {
isLoggedIn: function(req, res, next) {
console.log('isLoggedIn');
return next();
}
Any suggestions as to why app.use() is not catching?
UPDATE:
Here is the configuration in ape.js
app.configure(function() {
app.set('port', process.env.VCAP_APP_PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.logger('dev'));
app.use(express.compress()); // compress responses
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(expressValidator);
app.use(express.cookieParser('locket'));
app.use(express.cookieSession({
key: 'locket',
secret: 'mySecret',
cookie: {httpOnly: true, expires: 0, path: '/'}
}));
// cache every file going out
app.use(function(req, res, next) {
if (!res.getHeader('Cache-Control')) {
res.setHeader('Cache-Control', 'public, max-age=' + (86400 / 1000));
}
next();
});
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
});
app.configure('development', function(){
app.use(express.errorHandler({showStack: true, dumpExceptions: true}));
});
routes(app);
The router is responding to the request before your middleware function has a chance to run.
app.js sets up several other middleware functions, then uses app.router. You then call your routes/index.js file, which uses a new middleware function which gets added after app.router.
use your isLoggedIn function before the router, or use it specifically with the routes that need to check login state:
app.get('/', Sessions.isLoggedIn, function(req, res) { ... });
I have done this before... I don't follow what I'm doing wrong this time, but I've been struggling for a couple of hours and now consider myself mentally blocked. The corresponding code:
app.use(express.bodyParser());
app.use(i18next.handle);
app.use(express.methodOverride());
app.use(express.static(__dirname + '/public'));
app.set('views', __dirname + '/views');
app.set('view engine', 'swig');
app.set('view cache', false);
var session_store = new RedisStore({ client : redis_client});
app.use(express.errorHandler({ dumpExceptions : true, showStack : true}));
app.use(express.cookieParser());
app.use(express.session({ store : session_store, secret : SESSION_SECRET, key : "sid" }));
app.use(app.router);
Then when handling requests, here's just an example:
app.get('/session_test', function (req, res, next) {
console.log(req.session); //undefined
});
Connection to redis is working just fine. No errors are shown. Then, when trying to access it from the request, the req.session is undefined. The browser is sending the correct sid.
I'm no expert on the exact flow that occurs during the request, but after debugging, it seems as if the router was being called before the session middleware.
Thanks in advance for any and all the likely help. I will provide any code I can, I'm unsure what might be of your help.
Here's more code.
server.js
//Dependency modules
var express = require('express'),
app = express.createServer(),
//Application dependency modules
settings = require('./settings'), //app settings
routes = require('./routes'), //http routes
rtroutes = require('./rtroutes'); //real time communication routes (io)
var io = require('socket.io').listen(app);
var appWithSettings = settings.setup(io, app);
routes.settings.setup(appWithSettings);
rtroutes.settings.setup(io, appWithSettings);
No routes are added until routes.settings.setup is called. settings (which is the global settings) is a pretty big file. That's where all configuration is done. Settings are not added until settings.setup method is called too. Here's a cut of the file:
//Dependency modules
var express = require('express'),
redis = require('redis'),
//Important configuration values
var SESSION_SECRET = 'some secret thing which doesnt belong to stackoverflow!',
insert_other_variables_here = "lalala";
//Computed general objects
var RedisStore = require('connect-redis')(express),
redis_client = redis.createClient(REDIS_PORT, REDIS_HOST);
exports.setup = function (io, app) {
app.configure(function () {
app.use(express.bodyParser());
app.use(i18next.handle);
app.use(express.methodOverride());
app.use(express.static(__dirname + '/public'));
app.set('views', __dirname + '/views');
app.set('view engine', 'swig');
app.set('view cache', false);
var session_store = new RedisStore({ client : redis_client});
app.use(express.errorHandler({ dumpExceptions : true, showStack : true}));
app.use(express.cookieParser());
console.log("ABOUT TO ADD SESSION STORE MIDDLEWARE");
app.use(express.session({ store : session_store, secret : SESSION_SECRET, key : "sid" }));
console.log("AND NOW ADDED THE SESSION STORE MIDDLEWARE");
app.use(app.router);
});
app.configure('development', function () {
//some things in here, but nothing that affects app. I have commented this
//for debugging and it changed nothing
});
app.configure('production', function () {
//mostly configuration for io and some caching layers, as well as servers info
app.use(express.errorHandler());
app.use(express.logger({ stream : logFile }));
});
app.listen(WEB_PORT);
return {
app : app,
//some other stuff that isn't relevant
}
}
I have 25 routes split in 4 different files (somehow I didn't have a need for session until now, since I was delaying some parts and everything needed was done with Mongoose). Here's an example of how it is being done (with fake names):
routes/index.js
export.settings = require("./settings");
routes/settings.js
exports.setup = function (app_settings) {
require("./route1")(app_settings);
require("./route2")(app_settings);
require("./route3")(app_settings);
};
Here's a stripped out "route1" file ("routes/route1.js"):
module.exports = function (app_settings) {
var app = app_settings.app;
console.log("ABOUT TO ADD ROUTES")
app.get("/signin", function (req, res, next) {
console.log(req.session); //this will be undefined
});
app.get("/register", function (req, res, next) {
});
app.get('/language', function (req, res, next) {
});
app.post('/settings', function (req, res, next) {
});
console.log("ADDED ROUTES NOW!")
}
Whenever you define a route, the router gets automatically inserted into whatever the middleware stack is at the time (subsequent attempts to insert it deliberately will be ignored). Are you sure you aren't defining any routes before you set the session handler?
Forgot to update this: Ebohlman set me in the right track.
It was i18next. When calling one of the init method it sets up routes and it was forcing app.router to be forced into the handle stack sooner. My bad, I didn't realize that part of the code was interacting with the app object and it did.
There was no way the question could have been answered better than how he did with the information I gave, so I am marking his answer as right.
I should try sleeping more v.v