I'm coding a session with NodeJS, when I get the user connection first create a session.client with the MAC ADDRESS, so far so good, but then I ask to the client if he want to continue and login on the app with social -network like Facebook, Instagram, Tweeter or Google+, and then when the user is redirected to the social login it back with other session from passportjs and clear al my init data of session and I lost the client information. So, I tried to change the name of the data in session, session.data, session.test, session.whatever but always happen the same, when I test and the passport redirect me and back to my domain, the session is clean and it change with new data from passportjs, any one know what's happen here? any idea how to solve this?
the code run perfectly, the problem is the session when go and back to // the social login, it clear my init data and back with the passport data. // I need my init data to continue working!
this is just an extract of code. It works
'use sctrict'
const https = require('https'),
fs = require('fs'),
path = require('path'),
morgan = require('morgan'),
logger = require('express-logger'),
express = require('express'),
favicon = require('serve-favicon'),
bodyParser = require('body-parser'),
methodOverride = require('method-override'),
passport = require('passport'),
// config files
port = 443,
mongodbConfig = require('./config/mongodb-config'),
session = require('express-session'),
keys = require('./config/keys'),
options = {
key: fs.readFileSync('./config/ssl/server.key'),
cert: fs.readFileSync('./config/ssl/server.crt')
},
cookieParser = require('cookie-parser'),
loginAPRoutes = require('./routes/loginAPRoutes'),
passportSetup = require('./config/passport-setup'),
app = express()
// MongoDB - Mongoose connection
const mongoose = require('mongoose')
mongoose.Promise - global.Promise
mongoose.connect('mongodb://' + mongodbConfig.mongodb.route + '/' + mongodbConfig.mongodb.db, {})
.then(() => console.log('db connected'))
.catch(err => console.log(err))
// config
app.set('view engine', 'ejs')
// middlewares
app.use(morgan('dev'))
app.use(favicon(path.join(__dirname, 'public/img/', 'favicon.ico')))
app.use(bodyParser.urlencoded({
extended: false
}))
app.use(bodyParser.json())
app.use(methodOverride('X-HTTP-Method-Override'))
app.use(express.static(path.join(__dirname, 'public')))
app.use(session({
secret: 'cybor-cat',
resave: false,
saveUninitialized: true
}))
// initilize passport
app.use(passport.initialize())
app.use(passport.session())
// Main routes
app.use('/guest', loginAPRoutes)
app.use('/auth', loginAPRoutes)
// Run the server https
https.createServer(options, app).listen(port, () => {
console.log('NodeJS Server Started... splice.pro is running!')
})
router.get('/s/:site', (req, res) => {
data = req.query
data.site = req.params.site
req.session.data = data
console.log('===== session ========')
console.log(req.session)
console.log('====== session END =======')
res.render('login')
})
/////////////// GOOGLE AUTH ////////////////
// route for google login
router.get('/google', passport.authenticate('google', {
scope: ['profile', 'email']
}))
// route for google and redirect
router.get('/google/callback',
passport.authenticate('google'), (req, res) => {
if (!req.user) {
res.redirect('/guest/s/site')
} else {
/////////// here comes the new session from passport :( //////
////////// and lost the first data of my session /////
console.log(req.session.data)
//////////////// this show the session with info of user ///////
/////////////// but req.session.data is lost ///////////
res.redirect('/guest/startconnection')
}
}
)
/////////////// GOOGLE AUTH END ////////////////
Well, well, well.... I found my problem, my external site redirect me to my server with the ip and when the request of passport login redirect , it back to the domain name, that's why it generate a new session id ... A long day but at the end I found it !
Related
I am new here.
I am trying to develop a web application and I have hit a brick wall which I've been stuck on for a while now.
When running my app.js file all pages show up except for the chatroom. Could someone please take a look at the code and help me out?
I haven't included my code for register and login etc. as they are working fine. When using their router.get and .post concepts for the chatroom I just receive a "Cannot GET /chatroom" message.
Chatroom.js:
const express = require('express');
const router = express.Router();
const socketClient = require('socket.io').listen(4000).sockets;
//Chatroom page: Credit - Traversy Media - https://www.youtube.com/watch?v=hrRue5Rt6Is&t=1542s
router.get('/chatroom', (req, res) => res.render('chatroom.ejs'));
router.post('/chatroom', (req, res) => {
// Connect to Socket.io
socketClient.on('connection', function (socket) {
let chat = db.collection('UsersDB/chats');
// Create function to send status
sendStatus = function (s) {
useUnifiedTopology: true,
socket.emit('status', s);
}
// Get chats from mongo collection
chat.find().limit(100).sort({ _id: 1 }).toArray(function (err, res) {
if (err) {
throw err;
}
// Emit the messages
socket.emit('output', res);
});
// Handle input events
socket.on('input', function (data) {
let name = data.name;
let message = data.message;
// Check for name and message
if (name == '' || message == '') {
// Send error status
sendStatus('Please enter a name and message');
} else {
// Insert message
chat.insert({ name: name, message: message }, function () {
socketClient.emit('output', [data]);
// Send status object
sendStatus({
message: 'Message sent',
clear: true
});
});
}
});
// Handle clear
socket.on('clear', function (data) {
// Remove all chats from collection
chat.remove({}, function () {
// Emit cleared
socket.emit('cleared');
});
});
});
});
app.js:
const express = require('express');
const expressLayouts = require('express-ejs-layouts');
const mongoose = require('mongoose');
const passport = require('passport');
const flash = require('connect-flash');
const session = require('express-session');
const app = express();
// Passport Config
require('./config/passport')(passport);
// DB Config
const db = require('./config/keys').mongoURI;
// Connect to MongoDB
mongoose
.connect(
db,
{ useNewUrlParser: true }
)
.then(() => console.log('MongoDB Connected'))
.catch(err => console.log(err));
// EJS
app.use(expressLayouts);
app.set('view engine', 'ejs');
// Express body parser
app.use(express.urlencoded({ extended: true }));
// Express session
app.use(
session({
secret: 'secret',
resave: true,
saveUninitialized: true
})
);
// Passport middleware
app.use(passport.initialize());
app.use(passport.session());
// Connect flash
app.use(flash());
// Global variables
app.use(function(req, res, next) {
res.locals.success_msg = req.flash('success_msg');
res.locals.error_msg = req.flash('error_msg');
res.locals.error = req.flash('error');
next();
});
// Routes
app.use('/', require('./routes/index.js'));
app.use('/users', require('./routes/users.js'));
app.use('/chatroom', require('./routes/chatroom.js'));
const PORT = process.env.PORT || 5000;
app.listen(PORT, console.log(`Server started on port ${PORT}`));
First and foremost I'd like to thank Cranky Coder; Prakher Londe; and Sunil Lulla for your replies.
I ended up figuring out how to make the chatroom show up. As mentioned before my other pages(login and register etc.) were showing up fine. Unlike the chatroom I had the backend for these in a users.js file. So what I decided to do was move my chatroom.js code into my users.js which was then called in the app.js(the file I run) with app.use('/users', require('.routes/users.js')).
I then changed my router.get code to:
router.get('/chatroom', (req, res) => res.render('chatroom', {
user: req.user
}));
Then in my router.post (see OP for context) I added a res.redirect('/users/chatroom'); before closing with the final bracket.
Lastly I of course edited my .ejs file to have
I found that doing it this way is even better because the chatroom cannot be accessed unless one is logged in.
Thank you again for all your replies and although this is a bit of a specific problem I do hope this helps someone in the future.
I am writing a simple MEAN app, and I am currently working on the routes.
In my server.js, I have
var express = require('express');
var multer = require('multer');
var upload = multer({dest: 'uploads/'});
var sizeOf = require('image-size');
var app = express();
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var methodOverride = require('method-override');
// configuration ===========================================
require('./app/models/Purchase');
require('./app/models/Seller');
require('./app/models/User');
// config files
var db = require('./config/db');
var port = process.env.PORT || 8080; // set our port
// mongoose.connect(db.url); // connect to our mongoDB database
// get all data/stuff of the body (POST) parameters
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
app.use(bodyParser.urlencoded({ extended: true })); // parse application/x-www-form-urlencoded
app.use(methodOverride('X-HTTP-Method-Override')); // override with the X-HTTP-Method-Override header in the request. simulate DELETE/PUT
app.use(express.static(__dirname + '/public')); // set the static files location /public/img will be /img for users
// routes ==================================================
var routes = require('./app/routes/routes');//(app); // pass our application into our routes
var price = require('./app/routes/pricing');
var processing = require('./app/routes/processing');
var uploads = require('./app/routes/uploads');
var seller = require('./app/routes/seller');
app.use('/', routes);
app.use('/price', price);
app.use('/processing', processing);
app.use('/uploads', uploads);
app.use('/seller', seller);
// start app ===============================================
app.listen(port);
console.log('Magic happens on port ' + port);
exports = module.exports = app;
Then, in my route, I have
var express = require('express');
var mongoose = require('mongoose');
var Seller = mongoose.model('Seller');
var router = express.Router();
router.get('/', function(req,res){
res.json({message: 'youre in router.get'});
});
router.post('/registerSeller', function(req,res,next){
console.log('You made it all the way to seller route!');
res.json({message: "you did it"});
next();
});
module.exports = router;
When I start my node server, everything goes well. When I use Postman to POST to the above route, it just 'hangs' and eventually gives an error message that it cannot connect. In Postman, I select 'POST' to http://localhost:8080/seller/registerSeller.Clicking 'code', I get
POST /seller/registerSeller HTTP/1.1
Host: localhost:8080
Cache-Control: no-cache
Postman-Token: 070cb9b3-992a-ffd6-cede-c5b609bc9ce5
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Looking at the browser's developer tools, it shows a POST being made, and then after a while, it also reads that the POST failed.
Could anyone tell me what I'm doing wrong? Thank you.
The problem is that you are responding and then trying to call the next() function in the router stack.
router.post('/registerSeller', function(req,res,next){
console.log('You made it all the way to seller route!');
return res.send({message: "you did it"});
//next(); remove this shit.
});
This should work. Express middlewares go in order. So if you need to have a middleware to be called before this function, then you have to put it before in the stack. If you need to do something after this function, forget about the res.json... part.
I'm doing an application with Node.js, Express, MongoDB (mongoose), I'm trying to make the database connection in a separate file from server.js, but I'm having a hard time with connect-mongo.
First in my server.js I had this:
/* jshint esversion: 6 */
'use strict';
let express = require('express');
const db = require('./app/config/db');
const routes = require('./app/routes/routes');
const users = require('./app/routes/users');
let app = express();
const conn = db.connect();
app.set('views', path.join(__dirname, 'app/views'));
app.set('view engine', 'hbs');
...
app.use('/', routes);
app.use('/users', users);
app.listen(3000);
module.exports = app;
This only handle the application routes, and the application server, then I had the next folder structure for my project:
myApp
|___app
|___bin
|___config
|___credentials.js
|___db.js
|___controllers
|___routes
|___views
|___node_modules
|___package.json
|___server.js
Welll insidde config folder I had two javascripts that handle the connection to the database, in the credentials.js literally only had the credentials for the access of the database.
Then my problem is inside the db.js, next I show you the file:
/* jshint esversion: 6 */
'use strict';
let mongoose = require('mongoose'),
async = require('async'),
express = require('express');
const credentials = require('./credentials');
const session = require('express-session');
const MongoStore = require('connect-mongo')(session);
let db = mongoose.connection,
app = express();
exports.connect = function(done){
const connection = mongoose.connect(credentials.host, credentials.database, credentials.port, credentials.db);
db.on('error', (error =>{
console.log("Error estableciendo la conexion");
process.exit(1);
}));
db.on('open', (argv)=>{
db.db.listCollections().toArray((err, collections)=>{
collections.forEach(x => console.log(x));
});
});
/* Define sessions in MongoDB */
app.use(session({
secret: credentials.sessionSecret,
store: new MongoStore({ dbPromise: db })
}));
}
I got the next error:
Error with nodemon server.js
Do you know how to initiate connect-mongo using this project structure?
By the way, in the credentials.js file I setup Bluebird as my promise library.
In advance thank you!
The problem was, like #MananVaghasiya said, that my variable db was not a Promise, this is a bug inside the mongoose project, so I changed the connection type to a basic uri connection with mongoose and then after the query of login I set the session.
The code it's looking like this at this time, so thank you for your time.
module.exports.login = (req, res)=>{
const mail = req.body.mail.replace(/^\s\s*/, '').replace(/\s\s*$/, ''),
password = req.body.password;
user.findOne({$and:[{'mail' : mail}, {'password': password}]}, (err, user)=>{
if(err){
res.send(err);
} else {
/* Define sessions in MongoDB */
app.use(session({
secret: credentials.sessionSecret,
store: new MongoStore({ mongooseConnection: db }),
saveUnitialized: true,
resave: false,
cookie:{
path: "/"
},
name: user.role
}));
return user;
}
});
};
There are many questions relating to getting a req.user undefined after social authentication, but I found none which could help me.
I have been able to successfully use the example for using passport for twitter authentication: https://github.com/passport/express-4.x-twitter-example. I tried to follow this pattern as closely as possible but cannot seem to get it to work.
Specifically, I am able to successfully authenticate, but the req.user is undefined. This makes no sense to me as my user data was returned no problem from the example.
I'm not inclined to believe this is a middleware problem (as it has been for others) as the middleware is the same as that used in the example. It could be something about having multiple domains, but I'm not sure what. All of this is being done on the localhost.
In Twitter, the app is set up so that
website is: 127.0.0.1:3000/signin
and the
callback url is: 127.0.0.1:2999/auth/twitter/return
As you can tell, my client is working on port 3000 and it is making calls to a server running on port 2999.
To briefly walk you through the code, the client on 127.0.0.1:3000/signin has a button which links to 127.0.0.1:2999/auth/twitter, thus initiating the authentication request. Under the hood, the express server is created in server/index.js--server. This imports the routes in routes/index.js, some of which the controller authenticate.js handles. As you can see, the oauth twitter request is made in authenticate.js. Again, authentication proceeds successfully, I am redirected to 127.0.0.1:3000/search. However, as you can see in this.twitter_callback, I am printing the req.user and it is undefined.
Please note that I have redacted the consumer key/secret from my code.
server/index.js
var cors = require('cors')
var bodyParser = require('body-parser')
var express = require('express');
var app = express();
var http = require('http').Server(app)
var io = require('socket.io')(http)
// NOT SURE WHY I NEED TO GO BACK 3 FOLDERS TO GET TO PORT_CONFIG
var port = require("../port_config.json").server_port;
var PORT = Number(process.env.PORT || port);
var routes = require('./routes/index.js')
var database = require('./database/db.js')
var db = new database()
app.use(cors()); // middleware that allows cross-platform requests
app.use(bodyParser.json());
db.dbConnect(function(err,db_instance){
// routes
routes(app, db_instance, io)
// send user polls on connection
// TEMPORARY (WILL BE GRABBED ON LOGIN)
var user = null // WILL BE SET AFTER LOGIN
io.on('connection', function(socket) {
var places_attending = db_instance.collection('places_attending')
places_attending.find({}).toArray(function(err,docs){
var places_user_attending = docs.map(doc => {
if (doc.attending.indexOf(user) !== -1) {
return {
id: doc.id,
name: doc.name,
num_attending: doc.attending.length
}
}
})
socket.emit('places_user_attending', places_user_attending);
})
})
})
http.listen(PORT, function () {
console.log('Backend server listening at http://localhost:' + PORT);
})
module.exports = http
routes/index.js
var Search = require('../controllers/search.js')
var Add = require('../controllers/add.js')
var Authenticate = require('../controllers/authenticate.js')
module.exports = function(app, db, io) {
var search = new Search(db, io)
var add = new Add(db, io)
var authenticate = new Authenticate(app)
app.route('/api/search')
.post(search.search_yelp)
app.route('/api/add')
.post(add.add_attendee)
app.route('/auth/twitter')
.get(authenticate.twitter_authentication)
app.route('/auth/twitter/return')
.get(authenticate.twitter_callback)
}
authenticate.js
function authenticate(app) {
var passport = require('passport');
var Strategy = require('passport-twitter').Strategy;
// Configure the Twitter strategy for use by Passport.
passport.use(new Strategy({
consumerKey: REDACTED,
consumerSecret: REDACTED,
callbackURL: 'http://127.0.0.1:2999/auth/twitter/return'
},
function(token, tokenSecret, profile, cb) {
// In this example, the user's Twitter profile is supplied as the user
// record. In a production-quality application, the Twitter profile should
// be associated with a user record in the application's database, which
// allows for account linking and authentication with other identity
// providers.
return cb(null, profile);
}));
// Configure Passport authenticated session persistence.
passport.serializeUser(function(user, cb) {
cb(null, user);
});
passport.deserializeUser(function(obj, cb) {
cb(null, obj);
});
// Use application-level middleware for common functionality, including
// logging, parsing, and session handling.
app.use(require('morgan')('combined'));
app.use(require('cookie-parser')());
app.use(require('body-parser').urlencoded({ extended: true }));
app.use(require('express-session')({ secret: 'keyboard cat', resave: true, saveUninitialized: true }));
// Initialize Passport and restore authentication state, if any, from the
// session.
app.use(passport.initialize());
app.use(passport.session());
this.twitter_authentication = passport.authenticate('twitter')
this.twitter_callback = (
passport.authenticate('twitter', { failureRedirect: 'http://127.0.0.1:3000/signin' }),
function(req, res) {
console.log('REQ.USER OBJECT: ' + req.user)
res.redirect('http://127.0.0.1:3000/search');
}
)
}
module.exports = authenticate
Any help would be greatly, greatly appreciated.
The problem was in how my twitter_callback route was specified.
If I change the callback to this:
this.twitter_callback = app.get('/auth/twitter/return',
passport.authenticate('twitter', { failureRedirect: 'http://127.0.0.1:3000/signin' }),
function(req, res) {
console.log(req.user)
res.redirect('http://127.0.0.1:3000/search');
})
everything works fine. I think this has something to do with the middleware not being applied correctly the initial way I wrote it. Not exactly sure how I would rewrite it to export it, without using app.get in the twitter_callback though
I have been staring at the same SO questions/answers for too long.
I am trying to set my user ID in a req.session variable
here is my app.js stack
/**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, cors = require('cors')
, mongoose = require('mongoose')
, User = require('./user-model')
, path = require('path')
, mysql = require('mysql');
app = express()
/**
* Middleware.
*/
app.use(cors());
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'supercalafragalistic' }));
app.locals.pretty = true;
app.use(express.static(path.join(__dirname, 'public')));
app.set('view engine', 'jade');
...
app.get('/someRoute', routes.someRoute)
I have moved the app.router from top to bottom. Currently it is implied (I just deleted it as I stripped my code looking for error). I have exported app, included app in routes (also erased) . I added middleware. I am lost.....
here is my route stack
//routes/index.js
//requires
var User = require('../user-model')
,qs = require('querystring')
,http = require('http')
,mysql = require('mysql')
,connection = mysql.createConnection({
edited
});
/**
* Set up application.
*/
connection.connect(function(err){
if(err) console.log('failed to connect to mysql because'+ err);
else console.log('connected to mysql');
})
I save the id in the login route:
//login processing route
exports.logIn = function(req, res, next){
console.log('log in request from '+req.body.name);
User.findOne({name:req.body.name}, function(err, user, next){
if(err) return next(err);
if(!user) return res.end();
//check password
user.comparePassword(req.body.password, function(err, isMatch){
if(err) res.send('failed to find user');
console.log(""+isMatch);
if(isMatch){
console.log(user._id.toString()+' user loggd in');
//set session cookie
req.session.loggedIn = user._id.toString();
console.log('req.session.loggedIn set to :'+req.session.loggedIn );
res.send(user);
}else {
res.send('User not found try again');
}
});
});
However, in all other routes the variable is undefined:
// clock status
exports.clockStatus = function(req, res, next){
var user = req.session.loggedIn;
console.log('Status route, userID: '+user);
if(user){
I found the answer in "Cannot access req.session variables in Express/NodeJS" but the last part trails off:
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.
HOW? How do you "get user information in /auth request too by session id"?
Please ask for anything else you need to straighten me out.
I'm stumped. I have tried some dumb stuff already!
The variable is undefined in other routes if you don't log in first in the browser. Here is my test code:
var express = require('express');
var cors = require('cors');
app = express();
app.use(cors());
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: 'this is a test' }));
app.use(express.static(require('path').join(__dirname, 'public')));
app.get('/login', function(req, res) {
req.session.uid = 'user001';
res.send(req.session);
});
app.get('*', function(req, res) {
res.send(req.session);
});
app.listen(8080);
First visit http://localhost/login in the browser. Then visit other URLs(e.g., http://localhost/test) in this browser, the user id in the session is returned. So maybe there is something wrong in other parts of your code.
Test settings:
Ubuntu Desktop 13.10, 64 bit
Node 0.10.26
NPM 1.4.4
Express 3.4.8
cors 2.2.0