var express = require('express')
var parseurl = require('parseurl')
var session = require('express-session')
var app = express()
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}))
This is my simple code. However, I want to use session only if the req.url contains /web. Is there a way I can wrap this inside a middleware of my own?
I've tried:
function setSession(req,res,next){
if(req.url.indexOf('/api') != 0){
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}));
next();
}else{
next();
}
};
and then
app.use(setSession);
But setting req.session.hello = "world" in my controller gives: TypeError: Cannot set property 'hello' of undefined. Simply put, it doesn't work. Are my arguments wrong in my middleware?
However, I want to use session only if the req.url contains /web. Is there a way I can wrap this inside a middleware of my own?
You certainly can. You can use express.Router to create sub-routes, like this:
var sessionMiddleware = session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
});
var webRoutes = express.Router()
.get('/', function(req, res, next) {
res.send('I have a session!');
});
var nonWebRoutes = express.Router()
.get('/', function(req, res, next) {
res.send('No session here');
});
app.use('/web', express.Router()
.use(sessionMiddleware)
.use(webRoutes));
app.use('/nonweb', nonWebRoutes);
Edit:
If however you want to conditionally execute the middleware function, you could do it like this:
app.use(function(req, res, next) {
if (req.url.indexOf('/api') !== 0) {
sessionMiddleware(req, res, next);
} else {
next();
}
});
app.get('/api', function(req, res, next) {
res.send(!!req.session); //false
});
app.get('/web', function(req, res, next) {
res.send(!!req.session); //true
});
But I prefer the sub-route approach because it maps your path route structure to a hierarchy which makes the code easier to read and easier to incorporate other middleware that make use of sessions, like passport.js for example.
Related
I am developing a Shopify App in node.js. I am using different Shopify webhooks for different actions. similarly for a specific scenario I need to use session value while I am getting response from Shopify API. So in this scenario the session is not working for me. Please have a look on below code.
My code in index.js
const express = require('express');
const app = express();
var session = require('express-session');
app.set('trust proxy', 1); // trust first proxy
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true,
cookie: {
httpOnly: false,
secure: true,
maxAge: 60000
}
}));
//Set the session
app.get('/check_timewindow_orders', function (req, res, next) {
req.session.delvy_date = query.date_select;
});
app.use(function (req, res, next) {
res.locals.delvy_date = req.session.delvy_date;
next();
});
I get the session value in app.get and app.post.
app.get('/order_created_get', function (req, res) {
console.log(req.cookies.delDate);
// It display the value store in session.
});
But I cannot get the session value when I get the post from shopify Order Create Webhook API.
app.post('/order_created', function (req, res) {
console.log(req.cookies.delDate); // It display Null.
});
You are not actually using the session.
You need to add it as middleware:
app.get('/check_timewindow_orders', session, function(req, res, next){
req.session.delvy_date = req.query.date_select;
});
app.use(session, function(req, res, next) {
res.locals.delvy_date = req.session.delvy_date;
next();
});
I am using Express Framework and socket.io. I am working on authentication part and I am unable to change the value of cookie. Please see the code.
var session = require('express-session');
app.use(cookieParser());
app.use(session({
secret: "kvkjsdsbj12334",
resave:false,
saveUninitialized: false,
cookie:{
authStatus: "NotLoggedIn",
secure: false
},
rolling: true
}));
app.use(function (req, res, next){
console.log(req.session.cookie.authStatus); // Logs NotLoggedIn after /login.
});
app.post('/login',(req,res)=>{
var body = _.pick(req.body,['email','password']);
var email = body.email;
var password = body.password;
Users.findByCredentials(body.email,body.password).then((user)=>{
req.session.user = user;
req.session.cookie.authStatus = "loggedIn";
req.session.save();
//Redirected from here
});
});
I have a handler for '/', which redirects to /login.html.
However, even though i'm explicitly calling to redirection, the page that is rendered is STILL index.html.
it's pretty lame behaviour, since I'm expecting A and gets B.
How can I solve it?
var app = express();
app.use(express.static('public'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
app.use(session({ secret: 'keyboard cat', resave: false, saveUninitialized: false }));
app.use(passport.initialize());
app.use(passport.session());
MW:
app.use('/', (req, res, next) => {
if (req.user) {
next();
} else {
res.redirect('/login.html');
}
});
app.post('/login',
passport.authenticate('local', {
successRedirect: '/index.html',
failureRedirect: '/login.html'
})
);
I'm trying to access 'testpage' route. But the req.isAuthenticated() returns false only for this route. (This route was there before I started to add authentication).
I'm able to go to login page and authenticate with google. Then I can access 'signup' or 'user_profile' route without problems.
After login if I try:
localhost:8080/testpage
the server sends me to "/". But if I try:
localhost:8080/testpage#
with hash sign in the end, the page is rendered.
// routes/users.js
var express = require('express');
var router = express.Router();
module.exports = function (passport) {
router.get('/login', function (req, res) {
res.render('login', { message: req.flash('loginMessage') });
});
router.get('/auth/google', passport.authenticate('google', { scope: ['profile', 'email'] }));
router.get('/auth/google/callback',
passport.authenticate('google', {
successRedirect: '/',
failureRedirect: '/'
}));
router.get('/user_profile', isLoggedIn, function (req, res) {
res.render('user_profile');
});
router.get('/signup', isLoggedIn, function (req, res) {
res.render('signup');
});
router.get('/testpage', isLoggedIn, function (req, res) {
res.render('testpage');
});
return router;
};
function isLoggedIn(req, res, next) {
if (req.isAuthenticated())
return next();
res.redirect('/');
}
Any ideas why this is happening?
* update *
Here my app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var passport = require('passport');
var flash = require('connect-flash');
var session = require('express-session');
var db = require('./mongoose');
var app = express();
require('./config/passport')(passport);
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');
// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(session({
secret: 'secret123',
resave: true,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
var users = require('./routes/users')(passport);
app.use('/', users);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// 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);
res.render('error');
});
module.exports = app;
It could be due to the express-session middleware that is needed for passport. you can fix it by using middleware in following order.
var session = require('express-session')
var app = express()
app.set('trust proxy', 1) // trust first proxy
app.use(session({
secret: 'yoursecret',
resave: true,
saveUninitialized: true,
cookie: { secure: true },
// you can store your sessions in mongo or in mysql or redis where ever you want.
store: new MongoStore({
url: "mongourl",
collection: 'sessions' // collection in mongo where sessions are to be saved
})
}))
// Init passport
app.use(passport.initialize());
// persistent login sessions
app.use(passport.session());
See https://github.com/expressjs/session for more details.
Also I think so you have not config google strategy.
try some thing like following
var GoogleStrategy = require('passport-google-oauth').OAuthStrategy;
// Use the GoogleStrategy within Passport.
// Strategies in passport require a `verify` function, which accept
// credentials (in this case, a token, tokenSecret, and Google profile), and
// invoke a callback with a user object.
passport.use(new GoogleStrategy({
consumerKey: GOOGLE_CONSUMER_KEY,
consumerSecret: GOOGLE_CONSUMER_SECRET,
callbackURL: "http://www.example.com/auth/google/callback"
},
function(token, tokenSecret, profile, done) {
User.findOrCreate({ googleId: profile.id }, function (err, user) {
return done(err, user);
});
}));
Finally after one entire day I just realized that when I was typing localhost:8000/testpage in the url bar it was been changed to www.localhost:8000/testpage. And the auth dos not work with www*. Another thing is that google chrome tries to predict what url you will type and this could cause this type of error, and it is annoying at debugging. So I unchecked this options at chrome's settings, preventing prediction.
Node.js does not seem to be remembering my session.
I am using Express with cookie-parser and express-session as middleware.
In my application, I use Mongo to keep usernames and passwords.
The following is a MWE:
var express = require('express');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var app = express();
app.use(cookieParser({
secret: 'derma-aid'
}));
app.use(session({
secret: 'derma-aid',
resave: false,
saveUninitialized: false,
cookie: {secure: false}
}));
// CORS (Cross-Origin Resource Sharing) headers to support Cross-site HTTP requests
app.all('*', function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'X-Requested-With');
next();
});
app.get('/login', function(req, res)
{
console.log('login');
req.session.user_id = 500;
res.send('<h1>login</h1>');
});
app.get('/view', function(req, res)
{
console.log('view id: ' + req.session.user_id);
res.send('<h1>view: ' + req.session.user_id + '</h1>');
});
app.get('/logout', function(req, res)
{
console.log('logout: ' + req.session.user_id);
res.send('<h1>logout: ' + req.session.user_id + '</h1>');
delete req.session.user_id;
});
app.listen(5000);
If you go to the browser to http://localhost:5000/login, then req.session.user_id should be set and displayed correctly on http://localhost:5000/view.
But, instead, I am getting undefined messages...
EDIT: cookie: {secure: false} as suggested by #tiblu. I get this error: TypeError: Secret string must be provided..
I managed to fix the TypeError: Secret string must be provided.
- app.use(cookieParser({
- secret: 'derma-aid'
- }));
+ app.use(cookieParser(
+ 'derma-aid'
+ ));
In your session middleware setup change from:
cookie: {secure: true}
to
cookie: {secure: false}
Cookies marked as secure are not sent for NON-HTTPS requests. You are accessing your application over HTTP.
More reading on that https://en.wikipedia.org/wiki/HTTP_cookie#Secure_cookie