Session management in Nodejs - javascript

I am beginner of NodeJS.And just started a simple project where I need a session management concept. So How to manage the session in NodeJS application.
In my project there is two file:- app.js and routes.js.
So where we add the session and how to add ??
app.js file :-
var express = require('express'),
app = express(),
path = require('path');
app.set('views', path.join(__dirname , 'views'));
app.engine('html', require('hogan-express'));
app.set('view engine', 'html');
app.use(express.static(path.join(__dirname,'public')));
require('./routes/routes.js')(express,app);
app.listen (3000 , function(){
console.log("working on the Port 3000");
});
and routes.js file :-
module.exports = function(express, app){
var router = express.Router();
router.get('/', function(req , res , next){
res.render('index',{title: 'Welcome'});
});
}

For the session management we need a middleware 'cookie-parser'.Previously it is the part of express but after express 4.0 and later it is a separate module.
So to access the cookie parser we need to install in our project as :
npm install cookie-parser --save
Then add this into your app.js file as :
var cookieParser = require('cookie-parser');
app.use(cookieParser());
Then we reqired session module. So first of all install the session module by :
npm install express-session --save
Then to enable the session. we add below code in app.js file.
app.use(session({secret:config.sessionSecret, saveUninitialized : true, resave : true}));
Then come to the routes.js file :-
Let us suppose there is a session variable favColor. Now using session set the color and get in the other page. the code is look like :-
router.get('/setColor', function(req , res , next){
req.session.favColor = 'Red';
res.send('Setting favourite color ...!');
});
router.get('/getColor', function(req , res , next){
res.send('Favourite Color : ' + (req.session.favColor == undefined?"NOT FOUND":req.session.favColor));
});
This is all about the session management.We can also learn more about the session :- This Reference

I dont suggest you try to build your own session and use https://github.com/expressjs/session instead which works with express well.

An update on 2019, using express-session 1.15.6 (From 1.5 there's no need to use cookie-parser, session can read and write the cookie directly.)
In app.js:
const app = express()
const session = require('express-session');
const options = {
name: 'foo', // Default is connect.sid
store: this.store, // Default is memoryStore, which is for dev only. Setup redis or memcached for prod
secret: 'bar', // Required, used to sign session id cookie
saveUninitialized: true, // Forces a session that is "uninitialized" to be saved to the store
resave: false, //Forces the session to be saved back to the session store
rolling: true //Force a session identifier cookie to be set on every response
};
// Session method will return a middleware function.
const middleware = session(options);
// Now we can make use of session in all the requests
app.use(middleware)
In routes.js or in any handler file created for specific route:
handler1(req, res, next) {
req.session.someField = 'foo';
// Use save method to update the store immediately, if there's other AJAX call pending.
req.session.save();
}
handler2(req, res, next) {
console.log(req.session.someField);
}
handler3(req, res, next) {
// we use delete operator here.
delete req.session.someField;
}

Related

stuck at building process while hosting on Vercel

I'm using node.js as a server-side to store the API respond, the app is working without any issue but recently I have been trying to host it on Vercel so I ran into many issue, the project get stuck at the building process...
the building output :
Building output
My server.js code :
// Setup empty JS object to act as endpoint for all routes
projectData = {};
// Require Express to run server and routes
const express = require('express');
// Start up an instance of app
const app = express();
/* Middleware*/
//Here we are configuring express to use body-parser as middle-ware.
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Cors for cross origin allowance
const Cors = require('cors');
app.use(Cors());
// Initialize the main project folder
app.use(express.static('website'));
// Setup Server
const port = 8000;
const Server = app.listen(port , run);
function run() {
console.log(`hello there :D`);
console.log(`here is ${port} ready to go`);
}
//GET method
app.get('/all', function(req,res){
res.send(projectData)
console.log(projectData);
})
//POST method
app.post("/addUserComment", function(req,res){
projectData = {
temp : req.body.temp,
date : req.body.date,
feeling : req.body.feeling,
}
console.log(projectData);
res.send(projectData);
})
My working directory and build settings :
Working directory
Build settings
note: server.js is my server-side file, and my website folder includes my app.js file and my HTML, CSS files, also i did try to add Vercel.json file but i couldn't understand how to use it, so if you gonna add this file in your answer please explain how and why
I think you need to remove the build command, because it's now trying to run the server.js file instead of making a build.

POST http://127.0.0.1:5500/add 405 (Method Not Allowed)

Could you help me solve this error? It seems that I can not connect between server.js and app.js.
What I want to do is: display the result of the postData('/add', {answer:42}); and postData('/addMovie', {movie:'the matrix', score:5}); in the console.
Thank you for your help in advance.
error image
server.js
// Setup empty JS object to act as endpoint for all routes
projectData = {};
// Require Express to run server and routes
const express = require('express');//add
// Start up an instance of app
const app = express();//add
/* Dependencies */
const bodyParser = require('body-parser') //add
/* Middleware*/
//Here we are configuring express to use body-parser as middle-ware.
//we can connect the other packages we have installed on the command line to our app in our code with the .use() method
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Cors for cross origin allowance
const cors = require('cors');//add
app.use(cors());//add
// Initialize the main project folder
app.use(express.static('website'));
////////////////////creating a local server
const port = 5500;//add
// Setup Server
//////////////////////add
const server = app.listen(port, listening);
function listening(){
// console.log(server);
console.log(`running on localhost: ${port}`);
};
app.get('/all', function (req, res) {
res.send(projectData)
})
// POST route
const data = []
app.post('/add', callBack);
function callBack(req,res){
res.send('POST received');
console.log(data)
}
const movieData = []
app.post('/addMovie', addMovie )
function addMovie (req, res){
movieData.push(req.body)
console.log(movieData);
}
app.js
app.js
[Addition]
Thank you for your feedback!!
I changed the port in server.js, but nothing changed.
port5500
The issue was resolved.
// when using local server ( ≒ server.js in this case)
postData('/add', {answer:42});
postData('/addMovie', {movie:'the matrix', score:5});
// when using live server
postData('http://localhost:5500/add', {answer:42});
postData('http://localhost:5500/addMovie', {movie:'the matrix', score:5});
You need to add an "allow" in the header field to support this or explicitly allow it in your webserver configuration
A lot of the time, this is set up in the configuration of your .htaccess or nginx.conf file (depending on the webserver). It will commonly be found in your RewriteRule section. You can look for a "R=405" flag there.

How to structure my project folder when building a secured NodeJs REST API

I am building a REST API using NodeJS and Express, powered by a MongoDB database.
I've been struggling for days now trying to get the right folder structure nailed down. So far, I can connect to my database and add new users without an API, but by simply doing GET, POST, etc. requests. I've seen several tutorials online on how to build API using node, but none of them have a more standardized way for setting their folder structure. And that is the reason why I am having such a hard time making it work given my current folder structure.
Here is my Folder Structure
app
---models
------user.js
---api.js
---routes.js
config
---auth.js
---database.js
---passport.js
public
views
package.json
server.js
Server.js
// server.js
// set up ======================================================================
// get all the tools we need
var express = require('express');
var app = express();
var port = process.env.PORT || 2016;
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');
var configDB = require('./config/database.js');
// configuration ===============================================================
mongoose.connect(configDB.url); // connect to our database
require('./config/passport')(passport); // pass passport for configuration
app.configure(function() {
// set up our express application
app.use(express.logger('dev')); // log every request to the console
app.use(express.cookieParser()); // read cookies (needed for auth)
app.use(express.bodyParser.json()); // get information from html forms
app.use(bodyParser.urlencoded({ extended: true }));
app.set('views', path.join(__dirname + '/views'));
app.set('view engine', 'ejs'); // set up ejs for templating
// set the static files location /public/img will be /img for users
app.use(express.static(__dirname + '/public'));
// required for passport
app.use(express.session({ secret: 'xxxxxxxxx' })); // 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
});
// routes ======================================================================
// require('./app/routes')(app, passport); // load our routes and pass in our app and fully configured passport
// require('./app/api')(api, passport);
app.use('/', require('./app/routes')(app, passport));
app.use('/api', require('./app/api')(api, passport));
// error handlers
// Catch unauthorised errors
app.use(function (err, req, res, next) {
if (err.name === 'UnauthorizedError') {
res.status(401);
res.json({"message" : err.name + ": " + err.message});
}
next();
});
// launch ======================================================================
app.listen(port);
console.log('Live on port ' + port);
api.js
var User = require('./models/user');
var express = require('express');
var apiRoutes = express.Router();
app.use('/api', apiRoutes);
module.exports = function(apiRoutes, passport){
apiRoutes.get('/testapi', function (req,res) {
res.json({SecretData: 'abc123'});
});
}
Every time I hit the endpoint /testapi I get the error "Cannot GET /testapi"
I think my main issue is how to organize my files and folder properly and import/require them the right way. Can anyone help me figure this out?
Server.js
on this line app.use('/api', require('./app/api')(api, passport));
Here you are telling Express to use ./app/api as an middleware by passing "api" and "passport" as arguments.
where you have defined api variable ?
Lets assume its a typo.. in that case from "app/api.js" you are exporting a function and you trying to execute it in server.js app.use('/api', require('./app/api')(api, passport)); which returns undefined.
Express will be expecting a function as middleware not a return value from function.
app/api.js
on line 4 you have app.use('/api', apiRoutes); which doesn't make any sense, because api.js has no idea about "app".
Cleanup your server.js and api.js and try again
This tutorial might help Node with Express

typeError when passing in objects to require() for passport

I get typeError: object is not a function
when I run:
node server.js
for the following line of code
require('./app/routes.js')(app, passport);
from the following code for my server.js file:
// server.js
// set up ======================================================================
// get all the tools we need
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');
var morgan = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var configDB = require('./config/database.js');
// configuration ================================================================
mongoose.connect(configDB.url); // connect to our database
// require('./config/passport')(passport); // pass passport for configuration
// set up our express application
app.use(morgan('dev')); // log every request to the console
app.use(cookieParser()); // read cookies (needed for auth)
app.use(bodyParser.json()); // get info from html forms
app.use(bodyParser.urlencoded({ extended: true}));
app.set('view engine', 'ejs'); // set up ejs for templating
// requirements for passport:
app.use(session({ secret: 'ilovescotchscotchyscotchscotch'}));
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
// routes ========================================================================
require('./app/routes.js')(app, passport); // load our routes and pass in our app and fully configured passport
// launch =======================================================================
app.listen(port);
console.log('The magic happens on port ' + port);
not entirely sure why this is happening...
I was following this tutorial btw: https://scotch.io/tutorials/easy-node-authentication-setup-and-local
Thanks!
Based on your comments: this post does a pretty good job of explaining how require works in nodeJS (it's not a Javascript thing). Basically every file that can be required is generally expected to export something that the requiring file can assign to a variable (e.g. var someVar = require('someFile');). IF the exported value is a function then you can immediately invoke it before assigning to that variable (e.g. var someVar = require('someFile')(params);). For your error it appears that the file ./app/routes.js is not exporting a function.
FILE: ./app/routes.js
// some code that does cool stuff
// ...
// Time to expose whatever we want to the requiring file
module.exports = someObject; // Or value, function, etc.
FILE: main.js
// we want cool stuff from routes.js
var coolStuff = require('./app/routes.js');
// someObject from ./app/routes.js is now assigned to coolStuff
coolStuff(); // ERROR: object is not a function
console.log(typeof coolStuff) // "object"

Cannot access req.session variables in Express/NodeJS

I've seen many variations of this question, but none seemed to solve my issue. I'm trying to set up a Node.js server using Express. Here is my server configuration:
var express = require('express'),
RedisStore = require('connect-redis')(express);
var app = express();
app.use(express.urlencoded());
app.use(express.json());
app.use(express.cookieParser());
app.use(express.session({
store: new RedisStore(),
secret: APP_SECRET
}));
// Initialize redis connection
var client = redis.createClient();
client.on('connect', function() {
console.log('Connected to Redis server')
})
client.on('error', function (err) {
console.log('Error ' + err);
});
// Enable cross-origin resource sharing
app.all('*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'X-Requested-With');
next();
});
var api = require('./controllers/api.js');
app.post('/login', api.login);
app.get('/auth', api.auth);
app.listen(3000);
And here are some simple routes:
exports.login = function(req, res) {
var user = new User(req.username, req.password);
req.session.user = user;
console.log(req.session.user); //works
res.json({user:user});
}
exports.auth = function(req, res) {
console.log(req.session.user); //doesn't work
res.json(req.session.user);
}
So in my login route, I can print the session variable as expected. But if I visit the auth route after visiting the login route, the session variable is undefined. How can I get Express sessions to work?
In a typical web application, the credentials used to authenticate a user will only be transmitted during the login request. If authentication succeeds, a session will be established and maintained via a cookie set in the user's browser.
Each subsequent request will not contain credentials or all user data, but rather the unique cookie that identifies the session. In order to support login sessions, You have to serialize and deserialize user instances to and from the session in every request.
In your case, you have assigned req.session.user = user; only in /login request. It will not be available for further requests(/auth).
You have to get user information in /auth request too by session id. (Or) Better you can use passport for authentication.
I think maybe your redis client is not connecting well, try something like this and be sure to start the redis service
sudo service redis-server start
or the way you are calling The RedisStore variable look at the example
example:
var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');
var session = require('express-session');
var RedisStore = require('connect-redis')(session);
app.set('port',process.env.PORT || 3000);
app.use(cookieParser());
app.use(session({
resave: true,
saveUninitialized: true,
store: new RedisStore({
host: 'localhost',
port: 6379
}),
secret: 'some string/hash secret'
}));
var counter=0;
app.get('/', function(request, response){
//adding some value to request.session
counter = counter+1;
request.session.color = {'anyValue': counter};
//
console.log('Session ID: ', request.sessionID);
console.log('Session: ', request.session);
response.send('some text counter: '+request.session.color['anyValue']);
});
app.listen(app.get('port'));
The currently accepted answer didn't realize that express.session already handles cookie based sessions with the req.session object. I tried a trimmed down version of yours not using redis and it worked. Looking at the connect-redis docs it looks like you need to pass a session to connect-redis. You are currently passing it express. I believe changing that will fix your problem.
P.S. I would update your node/express versions as current versions of express no longer have the built in middleware along with other improvements.
Newer versions of express:
var session = require('express-session');
var cookieParser = require('cookie-parser');
var json = require('express-json');
var bodyParser = require('body-parser')
Rather than:
express.session
express.cookieParser
express.json
express.bodyParser

Categories