Node endpoints stop working after cookie is set - node.js

I've been struggling with this issue for a while now. First, everything works great on my local PC, which makes it more difficult to test. When I upload the site to our public site, it breaks. I can log in just fine and get a cookie. But after that, all my endpoints stop working. Network tab shows nothing for request or response for them. I have tested with Postman. I can hit all the endpoints just fine until I log in and get a cookie. Then I can't hit those endpoints anymore, it just spins. If I delete the cookie, I can hit them again. So it's gotta be something with the way I'm setting the cookie or checking the cookie in my Node server.
Here is my main app.js Node server file. If any other files are needed, let me know.
const createError = require('http-errors');
const express = require('express');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const passport = require('passport');
const session = require('express-session');
const flash = require('connect-flash');
const cors = require('cors');
const MySQLStore = require('express-mysql-session')(session);
const config = require('./config/config');
// MySql Store setup
const options = {
host: config.host,
port: config.port,
user: config.username,
password: config.password,
database: config.database
};
const sessionStore = new MySQLStore(options);
const app = express();
// Middleware
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(config.session_secret));
app.use(cors());
app.options('*', cors());
// app.use(function(req, res, next) {
// res.header('Access-Control-Allow-Origin', '*');
// res.header(
// 'Access-Control-Allow-Headers',
// 'Origin, X-Requested-With, Content-Type, Accept'
// );
//
// next();
// });
//
// app.use(function(req, res, next) {
// res.setHeader('Access-Control-Allow-Origin', '*');
// res.setHeader(
// 'Access-Control-Allow-Methods',
// 'GET, POST, PUT, DELETE'
// );
// res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
// res.setHeader('Access-Control-Allow-Credentials', true);
// next();
// });
// session setup
app.set('trust proxy', 1); // trust first proxy
app.use(
session({
secret: config.session_secret,
resave: false,
saveUninitialized: false,
store: sessionStore,
name: 'reg-portal-cid',
cookie: {
secure: false,
httpOnly: false,
maxAge: 1000 * 60 * 60 * 24 * 365
}
})
);
app.use(flash());
require('./API_Gateways/passport')(passport);
// passport authentication
app.use(passport.initialize());
app.use(passport.session());
// user identification
app.use(require('./middleware/user_identification'));
app.use('/auth', require('./API_Gateways/Auth_Routes'));
// Application Gateways
// app.use('/api', function(req, res) {
// return res
// .status(200)
// .json({ message: 'Success! Base API endpoint.' });
// });
app.use('/users', require('./API_Gateways/User_Gateway'));
app.use('/customers', require('./API_Gateways/Customer_Gateway'));
app.use('/SDS', require('./API_Gateways/SDS_Gateway'));
app.use('/chemicals', require('./API_Gateways/Chemical_Gateway'));
app.use('/PDF', require('./API_Gateways/PDF_Gateway'));
app.get('/', (req, res) => {
return res
.status(200)
.send(
'<h1>This is the Node server for the Registration Portal.</h1>'
);
});
// Logout Route
app.post('/logout', (req, res) => {
console.log('app logout route');
sessionStore.destroy(req.sessionID, (err) => console.log(err));
req.logout();
req.session.destroy();
res.clearCookie('reg-portal-cid');
// res.clearCookie('connect.sid');
return res.status(200).json({ message: 'User Logged Out' });
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
});
process
.on('unhandledRejection', (reason, p) => {
console.error(reason, 'Unhandled Rejection at Promise', p);
})
.on('uncaughtException', (err) => {
console.error(err, 'Uncaught Exception thrown');
//process.exit(1);
});
module.exports = app;
Also, if this helps at all, after I have logged in with Postman and have a cookie, I click on the logout route and it just sits there and spins. When I hit cancel in Postman, my Node server terminal prints out POST /logout - - ms - - which tells me it is getting hit kind of.

The issue seems to be related to caching in the browser as there are no requests in the network tab of the browser.
To rule out this can you try to open the site in an incognito tab and try?

Try adding a memorystore, it worked for me
var MemoryStore = require('memorystore')(session)
app.use(session({
cookie: { maxAge: 86400000 },
store: new MemoryStore({
checkPeriod: 86400000 // prune expired entries every 24h
}),
resave: false,
secret: 'keyboard cat'
}))```

I figured out the issue. It was not anything anyone would have figured out from my question or from my code. So it is likely this question and answer will not be useful to anyone in the future. And it was very hard to find, like a needle in a haystack. I figured out that the session was not saving into the database on our live site, but it was on localhost.
So I started looking into why and started specifically looking into the express-mysql-session package. I figured out there was a way to run it in debug mode and once I did that, I instantly saw errors in the terminal saying it could not save to the database. So I knew I was on the right track. I looked up the specific error I was getting of ER_NOT_SUPPORTED_AUTH_MODE and that brought me to this Github issue thread: https://github.com/chill117/express-mysql-session/issues/109 And then I found twentythreetea's answer to run these 2 Mysql queries:
ALTER USER 'YOUR USERNAME'#'localhost' IDENTIFIED WITH mysql_native_password BY 'YOUR PASSWORD'
flush privileges;
I was using MySQL Workbench and figured out I had to remove the #'localhost' part. Once I did that, BOOM!! Everything is working beautifully on the live site!!

Related

Passport.js cookie not persist so login auth doesn't work even though session has the passport

I'm using the passport.js local strategy.
I was testing it under proxy setting, localhost.
Things worked fine until I prepare to deploy.
I changed the API address to include dotenv and set CORS settings on the server-side.
When trying to login, CORS works fine, OPTIONS and the POST get 200 ok. The client receives the success data. cookie saved in client.
But when auth checking process runs right after Redux "isLoggedin" state is updated(useEffect), req.session doesn't
t have the passport object. So deserializeUser not be called. The session contains other cookie info except for Passport.
This one is only on Firefox(not Chrome): Page will be redirected if the login auth succeeded(it checks right after login redux state changed), but since it's failed, the user stays on the login page still. But if I try to login on the same page again, the cookie start to show the passport object.(in other words, it shows from 2nd attempt). But it doesn't persist because the Redux login state has been changed to true at the first login attempt already.(so Auth checking doesn't occur.)
client:
Axios.post(
`${process.env.REACT_APP_API_URI}/api/users/login`,
loginData,
{ withCredentials: true, }
).then((res) => res.data){
//save isLoggedin to true in Redux
}
// auth check logic starts right after changing isLoggedin. Axios Get to authenticateCheck
server.js
app.use(helmet());
// app.use(express.static('public'));
app.use("/uploads", express.static("uploads"));
// Passport configuration.
require("./utils/passport");
// connect to mongoDB
mongoose
.connect(db.mongoURI, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
useFindAndModify: false,
})
.then(() => console.log("mongoDB is connected."))
.catch((err) => console.log(err));
// CORS Middleware
const corsOptions = {
origin: "http://localhost:8000",
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
credentials: true,
methods: ["POST", "GET", "DELETE", "PUT", "PATCH", "OPTIONS"],
allowedHeaders:
"Origin, X-Requested-With, X-AUTHENTICATION, X-IP, Content-Type, Accept, x-access-token",
};
// app.use(cors(corsOptions));
app.options(/\.*/, cors(corsOptions), function (req, res) {
return res.sendStatus(200);
});
app.all("*", cors(corsOptions), function (req, res, next) {
next();
});
// to get json data
// support parsing of application/json type post data
app.use(express.json());
app.use((req, res, next) => {
req.requestTime = new Date().toISOString();
next();
});
//support parsing of application/x-www-form-urlencoded post data
app.use(express.urlencoded({ extended: true }));
app.use(cookieParser());
// db session store
const sessionStore = new MongoStore({
mongoUrl: db.mongoURI,
collection: "sessions",
});
// tell app to use cookie
app.use(
session({
secret: process.env.SESSION_SECRET_KEY,
resave: false,
saveUninitialized: false,
store: sessionStore,
cookie: {
httpOnly: true,
secure: false,
sameSite:"none",
maxAge: 24 * 60 * 60 * 1000, // 24 hours
//keys: [process.env.COOKIE_ENCRYPTION_KEY]
},
name: "pm-user",
})
);
// tell passport to make use of cookies to handle authentication
app.use(passport.initialize());
app.use(passport.session());
app.use(compression());
app.use(flash());
app.use((req, res, next) => {
console.log("req.session:", req.session);
// console.log('/////// req: ///////', req);
console.log("////// req.user: ", req.user, " //////");
next();
});
//---------------- END OF MIDDLEWARE ---------------------//
authController:
exports.authenticateCheck = (req, res, next) => {
console.log("req.isAuthenticated():", req.isAuthenticated());
if (req.isAuthenticated()) {
return next();
} else {
return res.json({
isAuth: false,
error: true,
});
}
};
It would be a really big help if you can advise me where to look to fix it.
Thanks.
I found the solution finally.
It was because the session was renewed every time when a new request starts other than a login request.
The solution was, I had to add { withCredentials: true } to every Axios option in my frontend.

Express session resets session on every request

I have a VueJS project that uses axios to call a server on another domain. On this server, I need to save a few values in the session so they don't need to be looked up on every request.
The server is NodeJS and runs on Heroku and I'm using Redis for memory storage. I can successfully save data to the session, but on every new request, the system creates a new session with a new ID so I can't access the values saved during the previous request.
EDIT
After updating the code based on a number of suggestions, I can see the following error in the Network console on the session cookie:
Preflight Invalid Allow Credentials
EDIT 2
I was able to resolve the Preflight Invalid Allow Credentials by adding "credentials: true" to the corsOptions. This resolves the error I was seeing in network on the session, but I am still getting a new session ID for every request.
Code on the server:
const express = require('express');
const app = express();
const cors = require('cors');
var corsWhitelist = ['http://127.0.0.1:8080','http://127.0.0.1:8081']
var corsOptions = {
origin: function (origin, callback) {
if (corsWhitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS - '+origin))
}
},
credentials: true
}
let REDIS_URL = process.env.REDIS_URL;
var Redis = require('ioredis');
const session = require('express-session');
const cookieParser = require('cookie-parser');
const RedisStore = require('connect-redis')(session);
const sessionClient = new Redis(REDIS_URL)
sessionClient.on('error', function (err) {
console.log('could not establish a connection with redis. ' + err);
});
sessionClient.on('connect', function (err) {
console.log('connected to redis successfully');
});
app.set('trust proxy', 1)
app.use(cookieParser());
app.use(session({
store: new RedisStore({ client: sessionClient }),
secret: 'someSecret',
resave: false,
saveUninitialized: true,
cookie: {
secure: false,
httpOnly: false,
maxAge: 1000 * 60 * 10
}
}))
app.use(cors(corsOptions));
app.options('*', cors(corsOptions))
// Add headers
app.use(function (req, res, next) {
if (corsWhitelist.indexOf(req.headers.origin) !== -1) {
res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Credentials', 'true');
}
next();
});
const getUser = async function(req, res, next) {
if (!req.session.user) {
req.session.user = "test#example.com"
req.session.save()
}
next()
}
app.get('/session', getUser, (req, res) => {
// get the session id
console.log('session id:', req.session.id)
// the session will be automatically stored in Redis with the key prefix 'sess:'
const sessionKey = `sess:${req.session.id}`;
// let's see what is in there
client.get(sessionKey, (err, data) => {
console.log('session data in redis:', data)
})
res.status(200).send('OK');
})
Method on VueJS:
getSession: async function () {
axios({
url: 'https://server.example.com/session',
withCredentials: true,
}).then(res => {
console.log(res)
})
},
There were a number of changes required to make it work:
The preflight settings were being set twice, so in the code below, I needed to remove the second line:
app.use(cors(corsOptions));
app.options('*', cors(corsOptions)) //delete this
The headers I was trying to set under "// Add headers" didn't make it to the preflight request, so instead I needed to add "credentials: true" to the corsOptions and remove the code under "// Add headers":
var corsOptions = {
origin: function (origin, callback) {
if (corsWhitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS - '+origin))
}
},
credentials: true
}
Last but not least, the cookie settings in the session definition weren't working for a cross-domain request. Specifically, "sameSite: 'none'" and "secure: true" were necessary. Result looks like this:
app.use(session({
store: new RedisStore({ client: client }),
secret: 'someSecret',
resave: false,
saveUninitialized: true,
cookie: {
secure: true,
httpOnly: false,
sameSite: 'none',
maxAge: 1000 * 60 * 10
}
}))

Route callbacks not executing but middleware is

So this project was working fine before today, but after a bit of a nooby mistake with git I broke my project, and was unable to recover the commit. After spending some time getting everything fixed, my routes are now broken. My issue is that when calling my API routes now the server hangs for exactly 1 minute, then times out and logs a 404 on the server.
To give some background I'm using this boilerplate. In my debugging process I basically put console.logs everywhere I possibly could, and it looks like all my initialization middleware for express and passport are working fine, and my code is getting to where the routes are defined with no errors.
Middleware with app.use works and all checks out when a request is made, and all console.logs I've put there show fine. The console.logs only stop appearing in the final route definition like in this example:
app.get('/route', function(req, res, next) {
console.log('this never shows');
next();
}, function(req, res, next) {
console.log('this never shows');
})
My actual routes do have a res.send(), this is just an example to show you. All the console.logs I put in the middleware before this route show when the request is made, so it is hanging somewhere in app here.
It's a rather large project, so if you want specific code examples just ask and I'll post it. But I was able to recover all the important files that I had saved somewhere else and I'm pretty sure all my code is back to how it was before now.
edit:
Here is my file with express middleware definitions:
config/express.js
/**
* Module dependencies.
*/
var express = require('express');
var MongoStore = require('connect-mongo')(express);
var flash = require('connect-flash');
var helpers = require('view-helpers');
var swig = require('swig');
var session = require('express-session');
module.exports = function (app, config, passport) {
app.set('showStackError', true);
// should be placed before express.static
app.use(express.compress({
filter: function (req, res) {
return /json|text|javascript|css/.test(res.getHeader('Content-Type'));
},
level: 9
}));
app.use(express.favicon());
app.use(express.static(config.root + '/public'));
app.use('/uploads', express.static(config.root + '/uploads'));
var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header("Access-Control-Allow-Headers", "Access-Control-Allow-Methods, Access-Control-Allow-Headers, Access-Control-Allow-Origin, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
// intercept OPTIONS method
if ('OPTIONS' == req.method) {
res.status(204).end();
}
else {
next();
}
};
app.use(allowCrossDomain);
// don't use logger for test env
if (process.env.NODE_ENV !== 'test') {
app.use(express.logger('dev'));
}
// set views path, template engine and default layout
app.engine('html', swig.renderFile);
app.set('view engine', 'html');
app.set('views', config.root + '/app/views');
app.set('view cache', process.env.NODE_ENV !== 'development');
app.configure(function () {
// dynamic helpers
// app.use(function(req,res,next){
// req.locals.session = "eeeeeeee";
// next();
// });
// cookieParser should be above session
app.use(express.cookieParser());
// bodyParser should be above methodOverride
app.use(express.bodyParser());
app.use(express.methodOverride());
// express/mongo session storage
app.use(function(req, res, next) {
if(!req.cookies['_ga']) {
next();
}
else {
session({
secret: 'secrettexthere',
saveUninitialized: true,
resave: true,
store: new MongoStore({
url: 'mongodb://localhost/traderdb',
db: 'traderdb',
collection: 'sessions',
auto_reconnect: true
})
})(req, res, next);
}
});
// connect flash for flash messages
app.use(flash());
app.use(function (req, res, next) {
res.locals.session = req.session;
res.locals.req = req;
next();
});
app.use(function(req, res, next) {
if(!req.cookies['_ga']) {
next();
}
else {
passport.initialize()(req, res, next);
}
});
//app.use(helpers('app name'));
//
// use passport session
app.use(function(req, res, next) {
if(!req.cookies['_ga']) {
next();
}
else {
passport.session()(req, res, next);
}
});
// routes should be at the last
app.use(app.router);
// assume "not found" in the error msgs
// is a 404. this is somewhat silly, but
// valid, you can do whatever you like, set
// properties, use instanceof etc.
app.use(function(err, req, res, next) {
// treat as 404
if (~err.message.indexOf('not found')) return next();
// log it
console.error(err.stack);
// error page
res.status(500).render('500', { error: err.stack });
});
// assume 404 since no middleware responded
app.use(function(req, res, next) {
res.status(404).render('404', { url: req.originalUrl, error: 'Not found' })
});
})
}
I also have another file with passport route definitions if you'd like to see that too, but all that is tested and works okay too.
edit 2:
This is my entry point file:
server.js
/**
* Module dependencies.
*/
var express = require('express')
, fs = require('fs')
, passport = require('passport');
/**
* Main application entry file.
* Please note that the order of loading is important.
*/
// Load configurations
// if test env, load example file
var env = process.env.NODE_ENV || 'development'
, config = require('./config/config')[env]
, auth = require('./config/middlewares/authorization')
, mongoose = require('mongoose');
// Bootstrap db connection
mongoose.connect(config.db);
// Bootstrap models
var models_path = __dirname + '/app/models'
fs.readdirSync(models_path).forEach(function (file) {
require(models_path+'/'+file);
});
// bootstrap passport config
require('./config/passport')(passport, config);
var app = express();
// express settings
require('./config/express')(app, config, passport);
// Bootstrap routes
require('./config/routes')(app, passport, auth);
// Start the app by listening on <port>
var port = 3002;
app.listen(port);
console.log('Express app started on port '+port);
// expose app
exports = module.exports = app;
edit 3:
Here are my route definitions:
config/routes.js
var express = require('express');
var path = require('path');
var fileManager = require('express-file-manager');
var mongoose = require('mongoose');
var Session = mongoose.model('Session');
module.exports = function (app, passport, auth) {
var users = require('../app/controllers/users');
var coupons = require('../app/controllers/coupons');
var magazines = require('../app/controllers/magazines');
var zones = require('../app/controllers/zones');
var transactions = require('../app/controllers/transactions');
var favorites = require('../app/controllers/favorites');
var banners = require('../app/controllers/banners');
var reports = require('../app/controllers/reports');
var coverContest = require('../app/controllers/coverContest');
var contactMessage = require('../app/controllers/contactMessage');
app.post('/api/users/login', users.login);
app.post('/api/users/register', users.register);
app.post('/api/users/logout', users.logout);
app.post('/api/users/sendResetEmail', users.sendResetEmail);
app.post('/api/users/changePassword', users.changePassword);
app.post('/api/users/redeemCoupon', isValidAppUser(), users.redeemCoupon);
app.get('/api/users/validate', isLoggedIn(0), function(req, res) {
res.send(req.user);
});
app.post('/api/coupons', coupons.get);
app.post('/api/coupons/import', isLoggedIn(0), coupons.import);
app.post('/api/coupons/remove', isLoggedIn(0), coupons.remove);
app.post('/api/coupons/upload', isLoggedIn(0), coupons.upload);
app.post('/api/transactions', transactions.get);
app.post('/api/allTransactions', isLoggedIn(0), transactions.getAll);
app.post('/api/magazines', magazines.get);
app.post('/api/magazines/import', isLoggedIn(0), magazines.import);
app.post('/api/magazines/remove', isLoggedIn(0), magazines.remove);
app.post('/api/banners', banners.get);
app.post('/api/banners/import', isLoggedIn(0), banners.import);
app.post('/api/banners/remove', isLoggedIn(0), banners.remove);
app.post('/api/favorites', isValidAppUser(), favorites.get);
app.post('/api/favorites/import', isValidAppUser(), favorites.import);
app.post('/api/zones', zones.get);
app.post('/api/zones/add', zones.add);
app.post('/api/zones/addCoupon', zones.addCoupon);
app.post('/api/zones/addMagazine', zones.addMagazine);
app.post('/api/mail/ccSubmit', coverContest.ccSubmit);
app.post('/api/mail/contactSubmit', contactMessage.contactSubmit);
//app.get('/api/reports/siteUsers', reports.siteUsers);
app.get('/auth/facebook', passport.authenticate('facebook', { scope: [ 'email', 'user_about_me'], failureRedirect: '/login' }), users.signin);
app.get('/auth/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/login' }), users.authCallback);
app.get('/auth/github', passport.authenticate('github', { failureRedirect: '/login' }), users.signin);
app.get('/auth/github/callback', passport.authenticate('github', { failureRedirect: '/login' }), users.authCallback);
app.get('/auth/twitter', passport.authenticate('twitter', { failureRedirect: '/login' }), users.signin);
app.get('/auth/twitter/callback', passport.authenticate('twitter', { failureRedirect: '/login' }), users.authCallback);
app.get('/auth/google', passport.authenticate('google', { scope: ['profile', 'email'] }));
app.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/', successRedirect: '/main.html' }));
}
function isLoggedIn(secLvl) {
return function(req, res, next) {
if(req.isAuthenticated() && req.user.secLvl <= secLvl && req.user.google.email.includes('#bizpub36.com')) {
return next();
}
res.redirect('https://accounts.google.com/logout');
}
}
function isValidAppUser() {
return function(req, res, next) {
Session.findOne({ sess_id: req.body.sess_id }).exec(function(err, session) {
if(!err && session) {
next();
}
else {
res.end({ status: 'error', message: 'invalid session' });
}
});
}
}
If app.use works, my guess would be your protocol, is the app.get correct? You issue is otherwise located somewhere else in your code base as your sample runs fine as a single route express app.
It sounds like one of three things:
Somewhere in your middleware chain, you are not calling next() to allow it to advance to the next level of handlers and thus the request just eventually times out waiting for that middleware to finish (this seems to match the symptoms you describe).
Somehow, your app.get() doesn't actually match the route you expect it to or is not specified correctly.
You're using a router, but have not configured it correctly.
But, because you don't get an immediate 404, but rather it times out, it is probably option #1 above.

Cross Domain Cookies with Angularjs, Nodejs, Expressjs, express-sessoion, and Mongo Store

I have a suite of programs that are all under the same company and I am trying to develop a single login / authentication service that can persist through all of the programs. The idea is very micro-service oriented in which we will have one service to handle authentication and persist it as long as someone is in one of the programs. The issue is I need my other services to be able to access the same cookies across all of the domains and be able to send those cookies to the auth service for session verification. Please correct me if this is not the proper way to set up micro-services with a login/auth service.
For my front end (Angularjs):
service.login = function (obj, callback) {
$http.post(loginService + "login", obj, {
withCredentials: true
}).success(function (data) {
callback(data);
})
.error(function (data, status, headers) {
console.log(status);
});
};
For my server (Node, Express, Mongo):
var options = {
pfx: fs.readFileSync('company.pfx'),
passphrase: 'pass',
ca: [fs.readFileSync('gd1.crt'), fs.readFileSync('gd2.crt'), fs.readFileSync('gd3.crt')],
spdy: {
protocols: ['h2', 'spdy/3.1', 'http/1.1'],
plain: false,
'x-forwarded-for': true,
connection: {
windowSize: 1024 * 1024, // Server's window size
// **optional** if true - server will send 3.1 frames on 3.0 *plain* spdy
autoSpdy31: false
}
}
};
var server = spdy.createServer(options, app);
app.use(helmet());
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use("/static", express.static('static'));
app.use("/logins", express.static('logins'));
app.set('trust proxy', 1) // trust first proxy for production with a proxy server
app.use(session({
resave: false,
saveUninitialized: true,
genid: function (req) {
return uuid.v4() // use UUIDs for session IDs
},
name: "myToken",
secret: 'mysecret',
cookie: { secure: false, maxAge: (45 * 60000) }, // set secure to true when in production
store: new mongoStore({ url: 'mongodb://' + base + 'sessions' })
}));
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);//req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,PATCH');
res.header('Access-Control-Allow-Headers', 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version');
next();
});
Requesting:
app.get('/', function (req, res) {
var sess = req.session, token = req.cookies.myToken;
res.send('Hello World!');
});
To test this I have a virtual machine running on my system with the application deployed and then I am also running my localhost:/ application. From my understanding my cookies should remain the same between the two calls with the same session if I have CORS set up properly. Any help or suggestions?
Have you tried
res.header('Access-Control-Allow-Origin', '*.domain') ?
Basically a wildcard matching any subdomain under your main domain.

Cross domain session authentication with Node.js, Passport, Backbone

I am using Node.js with express server, and passport package for authentication. Client is on same server, different domain built on Backbone.js. The session is created on login request, but if another request comes from client side, I don't manage to access the session.
Node server configuration:
var express = require( 'express' ),
path = require( 'path' ),
mongoose = require( 'mongoose' ),
passport = require('passport'),
cors = require('cors');
app.configure( function() {
app.use(express.cookieParser());
app.use(express.bodyParser());
app.use(express.session({
secret: secret,
key: key,
cookie : {
maxAge: maxAge
}
}));
app.use(passport.initialize());
app.use(passport.session());
app.use( express.methodOverride() );
app.use( app.router );
app.use( express.static(application_root) );
app.use(cors());
});
Logging in and auth check:
app.post('/login', cors(corsOptions), passport.authenticate('login', {
successRedirect : successDirect,
failureRedirect : failureDirect
}));
function requireAuth(req, res, next) {
if(req.session.user) {
next();
}
else if (req.cookies.isAuthenticated) {
next();
} else {
res.redirect(loginUrl);
}
}
On login, the session is created. If I send any requests from the server side (localhost:9999/anymethod), then the session is accessed, responses accordingly. If I try to send a request from client side to the same url, then the session is always 'undefined'.
Example:
app.get('/mymethod', cors(corsOptions), requireAuth, function(request, response) {
return response.send("Done");
});
This method works when accessed from server after logging in, but not when accessed from client side (client is established on same server, different domain).
Added to Backbone.js:
initialize: function() {
this.collection.fetch({reset: true, beforeSend: this.beforeFetch});
},
beforeFetch: function(xhr) {
xhr.withCredentials = true;
},...
Edit: The request coming from client doesn't contain any cookies.
How can I access the session created by passport after logging in, sending a request from client?
I guess cors library does it (i haven't used that library). But if it doesn't then in server side
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Origin', req.headers.origin);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,PATCH');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
next();
});
And in client ajax request
xhrFields: {
withCredentials: true
}

Resources