I could send messages before, but I shared passport's sessions with express and socket.io using redis by following this tutorial http://www.scotthasbrouck.com/blog/2016/3/18/passportjs-express-session-with-sockeio and now I can no longer send any chat messages.
Also, in my routes req.isAuthenticated() always returns false but I didn't have this problem before.
This is my server.js.
// server.js
// set up ======================================================================
// get all the tools we need
var express = require('express');
var app = express();
var server = require('http').Server(app);
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 configDB = require('./config/database.js');
var http = require('http').Server(app);
var io = require('socket.io')(http);
var passportSocketIo = require('passport.socketio');
var session = require('express-session');
var chatdb = require('./app/models/chat.js');
var user = require('./app/models/user.js');
var redis = require('redis');
var client = redis.createClient();
var RedisStore = require('connect-redis')(session);
// 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()); // get information from html forms
app.set('view engine', 'ejs'); // set up ejs for templating
var sessionStore = new RedisStore({ host: 'localhost', port: 6379, client: client, ttl: 260 });
// required for passport
app.use(session({
secret: 'secret',
store: sessionStore,
resave: true,
saveUninitialized: true,
cookie: {
secure: process.env.ENVIRONMENT !== 'development' && process.env.ENVIRONMENT !== 'test',
maxAge: 2419200000
},
}));
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash()); // use connect-flash for flash messages stored in session
app.use(express.static(__dirname + '/views'));
app.use(express.static(__dirname + '/public'));
io.use(passportSocketIo.authorize({
key: 'connect.sid',
secret: 'secret',
store: sessionStore,
passport: passport,
cookieParser: cookieParser,
}));
var eventSocket = io.of('/chat');
// socket.io
io.on('connection', function (socket) {
console.log('a user connected');
socket.on('chat message', function(msg){
var name = "efe";
chatdb.saveMsg({name: name, msg: msg}, function(err){
if(err) throw err;
io.emit('chat message', msg);
});
if (socket.request.user && socket.request.user.logged_in) {
console.log(socket.request.user);
}
});
});
// routes ======================================================================
require('./app/routes.js')(app, passport); // load our routes and pass in our app and fully configured passport
// launch ======================================================================
http.listen(port);
console.log('The magic happens on port ' + port);
I had the same problem. I tried to implement passport.socketio like you but I solved my problem without it.
Here is my middleware :
// Express session middleware
var sessionMiddleware = session({ secret: 'secret-key', resave: true, saveUninitialized: true });
// Send Express sessionMiddleware through socket.io
io.use(function(socket, next){
// Params: request object, response object and callback.
sessionMiddleware(socket.request, {}, next);
});
The second parameter (response object) of sessionMiddleware function is empty. This will renders the session read-only.
And Here is how I use passport js session variable to get user informations :
io.on("connection", function(socket){
socket.on('chat message', function(msg){
var passport = socket.request.session.passport; // Get the passport variable
// Check if passport session exists
if (passport && typeof passport !== 'undefined'){
var userSession = passport.user; // Get the user session
// Build JSON with user session data
var message = {
message : msg,
name : userSession.name,
avatar : userSession.avatar
};
io.emit('chat message', message); // Emit my socket
}
});
});
Hope it help.
This was how i was able to solve it.
var express = require('express');
var app = express();
var server = require('http').Server(app);
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');
// Add connect-mongo to project - npm install connect-mongo
var MongoStore = require('connect-mongo')(session);
var configDB = require('./config/database.js');
var http = require('http').Server(app);
var io = require('socket.io')(http);
var chatdb = require('./app/models/chat.js');
// configuration ===============================================================
// NOTE: This might need to be put into a callback/promise inside an initialize function
var db = 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()); // get information from html forms
app.set('view engine', 'ejs'); // set up ejs for templating
var mongoStore = new MongoStore({
mongooseConnection: db.connection,
});
app.use(session({
secret: 'secret',
clear_interval: 900,
cookie: { maxAge: 2 * 60 * 60 * 1000 },
store: mongoStore,
}));
// required for passport
app.use(session({ secret: 'secret' })); // 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
app.use(express.static(__dirname + '/views'));
app.use(express.static(__dirname + '/public'));
// Intercept Socket.io's handshake request
io.use(function(socket, next) {
// Use the 'cookie-parser' module to parse the request cookies
cookieParser('secret')(socket.request, {}, function(err) {
// Get the session id from the request cookies
var sessionId = socket.request.signedCookies ? socket.request.signedCookies['connect.sid'] : undefined;
if (!sessionId) return next(new Error('sessionId was not found in socket.request'), false);
// Use the mongoStorage instance to get the Express session information
mongoStore.get(sessionId, function(err, session) {
if (err) return next(err, false);
if (!session) return next(new Error('session was not found for ' + sessionId), false);
// Set the Socket.io session information
socket.request.session = session;
// Use Passport to populate the user details
passport.initialize()(socket.request, {}, function() {
passport.session()(socket.request, {}, function() {
// This will prohibit non-authenticated users from connecting to your
// SocketIO server.
if (socket.request.user) {
next(null, true);
} else {
next(new Error('User is not authenticated'), false);
}
});
});
});
});
});
// socket.io
io.on('connection', function(socket) {
socket.on('chat message', function(msg) {
console.log(socket.request.user.facebook.name || socket.request.user.local.email);
var name = socket.request.user.facebook.name || socket.request.user.local.email;
chatdb.saveMsg({
name: name,
msg: msg
}, function(err) {
if (err) throw err;
io.emit('chat message', msg);
});
});
socket.on('disconnect', function() {
console.log('user disconnected');
});
});
// routes ======================================================================
require('./app/routes.js')(app, passport); // load our routes and pass in our app and fully configured passport
// launch ======================================================================
http.listen(port);
console.log('The magic happens on port ' + port);
Related
I have a little probleme with my Nodejs application. I want protect my forms with csrf token, but it's not work. I have an error like
ForbiddenError: invalid csrf token
POST http://localhost:3000/addfile 403 (Forbidden)
I want to create csrf token for all requests. I can create csrf token, but if I use the methods like : POST/PUT or DELETE it's not work.
I don't understand why I have this error. Thanks for yours answers.
app.js
var express = require("express");
var bodyParser = require("body-parser");
var mongoose = require('mongoose');
var fs = require('fs');
var path = require('path');
var logger = require('morgan');
var expressValidator = require('express-validator');
var csrf = require('csurf');
var session = require('express-session');
var passport = require('passport');
var PORT = 3000;
var config = require('./config/database');
var app = express();
// Connexion to MongoDb
mongoose.connect(config.database, function(err) {
if(err){
console.log(err);
}
else{
console.log("Connected to MongoDb");
}
});
// Middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(expressValidator());
app.set('views',path.join(__dirname, ''));
app.set('view engine','pug');
app.use(express.static(path.join(__dirname, '')));
app.disable('x-powered-by');
app.use(session({
name: 'SESS_ID',
secret: config.secret,
resave: true,
saveUninitialized: true,
cookie: {
secure: false,
httpOnly: true,
maxAge: 5*60*1000 } //15minutes*60sec*1000ms
//cookie: {secure: false} //https = true, http=false
}));
app.use(csrf());
app.use(passport.initialize());
app.use(passport.session());
require('./config/passport')(passport);
app.use(function(req, res, next) {
res.locals._csrf = req.csrfToken();
next();
});
app.use('/', require('./routes/fileRoutes'));
app.use('/', require('./routes/authRoutes'));
app.listen(PORT,function(){
console.log("Server started at the port " + PORT);
});
routes/fileRoutes.js
app.get('/',function(req,res){
File.find(function(err, files){
res.render('views/layout',{files:files});
});
});
app.post('/addfile',upload,function(req,res){
if (req.fileValidationError) {
return res.end("Error PDF");
} else {
for (var i = 0; i < req.files.length; i++)
{
var files = new File ();
files.fieldname= req.files[i].fieldname;
files.originalname= req.files[i].originalname;
files.encoding= req.files[i].encodin;
files.path= req.files[i].path;
files.save(function(err, data){
});
}
res.redirect('/');
}
});
layout.pug
form#uploadForm(enctype='multipart/form-data', action='/addfile', method='post')
input(type='hidden', name='_csrf', value=_csrf)
input(type='file', name='userPhoto', multiple='')
input(type='submit', value='Upload Image', name='submit')
input#random(type='text', name='random')
I see you have:
input(type='hidden', name='_csrf', value=_csrf)
What is the value for if you console.log(_csrf)? I also noticed you didn't put that one in quotes.
I've checked the other related questions and can't pinpoint what's causing the issue (don't have a lot of experience here). I'm trying to launch this app locally basically with its default settings (other than some Twilio keys), have the dependencies installed, mongo is running, but localhost:5000 returns CANNOT GET /.
> node server.js
listening on port 5000
server.js:
// modules =================================================
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var http = require('http').Server(app);
var io = require('socket.io')(http); //real-time chat
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var cookieParser = require('cookie-parser');
// configuration ===========================================
// public folder for images, css,...
app.use(express.static(__dirname + '/public'))
// config files
// database
var db = require('./config/db');
// models
var User = require('./app/models/users');
var Message = require('./app/models/messages');
//parsing
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); //for parsing url encoded
//AUTH========================================================
app.use(cookieParser());
app.use(require('express-session')({
secret: 'white rabbit',
resave: false,
saveUninitialized: false
}));
app.use(passport.initialize());
app.use(passport.session());
// passport config
var Member = require('./app/models/members');
passport.use(new LocalStrategy(Member.authenticate()));
passport.serializeUser(Member.serializeUser());
passport.deserializeUser(Member.deserializeUser());
// view engine ejs
app.set('view engine', 'ejs');
//chat namespace
var chatSocket = io.of('/chat')
//routes
require('./app/routes/routes')(app, chatSocket);
//Heroku port
app.set('port', (process.env.PORT || 5000));
//ADMIN====================================================
//create an admin account if none exists
var admin = Member.find({admin: true}, function(err, admins) {
if (err) throw err
else if(admins.length == 0){
//no admin. create default account
Member.register(new Member({username: "admin", admin: true}), "mypassword", function(err, admin){
if(err) throw err;
console.log('Defaut account created successfully!');
})
}
else{
//at least one admin exists
console.log('Admin account already exists : ');
console.log(admins)
}
});
//START ===================================================
http.listen(app.get('port'), function(){
console.log('listening on port ' + app.get('port'));
});
//SOCKET ==================================================
require('./app/controllers/socket')(chatSocket, User, Message);
You didn't set any route that points to /
Point to that route by using app.get
app.get("/", function(req, res) {
res.send("home");
});
There are available routes in /app/routes/*.js files of the repository you cloned.
I want to use
req.user.id
inside
io.sockets.on('connection', module.exports = function(socket){}
so I tried to using this line
socket.request.client.user
like that on my
io.socket
io.sockets.on('connection', module.exports = function(socket,client,req){
connections.push(socket);
app.use(session({ secret: 'keyboard cat',resave: true, saveUninitialized:true})); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
console.log('connected: %s socket connected -session',socket.request.client.user ,connections.length);
but i get undefined on console
that's are my full code full code
var authController = require('./app/controllers/authcontroller.js');
var auth = require('./app/routes/auth.js');
var express = require('express')
var app = express()
var passport = require('passport')
var session = require('express-session')
var bodyParser = require('body-parser')
var env = require('dotenv').load()
var exphbs = require('express-handlebars')
app.use(session({secret: 'ssshhhhh'}));
app.use(passport.initialize())
app.use(passport.session())
var server = require('http').createServer(app);
var io = require('socket.io').listen(server);
var mysql = require('mysql');
var connection = mysql.createConnection({
host: 'localhost',
database: 'db_users',
user: 'root',
password: '',
});
users = [];
connections = [];
app.use('/cssFiles', express.static('/opt/lampp/htdocs/x/regtest/using-passport-with-sequelize-and-mysql-master/app/routes/assets'));
//For BodyParser
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
// For Passport
app.use(session({ secret: 'keyboard cat',resave: true, saveUninitialized:true})); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
//passport.authenticate('local-signin');
//For Handlebars
app.set('views', './app/views')
app.engine('hbs', exphbs({extname: '.hbs'}));
app.set('view engine', '.hbs');
app.get('/', function(req, res){
console.log('idddddd',req.sessionID);
res.send('Welcome to Passport with Sequelize');
});
//Models
var models = require("./app/models");
//Routes
var authRoute = require('./app/routes/auth.js')(app,passport);
//load passport strategies
require('./app/config/passport/passport.js')(passport,models.user);
//Sync Database
models.sequelize.sync().then(function(){
console.log('Nice! Database looks fine')
}).catch(function(err){
console.log(err,"Something went wrong with the Database Update!")
});
server.listen(process.env.PORT || 5000, function(err){
if(!err)
console.log("Site is live"); else console.log(err)
});
console.log('Server running...');
app.get('/', function(req, res){
res.sendFile('/opt/lampp/htdocs/x/regtest/using-passport-with-sequelize-and-mysql-master/app/routes/page.html');
});
//connection.connect();
io.sockets.on('connection', module.exports = function(socket,client,req){
//con
connections.push(socket);
//app.use(session);
app.use(session({ secret: 'keyboard cat',resave: true, saveUninitialized:true})); // session secret
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
console.log('connected: %s socket connected session',socket.request.client.user ,connections.length);
req.user is only available in express middleware unfortunately. You'll have to use something like https://www.npmjs.com/package/passport.socketio if you want to access passports user info.
You will have to use some sort of persistent store as well such as redis or mongodb
I am trying to build a chat room, where I pass user session from passport + express to socket.io. but now I cannot emit any messages. io.on does not seem to connect.
I don't get any error messages
Here is my code
var express = require('express');
var app = express();
var server = require('http').Server(app);
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');
// Add connect-mongo to project - npm install connect-mongo
var MongoStore = require('connect-mongo')(session);
var configDB = require('./config/database.js');
var http = require('http').Server(app);
var io = require('socket.io')(http);
var chatdb = require('./app/models/chat.js');
// configuration ===============================================================
// NOTE: This might need to be put into a callback/promise inside an initialize function
var db = 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()); // get information from html forms
app.set('view engine', 'ejs'); // set up ejs for templating
// required for passport
app.use(session({ secret: 'secret' })); // 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
app.use(express.static(__dirname + '/views'));
app.use(express.static(__dirname + '/public'));
// Create a MongoDB storage object
var mongoStore = new MongoStore({
mongooseConnection: db.connection,
collection: configDB.sessionCollection,
});
// Intercept Socket.io's handshake request
io.use(function (socket, next) {
// Use the 'cookie-parser' module to parse the request cookies
cookieParser('secret')(socket.request, {}, function (err) {
// Get the session id from the request cookies
var sessionId = socket.request.signedCookies ? socket.request.signedCookies['session-key'] : undefined;
if (!sessionId) return next(new Error('sessionId was not found in socket.request'), false);
// Use the mongoStorage instance to get the Express session information
mongoStore.get(sessionId, function (err, session) {
if (err) return next(err, false);
if (!session) return next(new Error('session was not found for ' + sessionId), false);
// Set the Socket.io session information
socket.request.session = session;
console.log(session);
console.log(socket.request.user);
// Use Passport to populate the user details
passport.initialize()(socket.request, {}, function () {
passport.session()(socket.request, {}, function () {
// This will prohibit non-authenticated users from connecting to your
// SocketIO server.
if (socket.request.user) {
next(null, true);
} else {
next(new Error('User is not authenticated'), false);
}
});
});
});
});
});
// socket.io
io.on('connection', function (socket) {
console.log('a user connected');
socket.on('chat message', function(msg){
console.log('a use connected');
var name = "efe";
chatdb.saveMsg({name: name, msg: msg}, function(err){
if(err) throw err;
io.emit('chat message', msg);
});
});
socket.on('disconnect', function () {
console.log('user disconnected');
});
});
// routes ======================================================================
require('./app/routes.js')(app, passport); // load our routes and pass in our app and fully configured passport
// launch ======================================================================
http.listen(port);
console.log('The magic happens on port ' + port);
This is my client side code.
<!doctype html>
<html>
<head>
<title>chat message</title>
<link rel="stylesheet" href="/css/chat.css" type="text/css"/>
</head>
<body>
<div class="messages"><br/><br/><br/><br/><br/><br/> </div>
<form action="">
<input id="m" autocomplete="off" /><button>Send</button>
</form>
<script src="https://cdn.socket.io/socket.io-1.3.7.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('.messages').append($('<div class=bubble><br/>').text(msg));
});
</script>
</body>
</html>
This was my fix
var express = require('express');
var app = express();
var server = require('http').Server(app);
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');
// Add connect-mongo to project - npm install connect-mongo
var MongoStore = require('connect-mongo')(session);
var configDB = require('./config/database.js');
var http = require('http').Server(app);
var io = require('socket.io')(http);
var chatdb = require('./app/models/chat.js');
// configuration ===============================================================
// NOTE: This might need to be put into a callback/promise inside an initialize function
var db = 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()); // get information from html forms
app.set('view engine', 'ejs'); // set up ejs for templating
var mongoStore = new MongoStore({
mongooseConnection: db.connection,
});
app.use(session({
secret: 'secret',
clear_interval: 900,
cookie: { maxAge: 2 * 60 * 60 * 1000 },
store: mongoStore,
}));
// required for passport
app.use(session({ secret: 'secret' })); // 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
app.use(express.static(__dirname + '/views'));
app.use(express.static(__dirname + '/public'));
// Intercept Socket.io's handshake request
io.use(function(socket, next) {
// Use the 'cookie-parser' module to parse the request cookies
cookieParser('secret')(socket.request, {}, function(err) {
// Get the session id from the request cookies
var sessionId = socket.request.signedCookies ? socket.request.signedCookies['connect.sid'] : undefined;
if (!sessionId) return next(new Error('sessionId was not found in socket.request'), false);
// Use the mongoStorage instance to get the Express session information
mongoStore.get(sessionId, function(err, session) {
console.log('efe');
if (err) return next(err, false);
if (!session) return next(new Error('session was not found for ' + sessionId), false);
// Set the Socket.io session information
socket.request.session = session;
console.log(sessionId);
console.log(socket.request.user);
// Use Passport to populate the user details
passport.initialize()(socket.request, {}, function() {
passport.session()(socket.request, {}, function() {
// This will prohibit non-authenticated users from connecting to your
// SocketIO server.
if (socket.request.user) {
next(null, true);
} else {
next(new Error('User is not authenticated'), false);
}
});
});
});
});
});
// socket.io
io.on('connection', function(socket) {
console.log('a user connected');
socket.on('chat message', function(msg) {
console.log('a use connected');
var name = "efe";
chatdb.saveMsg({
name: name,
msg: msg
}, function(err) {
if (err) throw err;
io.emit('chat message', msg);
});
});
socket.on('disconnect', function() {
console.log('user disconnected');
});
});
// routes ======================================================================
require('./app/routes.js')(app, passport); // load our routes and pass in our app and fully configured passport
// launch ======================================================================
http.listen(port);
console.log('The magic happens on port ' + port);
How can I create session in expressjs(4.0)?
I am doing exactly same in the links
var session = require('express-session');
/* session */
app.use(session({ secret: '1s2sd25asd7asd5asd7f4f1f'}))
However it gives error?
TypeError: Cannot read property 'connect.sid' of undefined
How do I create session in expressjs? I have been trying to create session for 3 days.
In express 4, create session like this
var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');
var session = require('express-session');
You have to must use cookieParser before session
app.use(cookieParser())
app.use(session({secret: 'MySecret'}));
for further information, read connect official documentation here
Complete code :
var express = require('express');
var session = require('express-session');
var bodyParser = require('body-parser');
var app = express();
app.set('views', __dirname + '/views');
app.engine('html', require('ejs').renderFile);
app.use(session({secret: 'ssshhhhh'}));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
var sess;
app.get('/',function(req,res){
sess=req.session;
//Session set when user Request our app via URL
if(sess.email)
{
/*
* This line check Session existence.
* If it existed will do some action.
*/
res.redirect('/admin');
}
else{
res.render('index.html');
}
});
app.post('/login',function(req,res){
sess=req.session;
//In this we are assigning email to sess.email variable.
//email comes from HTML page.
sess.email=req.body.email;
res.end('done');
});
app.get('/admin',function(req,res){
sess=req.session;
if(sess.email)
{
res.write('
<h1>Hello '+sess.email+'</h1>
');
res.end('Logout');
}
else
{
res.write('
<h1>Please login first.</h1>
');
res.end('Login');
}
});
app.get('/logout',function(req,res){
req.session.destroy(function(err){
if(err){
console.log(err);
}
else
{
res.redirect('/');
}
});
});
app.listen(3000,function(){
console.log("App Started on PORT 3000");
});
Read here : http://codeforgeek.com/2014/09/manage-session-using-node-js-express-4/