How to set redis express-session store with loopback? - node.js

I'm using loopback 3. Wich connector is better loopback-connect-redis or loopback-kv-redis and how to configure store attribute in express-session object after adding the datasouce .
I tried :
store: app.dataSources.myDataSourceName but I got an error "store.get is not a function" so I tried :
store: app.dataSources.myDataSourceName).KeyValueAccessObject
I don't get any error but I don't have any key,value on redis. Thank you

Loopback (which I'm not hugely familiar with, admittedly) is based on Express (which I am familiar with).
I believe you should just use the express-sessions as in normal Express.
const
...
session = require('express-session'),
RedisStore = require('connect-redis')(session),
redis = require('redis'),
rs = new RedisStore({ client : redis.createClient([connection your info]) })
});
session({
secret : 'foobar',
store : rs
});
Then you would register it in your middleware.json file in the session phase.

Related

"MYSCHEMA.sessions" is an undefined name

When I try to connect to SESSIONS table which I created in the appropriate schema, I get this error:
[IBM][CLI Driver][DB2/LINUXX8664] SQL0204N "MYSCHEMA.sessions" is an undefined name. SQLSTATE=42704
I pass the DSN to the session like this:
var session = require("express-session")
, Db2Store = require('connect-db2')(session);
var options = {
dsn: 'DATABASE=MyDB;HOSTNAME=IpAddr;PORT=myPort;PROTOCOL=TCPIP;UID=db2_admin;PWD=db2_pwd;CurrentSchema=MYSCHEMA;'
}
var sessionStore = new Db2Store(options);
app.use(session({
store: sessionStore,
secret: "AAAAA:ZZZZZ:EEEEE"
}));
Did I miss something here ?
Due to DB2 auto-capitalize issue: https://www.ibm.com/developerworks/data/library/techarticle/0203adamache/0203adamache.html#N1011C, I had to put table name, columns and As clause between quotes when creating sessions table and also inside the module in connect-db2/lib/connect-db2.js file

Logging in to one Express app destroys session in other (same server)

I have two separate Express 4.x apps running on the same server machine (different ports), sharing a MongoDB instance. They both use different databases and have different session secrets.
I am able to log into application A or B individually without issue. My session is maintained and all is well. However, if I am logged into A and then log into B, my session in A is destroyed (and vice versa).
Both applications have near-identical local auth. Their serializeUser and deserializeUser is very primitive (following the Passport docs almost to the tee).
It seems that when logging into A then B, req.session.passport is destroyed, causing req.user to not serialize properly on app A and the session is considered invalid.
I'm starting to think it has to do with the fact both apps run on the same machine (thus domain), differing only by a port.
express-session : Simple session middleware for Express in Node.js. To use this you have to include this package like this.
var session = require('express-session');
To install this package, run the following command:
$ npm install express-session
How to use this in Express, following code is given:
app.use(session({
secret: 'secretkey',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));
By default, the name of the session ID cookie to set in the response (and read from in the request) is connect.sid. To overwrite this use the following :
app.use(session({
name: 'cookiename',
secret: 'secretkey',
resave: false,
saveUninitialized: true,
cookie: { secure: true }
}));
For more reference see this link - https://www.npmjs.com/package/express-session
Note:- Put your express-session statement in your application app.js before app.use(passport.session()) statement.
Hope this will help to solve your query !!
const mongoose = require('mongoose'),
timestamps = require('mongoose-timestamp');
var Schema = mongoose.Schema;
const Sessions = new mongoose.Schema({
expires : {
type : String,
default : ""
},
session : {
type : Schema.Types.Mixed,
default : {}
}
}, { collection: 'sessions' })
Sessions.plugin(timestamps)
module.exports = mongoose.model('sessions', Sessions);
//require schema
const Sessions = require('sessions');
//remove session by id
Sessions.remove({"session.user._id":user._id}
).exec(console.log)
you have to mention the different names for each session in different projects while running at different ports. by default, it will be connect.sid for all projects.
for example:-
project A running in port 3000 -
project B running in port 5000 -
while running these projects at the same time by default, they will have the same session name so they will get clashes in the authentication. so you must use different session names for each project.

connect-redis in Nodejs

I have nodejs/express/redis/express-session in use in my nodejs application (express 4.x)
The redis initializing is done by connect-redis/session framework under hood. So far it works. Now I need to use redis to store other data in addition to session, and world like to have a new store other than the session store. Is it just one store possible?
And is it possible to use the redis client initialized by connect-redis/session if only one store is possible? how to get it?
Thanks for the help!
The code now is:
var express = require('express');
var session = require('express-session');
// pass the express to the connect redis module
// allowing it to inherit from session.Store
var RedisStore = require('connect-redis')(session);
....
// Populates req.session
app.use(session({
resave: false, // don't save session if unmodified
saveUninitialized: false, // don't create session until something stored
secret: 'keyboard cat',
store: new RedisStore
}));
You'll actually want to initialize a new client for anything else, as the session library is handling it's own client under the hood.
You should most likely import the redis library itself, make your own client, and use that for all future requests / etc.
When I put following code after the code above, I got error
"myRedis Error-> Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED". It seems it is not allowed to init a new Redis instance.
So is there a way to have new client from connect-redis?
var myRedis = require('redis'); // additional redis store
var myRedisCli = myRedis.createClient();
myRedisCli.on('error', function (err) {
console.log('myRedis Error-> ' + err);
});

How to handle client-sessions in socket.io

I use client-sessions, not the express sessions. How could I get session data. Session stores on the client, not on a server.
I use client-session module https://github.com/mozilla/node-client-sessions
I found the right answer, to get session from cookie, first you should parse the cookie
handshakeData.cookie = cookie.parse(handshakeData.headers.cookie);
Than you have to decode the cookie, I used the original function from client-session module
var clientSessions = require('./node_modules/client-sessions/lib/client-sessions')
var opts = {
cookieName: 'yourSessionName'
, secret: 'secret'
}
var decoded = clientSessions.util.decode(opts, handshakeData.cookie['yourSessionName'])
decoded object holds your session data
If you want the session data on the client, you could just use the module's built-in features. If you need it on the server, then you could get the information on client-side and then emit it with socket.io, something like socket.emit('sendSocketData', dataToSend);

Shared Sessions between Node Apps?

I currently have two separate node apps running on two different ports but share the same backend data store. I need to share users sessions between the two apps so that when a user logs into through one app, their session is available and they appear to logged into the other app. In this case, its' a public facing website and an administrative backend.
Our setup is the following:
node with express
passport is being used to handle auth with Local Strategy
we're using connect-redis to allow us to share sessions via redis.
our domains look like this: www.mydomain.com and adm.mydomain.com
The config for for session stuff (and redis) is the same for both apps:
session: {
options: {
secret: "my secret",
cookie: {
domain: "mydomain.com",
maxAge:1000*60*60*24
}
},
redis: {
host: 'my host',
maxAge: 86400000,
secret: "my secret"
}
}
The config for session stuff in app.js looks like this:
if ( app.settings.env === "production" ) {
session.options.store = new RedisStore(session.redis);
}
app.use(express.session(session.options));
app.use(passport.initialize());
app.use(passport.session({ secret: 'a different secret' }));
What I expect it to do: Allow us to see the same session id in the cookie between the two apps.
So my question is: How do I set up express, redis and passport so that you can have sessions shared across different subdomains?
Maybe a bit outdated, but at this time, Express-session can recognise domain option for cookie. According to source:
function session(options){
var options = options || {}
// name - previously "options.key"
, name = options.name || options.key || 'connect.sid'
, store = options.store || new MemoryStore
, cookie = options.cookie || {}
...
And this is for setting cookie:
var Cookie = module.exports = function Cookie(options) {
this.path = '/';
this.maxAge = null;
this.httpOnly = true;
if (options) merge(this, options);
...
So, something like this will work for current 1.10.1 master:
secret: "my secret",
cookie: {
domain: "mydomain.com",
Express-session does not seem to recognize the "domain" option for cookies hence your problem. The cookie storing the session id is automatically tied to the domain for each app and so it cannot be shared.
One option is to write your own single-sign-on module to share sessions across webapps. It would probably live in an app.use() declaration fairly early in the execution order and would simply create a separate cookie (which would be cross-domain), create a separate SSO session id, and store the SSO id in this new cookie. Afterwards, you simply cross-populate req.session and req.sso-session as needed.

Resources