Express + Passport + Redis sessions? - javascript

To date I have been using the default MemoryStore for my Express sessions. Everything has been working great, except that all session data is lost between restarts. So I am trying to get my sessions working with Redis & Connect-Redis instead.
Here is the part of my code that concerns session config with Redis:
var express = require( "express" ),
app = module.exports = express(),
passport = require( "./passport" ),
http = require( "http" ),
RedisStore = require( "connect-redis" )( express ),
redis = require( "redis" ).createClient();
app.configure(function(){
app.set( "passport", passport );
app.use( express.cookieParser());
app.use( express.session({
secret: "I can haz working sessions?",
store: new RedisStore({ client: redis })
}));
app.use( passport.initialize() );
app.use( passport.session() );
...
When I run this application, there are no errors. However when I try to login, although it performs the initial login, I just keep getting bounced back to the login screen. It is as if passport cannot set a cookie, or cannot read a cookie after it has been set.
For reference, here are the functions I use in passport to serialize / deserialize the session:
passport.serializeUser(function( user, done ) {
done( null, {
id : user.id,
type : user.type,
firstname: user.firstname,
lastname: user.lastname
});
});
passport.deserializeUser(function( user, done ) {
done( null, user );
});
Any advice on where I am going wrong? Do the passport serializeUser / deserializeUser need to be modified to work with redis? Or am I missing something else?
Thanks (in advance) for your help.

One possibility: maybe your app can't connect to Redis? I found that when my redis-server was not running, I experienced the symptom you describe (silently fails to set cookies).
Aside from checking that it's running, make sure your Node server can actually connect to it—that is, that there are no firewall rules keeping you out.
Good luck!

Related

How can I setup an OpenID Connect authentication with Node Js?

here is the thing. I have my app that has separated back-end and front-end into two different project (back-end with Node-JS, and front-end with Vue-JS). I got a home page with a button that should redirect the user to the authentication server to log in.
So i made an "on-click" function in my homePage.vue that will consume a function from my api.
I've read a lot of documentation and seen some examples. But to be honest, during those past weeks, even if I tried, I still do understand nothing about how authentication works.
You can see below the js file i wrote inspired by examples that i found:
auth.js
const express = require('express');
const { auth } = require('express-openid-connect');
const app = express();
app.use(
auth({
issuerBaseURL: 'myDomainUrl',
baseURL: 'http://localhost:8080',
clientID: 'myClient_ID',
secret: 'aaaaaaaaaaaaaaaaaaaa',
idpLogout: true,
authRequired: false,
})
);
module.exports = app;
There is also the route with the function that I try to implement:
auth.route.js
module.exports = app => {
var router = require("express").Router();
router.get('', location.replace('myDomainUrl'));
app.use('/api/login', router);
};
I don't know if it's important but my back-end runs on the port 4000 and my front-end runs on the port 8080.
If someone can explain me how I can do to make my authentication work and what I have to change, it would be great.
Thanks you in advance, I hope I was clear enough about my problem. If not, do not hesitate to ask me what was not clear.

Node.js + Express + i18next how manage two languages same time

in my Node.js + Express + i18next app I would like to keep separate frontend and backend languages. I already managed to keep separate the login session data, so that I can login as normal user in the frontend and as administrator in the backend at the same time and
independently:
const express = require('express');
const session = require('express-session');
const app = express();
...
app
.use('/admin', session({
...
cookie: {
path: '/admin',
},
name: 'adminSessionID',
...
}))
.use('/', session({
...
cookie: {
path: '/',
},
name: 'sessionID',
...
Now I need to do the same with i18next and languages. What can I do? I tried creating 2 i18next instances but the cookie created is always only the last one defined and, even worst, if I change language via query string, it changes both in front and backend...
Any advice could be usefull, thank you

Node.js with firebase does not save info in the Session

I am trying to use session in my app, to keep track on user log-in and more.
But...
When I tried using the simplest way, I kept getting the error :
Warning: connect.session() MemoryStore is not designed for a production environment, as it will leak memory, and will not scale past a single process.
There for, after much searching, I added the firebase-session functionality,
but now, even though I get no error, nothing is saved in the session.
This is my code:
const functions = require('firebase-functions');
const express = require('express');
const session = require('express-session');
const FirebaseStore = require('connect-session-firebase')(session);
const firebase = require('firebase-admin');
const ref = firebase.initializeApp(
functions.config().firebase
);
const app = express();
app.use(session({
store: new FirebaseStore({
database: ref.database()
}),
secret: 'asdfasgbrwewet53hnhwetynsy',
resave: true,
saveUninitialized: true
}));
app.get('/', function(req, res, next) {
console.log(req.session);
req.session.username='rakafa';
res.send('Returning with some text');
});
app.get('/bar', function(req, res, next) {
console.log(req.session);
var someAttribute = req.session.username;
res.send(`This will print the attribute I set earlier: ${someAttribute}`);
});
exports.app = functions.https.onRequest(app);
This is what I did so far:
My original example taht I used to start using session: session-express example
I took the firebase part from npm: npm firebase-session
Tried to use radis-store as a solution, didn't word: using radis-store solution
Using session-store, gave me the same worning as using nothing.. npm session-store
This question gave me the idea of using firebase-session database sessions explanations
I saw this an example with cookies, but didn't understand, and didn't find another example cookie session
Just another word, I only just started learning Node.js, so please try using simple examples, so I would understand ;)
And please forgive my starte's mistakes
Please, HELP....
=== edit ===
According to orxelm's answer, I changed my ref to this:
const ref = firebase.initializeApp({
//admin.credential.cert(serviceAccount)
credential: firebase.credential.applicationDefault(),
databaseURL: "https://*****.firebaseio.com/"
});
But still, when I run the app, there is nothing in the session once I refresh the page.
sessions in the server
^^
I can see that the app created a lot of sessions in the server.
but none of them have the information I added on the app,
and since I use only one browser, there should only one session, am I wrong?
I had this problem, when I was using firebase hosting and functions, but can be solved by simply setting name:"__session" in the session.
app.use(session({
name:"__session,
...
after adding this, saving values in the session like req.session.username='rakafa' worked fine.
Where is you firebase config?
Maybe try to initialize the firebase admin this way:
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'https://<DATABASE_NAME>.firebaseio.com'
});

Session management in Nodejs

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;
}

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