Express session is undefined when accessing external website - javascript

I'm trying to use express sessions to store user credential information for my website. Unfortunately, while I managed to get the website to work from my local machine, express session is empty during every request from the hosted website.
To make this easier to understand:
server:
Node.JS app
hosted website (plain HTML, javascript)
req.session always empty
local:
local server accessible by localhost.com (hosts was edited to redirect localhost.com to 127.0.0.1)
req.session has the things I set in it
The website files are identical/synced & both connect to the same server.
requests from the website are ajax with default:
$.ajaxSetup({
xhrFields: {
withCredentials: true //for server-side sessions
}
});
server app.js setup:
var express = require('express');
var expsession = require('express-session');
var config = require('./config');
var app = express();
app.set('port', process.env.PORT || 3333);
app.use(require('method-override')());
app.use(require('morgan')('dev'));
app.use(require('body-parser')({ keepExtensions: true}));
app.use(require('cookie-parser')());
app.use(expsession({
secret: 'stufffandthings',
store: new expsession.MemoryStore({reapInterval: 600000})
}));
app.use(function(req, res, next) {
console.log('From: ' + req.get('origin'));
if(config.origins.indexOf(req.get('origin')) > -1){ //if in list of allowed origins
res.header("Access-Control-Allow-Origin", req.get('origin')); //allow them in
console.log('Set access control to allow origin');
}
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, X-Requested-With, Authorization, Content-Length');
res.header('Access-Control-Allow-Credentials', true);
res.header("Cache-Control", "no-cache");
next();
});
config.origins contains my http://localhost.com:3700 & http://hostedwebsite.com:8080. Both the localhost and local website are allowed origins.
Edit:
On the hosted website, if you don't leave the page and keep doing ajax requests the session object remembers you. Huh?

app.use(express.static(path.join(__dirname, '/public')));
Had to be above the express-session middleware declaration. It's a bug with express-session module.

Related

Nodejs local API does not work

I'm doing an university project with NodeJs but I have some trouble in testing it in local.
This is the problem:
I have a GET API "/api/services/names" and the NodeJS server is running on port 8080.
If I test the API with Postmanor by putting the URL in the Chrome bar ("http://localhost:8080/api/services/names") it works fine and I can get my response.
The problem is that if I test it in my local website using fetch() inside this function:
function fetchServicesNames(){
fetch('/api/services/names')
.then(function(response){
return response.json();
})
.then(function(data){
data.map(addServiceLink);
});
}
The Javascript console gives me this error:
Failed to load resource: the server responded with a status of 404 (Not Found)
I noticed that when I hover the console error, it shows the request string "http://localhost/api/services/names" without the port. But I don't think this is the problem because when I deploy the application on the Heroku platform it works fine... the problem is just in localhost (I'm working with a mid 2010 macbook pro with Mac OSX 10.10.2).
Any help is appreciated, thank you in advance.
Edit:
as requested I'm adding here the server code
// server.js for Hypermedia Application project.
// BASE SETUP
//============================================================
// call packages
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(express.static(__dirname + "/public"));
// we use body-parser, so we need to be able to read data either from
// GET and POST:
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// setting the application port to listen
var serverPort = process.env.PORT || 5000;
// --- database connection omitted ---
// API ROUTES
// ================================================================
// first of all: get the Router
var router = express.Router();
/**
* Services names
* /api/services/names - get - get all services ids and names
*/
router.route('/services/names')
.get(function (req, res) {
Service.find({}, 'id name', function (err, services) {
if (err)
res.send(err);
res.json(services);
});
});
// --- Other APIs omitted ---
// REGISTER ROUTES:
// all of our routes will be prefixed with /api
app.use('/api', router);
// START THE SERVER
//===================================================================
app.set("port", serverPort);
app.listen(serverPort, function() {
console.log(`Your app is ready at port ${serverPort}`);
});
at your server page you add
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();
});
before your API's
it might help you for CORS
Dear i suggest you to write total Path like
http://localhost:<your port number>/api/services/names
inside fetch()and u check once
I too tried and i got Success
Hi try modifying the line like fetch('http://'+window.location.host+':8080/api/services/...)

Cookies for Domain and its Subdomains in Node/ExpressJS

So what im attempting to do is to set a cookie on domain.com which is available to all subdomains *.domain.com. Im currently using Express 4.x and NodeJS.
At the moment I can set and get any Cookies on the main domain in my case its testing on a local environment via lvh.me:3000 (allowing for local subdomains)
This is bascially what my Express.js App looks like:
// Require all files (express,http,express-session,cookie-parser...)
var api = express()
// Cookie Parser
api.use(cookieParser());
api.use(session({
secret: 'yoursecret',
cookie: {
path: '/',
domain: '.lvh.me:3000',
maxAge: 1000 * 60 * 24, // 24 hours
},
resave: true,
saveUninitialized: true
}));
// CORS
api.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');
res.header('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
next()
})
// View Engine
api.set('views', './api/views');
api.set('view engine', 'ejs');
api.disable('x-powered-by');
// Stylus
function compile(str, path) {
return stylus(str).set('filename', path);
}
api.use(stylus.middleware({
src: './app',
compile: compile
}));
// Serving Static Content
api.use(express.static('./app'));
// All Routes
require('../api/routes/test.server.routes.js')(api);
// Router
api.get('*', function(req, res) {
//res.cookie('remember', 1, { domain : "lvh.me:3000" });
res.render('index'); // Get all requests to Index. Angular takes over routing.
});
// Return Application
return api;
Cookies are set via Cookie Parser res.cookie('user', 'bobby'); which seem to be fine for going to lvh.me:3000/anything but for boddy.lvh:3000/anything the Cookies are empty.
Am I missing anything here, I thought Cookies would be available across all subdomains? I have read a few Articles/Posts on Stack Overflow but they all seem rather outdated. Any guidance or help is greatly appreciated.
On a side note if i set a cookie within express file it will be available through out the application. For Example:
// Router
api.get('*', function(req, res) {
res.cookie('user', 'jim'); // This can be accessed
res.render('index');
// Get all requests to Index. Angular takes over routing.
});
Any reason why? - This is in the most part because its being set on any/every view. So it still leaves me with the original question.
While setting cookie if your domain name mydomain.com it is not accessible by subdomains. You have to put leading dot (e.g .mydomain.com). In that case cookie will be shared across subdomains

NodeJs, ExpressJs, PassportJs, isAuthenticated returns null even though CORS is enabled

I've got an app which has a front end/website serving logic on server A in Express, and backend logic with POST endpoints written in Express again on server B.
I've got withCredentials set to true on all my AngularJs methods which call the backend.
In the backend I've got this
var cors = require('cors');
var whitelist = 'http://serverA.com';
var corsOptions = {
origin: whitelist,
methods: ['GET', 'POST', 'OPTIONS', 'PUT'],
allowedHeaders: ['Content-Type', 'Authorization'],
exposedHeaders: ['Content-Range', 'X-Content-Range'],
credentials: true
};
app.options('*', cors(corsOptions));
app.use(cors(corsOptions));
I try logging in from the client side and the login succeeds and redirects to the correct page but the isAuthenticated method on Passport returns false and it redirects me back to the login page.
What do you think the reason is that the session is not being stored on the client side. The cookie value seems to be set correctly (Chrome dev tools.)
Here is some client code. This is a middleware method used to protect pages for authenticated users.
function authenticate_func(req, res, next) {
//return next();
if (req.isAuthenticated())
{
console.log("Login Successful");
return next();
}
console.log('Login Unsuccessful');
res.redirect('/');
};
Here are middlewares I'm using and the order they are used in.
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
require('/local_strategy')(passport, my_sql);
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
Am I missing anything?

CORS with socket.io

I'm having trouble with CORS on a node.js app using express.io. I'm hosting the socket.io client js remotely since this needs to works as a remote app.
<script src="resources/js/socket.io.min.js"></script>
It's hosted on OpenShift
server.js:
var ipaddr = process.env.OPENSHIFT_NODEJS_IP || "localhost";
var port = process.env.OPENSHIFT_NODEJS_PORT || 8080;
var express = require('express.io');
// magical express.io
var app = express();
// Enables CORS
var enableCORS = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, *');
// intercept OPTIONS method
if ('OPTIONS' == req.method) {
res.send(200);
} else {
next();
};
};
app.configure(function() {
// enable CORS!
app.use(enableCORS);
});
app.http().io();
app.io.set('origins', '*:*');
//.... other stuff
app.listen(port, ipaddr);
Then on the client:
var socket = io.connect(window.chat_url);
When I run the client from localhost:8888 with the server localhost:8080 socket.io works fine.
When I run the client from localhost:8888 and the server on odechat-latestsightings.rhcloud.com then socket.io times out:
Firebug:
GET http://nodechat-latestsightings.rhcloud.com:8888/socket.io/1/?t=1391542144169 1m 16s
The other routes work fine:
GET http://nodechat-latestsightings.rhcloud.com/rooms 200 OK 664ms
I just can't figure this out
Also, if your server is on openshift then you should bind to port: 8000 to use websockets since that is the port openshift's nginx reverse proxy has public access.
You can read more from here: https://developers.openshift.com/en/managing-port-binding-routing.html

Trouble using express.session with https

I have to use authentication and then create a session for this i have a HTTPS static website running on expressjs
Code :
app.js:
//created the https server
var express = require('express');
var https = require('https');
var http = require('http');
var fs = require('fs');
var mongo = require('mongodb');
var monk = require('monk');
var db = monk('localhost:27017/svgtest1');
// This line is from the Node.js HTTPS documentation.
var options = {
key: fs.readFileSync('privatekey.pem'),
cert: fs.readFileSync('certificate.pem')
};
// Create a service (the app object is just a callback).
var app = express();
app.use(express.static(__dirname + '/public'));
app.use(express.cookieParser());
app.use(express.session({cookie: { httpOnly: false , maxAge: 24*60*60*1000}, secret: '1234567890QWERT'}));
app.use(express.urlencoded());
app.use(express.json());
// middle ware to check auth
function checkAuth(req, res, next) {
if (!req.session.user_id) {
res.send('You are not authorized to view this page');
} else {
next();
}
}
app.get('/', function(req, res) {
console.log('First page called');
res.redirect('xyz.html');
res.end();
});
app.post('/login', function(req, res) {
console.log('login called');
var usrfield = req.body.usrfield;
var passfield = req.body.passfield;
// Play with the username and password
if (usrfield == 'xxx' && passfield == 'xxx') {
req.session.user_id = '123';
res.redirect('abc.html');
} else {
res.send('Bad user/pass');
}
console.log(usrfield);
console.log(passfield);
res.end();
});
// Create an HTTPS service.
https.createServer(options, app).listen(8888);
When I visits https://localhost:8888 it continuously loads the page and does not redirect to xyz.html where i have to enter the credentials to authenticate the user ?
When I comment out
app.use(express.session({cookie: { httpOnly: false , maxAge: 24*60*60*1000}, secret: '1234567890QWERT'}));
Then the page loads correctly but when i post the form to /login then it says req.session cannot be written. For this i know because i have comment out the express.session, but the strange thing is that connect.sid cookie is created. Why ?
I am confused regarding question 1 and 2.
I tried your example, and it works for me. Are you sure you're using the https protocol in the browser? By default, a browser will try to connect with HTTP protocol unless you redirect to HTTP. With your set, navigating to this URL will just spin:
http://localhost:8888
However, if you navigate to this URL:
https://localhost:8888
It will work as expected. Most servers that use HTTPS automatically redirect to an HTTPS connection if the user came in over HTTP, but you still have to have two servers: one accepting HTTP request, and the other accepting HTTPS requests. For example, you could do this:
// create an HTTPS service
https.createServer(options, app).listen(443);
// create HTTP service to redirect to HTTPS
http.createServer(express().use(function(req,res){
res.redirect('https://localhost:443' + req.url);
})).listen(8888);
Note that if you use ports below 1024 (such as 443, which is common for HTTPS), you'll probably have to have elevated privileges depending on your server set up. In OSX/Linux, you would just do sudo node app.js. Of course you don't have to run on port 443: you could have your HTTPS server run on 8887 and your HTTP redirect server run on 8888.

Categories