I can't create a cookie using node-client-sessions - node.js

I am building a NodeJS web server, mostly static files (jade to come) but I am at the point where I want to be able authenticate the user and all was going fine until I hit a speed bump with setting cookies.
I am using express & client-sessions and I am almost verbatim example code.
No matter what I am doing I don't seem to be able set a cookie.
Code below I am hoping there's a simple gotcha I have missed!
** Versions **
NodeJS: v 6.2
client-sessions: 0.7.0
//** Required files
var express = require("express");
var bodyParser = require("body-parser");
var sessions = require("client-sessions");
var app = express();
var port = 8080;
var svr = app;
//** Middleware
app.use(express.static(__dirname + '/Public')); //** Use express globally to catch all requests and direct to Public folder
app.use(bodyParser.urlencoded({extended: false})); // create application/x-www-form-urlencoded parser
app.use(bodyParser.json()); // create application/json parser
app.use(sessions({
cookieName: 'mySession', // cookie name dictates the key name added to the request object
secret: 'kdheiuehiygft', // should be a large unguessable string
duration: 24 * 60 * 60 * 1000, // how long the session will stay valid in ms
activeDuration: 1000 * 60 * 5 // if expiresIn < activeDuration, the session will be extended by activeDuration milliseconds
}));
app.get("/", function(req, res){
req.mySession.seenyou = true;
res.setHeader('X-Seen-You', 'false');
res.sendFile(__dirname + "/index.htm");
});

The reasons appears to be that Express was "capturing" the input prior to me setting anything and redirecting to the index.html file in Public.
Having now created a separate login page which POST's the data to a new route, all works fine!

Related

Double authenticator with JWT in NodeJS Express

I'm currently trying to build an express server that allows the user to authenticate via two third-party services: Google and Steam. The authentication is done via JWT and it works when only one of the two services is activated, but I can't get the protected routes to work when the user is logged in using one of the two services.
The code:
const express = require('express');
const bodyParser = require('body-parser');
const {gAuth, gProtect} = require('./auth/google_auth');
const {sAuth, sProtect} = require('./auth/steam_auth');
const app = express();
gAuth(app);
sAuth(app);
//middlewares
app.use(express.static('views'));// folder in which to put the static files (html, css, js client)
app.use(bodyParser.json({limit: '50mb'})); // read json
//middlewares (just for the widget)
app.use(bodyParser.urlencoded({ extended: true , limit: '50mb'})); // read form enctype data
app.set('view engine', 'ejs'); // set the engine render ejs for dynamic building of html pages with ejs tags
//set up routers for v1 app
const genericRouter = require('./routes/generic_router'); //testing if the application is working
const secureRouter = require('./routes/secure_router'); //testing if normal auth is working
//set up routers for latest version app
app.use('/', genericRouter);
app.use('/', gProtect(), secureRouter);//protected end-points (requiring auth)
app.use('/', sProtect(), secureRouter);
module.exports = app;
The problem is in the
app.use('/', gProtect(), secureRouter);//protected end-points (requiring auth)
app.use('/', sProtect(), secureRouter);
bit, since the second app.use overwrites the first, making all authentication attempts with Google fail. What can I do to make it so that the user can access the protected routes either with Google or Steam?
Use different endpoints
app.use('/', genericRouter);
app.use('/google', gProtect(), secureRouter);
app.use('/steam', sProtect(), secureRouter);

node js server propplem

const express = require("express");
const app = express();
var i = new Number;
i=0;
app.get("/", function(req, res){
i++
console.log(i);
});
app.listen(8080);
I created a very small node js project. I have a problem. when I create a variable like above, it doesn't evaluate for each user separately. that is, when a user requests a get, I want it to be 1 each time.
Sample
my problem is that when a jack user enters a site, if he doesn't log out, someone who enters the site's home page from another device enters his account with jack.
how can I do that?
The simplest answer for your question is to simply declare and increment the variable inside the function passed to app.get, but I'm going to assume that you would like a situation where, for a given user's series of requests, the number will increment.
The simplest way to do this is using a server side session, which is provided by the express-session library. Additionally, in order for this to work, you need to call res.end() in order to send the cookie associated with the server session back to the user's browser. More information on sessions generally can be found here.
Below is code to replicate the intent of what you have there, but incrementing for each request from a unique browser instance (identified by the same cookie value associated with the server session):
const express = require('express');
const session = require('express-session');
const app = express();
app.use(session({
resave: false,
saveUninitialized: true,
secret: 'secret',
cookie: {
maxAge: 60000
}
}));
app.get('/', function(req, res){
if (!req.session.value) {
req.session.value = 0;
}
req.session.value++;
console.log(req.session.value);
res.end();
});
app.listen(8080);

client-sessions nodejs / Express - error: Cannot set property 'mydata' of undefined

I'm trying to use the client-sessions middleware in nodejs / Express and I get the following error: Cannot set property 'mydata' of undefined.
I've also looked at this post, but could not find additional clues as to why I may be getting the error. node-js-client-sessions-not-creating-req-session
var bodyParser = require('body-parser');
const express = require('express');
const app = express();
const clientSessions = require("client-sessions");
var urlencodedParser = bodyParser.urlencoded({ extended: false });
var router = express.Router();
app.use(clientSessions({
cookieName: 'mydata', // cookie name dictates the key name added to the request object
secret: 'longsecretkeyorwhatever', // should be a large unguessable string
duration: 24 * 60 * 60 * 1000, // how long the session will stay valid in ms
activeDuration: 1000 * 60 * 5 // if expiresIn < activeDuration, the session will be extended by activeDuration milliseconds
}));
/* Form POST handler */
router.post('/', urlencodedParser, function(req, res) {
if (!req.body) return res.sendStatus(400);
if(req.body.firstName){
req.session_state.mydata = req.body.mydata;
}
})
The documentation of client-sessions explains:
cookie name dictates the key name added to the request object
Since you're setting firstName as cookie name, the session object is available as req.firstName:
req.firstName.mydata = req.body.mydata

node.js session values aren't accessible in second api call

i am facing the following issue:
(I am using node-client-sessions module)
I send an ajax request, through the browser, to my API : /api/request1
In my api.js I handle that request, calculate some stuff and write some results into the session like this.
router.post('/request1', function(req, response, next) {
// some wield calculations
req.session.calcData = { // some content }; 
// some other calculations
console.log(req.session.calcData); // logs the correct object
response.send('success');
}
After receiving the success on client side I send another api call like this for example: /api/request2
router.post('/request2', function(req, response, next) {
// here i want to use some of the results from the previous calculations which i stored in the calcData session.
console.log(req.session.calcData); // this logs undefined
}
Shouldn't req.session.calcData be available in both functions?
Enviroment Info
Express Framework 4.x
app.js :
...
var app = express();
...
var session = require('client-sessions');
...
app.use(session({
cookieName: 'session',
secret: 'random_string_goes_here',
duration: 30 * 60 * 9999999,
activeDuration: 5 * 60 * 1000,
}));
...
app.use('/api', api);
According to example at client-session, you must use req.csession and req.csflush();
var express = require('express');
var path = require('path')
var cs = require('client-session');
var clientSession = cs('mysecretkey');
var app = express();
app.use(clientSession.connect());
app.get('/', function(req, res){
var count = req.csession['count'];
if(!count) count = 1;
else count++;
req.csession['count'] = count;
//sync to cookie session equal to res.csflush(),make sure to call it before response
req.csflush();
res.send(count.toString());
});
app.listen(8124);
console.log('Server running at http://127.0.0.1:8124/');

passing objects (passport) between routes

Think what I am trying to do should be relatively easy, but I am loosing the thread, and potentially the will to do this.
Setting up a node application using node and express 4. And I use passport for authentication. Followed an absolutely amazing guide by scott.io which did the trick nicely https://scotch.io/tutorials/easy-node-authentication-setup-and-local
And it works a charm. However, I want to separate my routes, because I like keeping things tidy (thats a lie, but I intend to keep the lie living).
My plan was to have four sets of routes.
api (mapped to /api, using the file ./routes/api.js)
index (mapped to /, using the file ./routes/index.js)
auth (mapped to /auth, keeps track of all authentication, callbacks as well as some activator and other bits)
Now to my issue, I need to make the passport available to app (or get api.js and indes.js to be able to call functions in passport.js) and I can't quite figure out how.
My plan was to initiate passport like so:
var passport = require('passport');
app.use(session({secret: 'Not-telling-you)',
saveUninitialized: true,
resave: true
})); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
//Configuring the passports
require('./config/passport')(passport);
That should give me passport available in app
Next to load the route modules
var auth = require('./routes/auth')(app, passport);
var users = require('./routes/users')(app,passport);
var activator = require('./routes/activator')(app,passport);
This SHOULD allow me to access them in the modules?
Map all toutes in app
app.use('/api', api);
app.use('/auth', auth);
app.use('/', index);
And then write the modules as follows (this is a super simple version of auth)
var bodyParser = require('body-parser');
var activator = require('activator');
var express = require('express');
var router = express.Router();
//Lets read the configuration files we need
var activatorCfg = require('../config/activator.js')
var cfgWebPage = require('../config/webpage.js');
//So we can read the headers easily
router.use(bodyParser.json()); // support json encoded bodies
router.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
//Activating activator, so we can actively activate the actives
activator.init({user: activatorCfg, transport: activatorCfg.smtpUrl , from: activatorCfg.fromEmail, templates: activatorCfg.templatesDir});
router.get('/login', function(req, res) {
res.render('login.ejs', { title: 'Betchanow - Social betting as it should be' , loginUrl: cfgWebPage.loginUrl, trackingID: cfgWebPage.googleTracking.trackingID, message: req.flash('loginMessage') });
});
module.exports=function(app, passport) {
router
}
My problem is that if I do that, express complains that
throw new TypeError('Router.use() requires middleware function but got a
^
TypeError: Router.use() requires middleware function but got a undefined
If I just return the router (skip wrapping it in a function) I end up with a
var search = 1 + req.url.indexOf('?');
^
TypeError: Cannot read property 'indexOf' of undefined
So is there a right, simple or preferably right and simple way of achieving this?
Think the trick would be to pass app and passport (or only passport), think is I need access to either data or functions from passport in all three, and as I was planning to play with ACL as well, wanted to add that to auth to make my life simple as well.
============== EDIT =============
So here is my issue.
If I now do a post to the authentication route (code below)
//Lets load the modules, note the missing passport
var bodyParser = require('body-parser');
var activator = require('activator');
var express = require('express');
var router = express.Router();
//Lets read the configuration files we need
var activatorCfg = require('../config/activator.js')
var cfgWebPage = require('../config/webpage.js');
//So we can read the headers easily
router.use(bodyParser.json()); // support json encoded bodies
router.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
//Activating activator, so we can actively activate the actives
activator.init({user: activatorCfg, transport: activatorCfg.smtpUrl , from: activatorCfg.fromEmail, templates: activatorCfg.templatesDir});
//Lets start with our routes
// process the login form
router.post('/login', passport.authenticate('local-login', {
successRedirect : '/', // redirect to the secure profile section
failureRedirect : '/login', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}));
module.exports=function(app, passport) {
return router;
}
I end up with the issue that the route code (./routes/auth.js) have no clue what passport is. (loded in the app as follows):
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
//Configuring the passports
require('./config/passport')(passport);
You'll be getting the error because you're not returning the router.
module.exports=function(app, passport) {
return router;
}
EDIT:
You won't be able to access the passport property because you're not passing it around or setting it anywhere. As I'm not sure how passport works (whether it acts as a singleton or not), so you have a couple of options in your routes file:
var passport = require('passport')
which may "just work", or
var passport; // at the top of your routes file
// your routes
module.exports = function(app, _passport) {
passport = _passport;
return router;
}
A third option is to wrap your entire routes in the exports method:
// your requires here
module.exports = function(app, passport) {
//So we can read the headers easily
router.use(bodyParser.json()); // support json encoded bodies
router.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
//Activating activator, so we can actively activate the actives
activator.init({user: activatorCfg, transport: activatorCfg.smtpUrl , from: activatorCfg.fromEmail, templates: activatorCfg.templatesDir});
//Lets start with our routes
// process the login form
router.post('/login', passport.authenticate('local-login', {
successRedirect : '/', // redirect to the secure profile section
failureRedirect : '/login', // redirect back to the signup page if there is an error
failureFlash : true // allow flash messages
}));
return router;
}

Resources