I searched a lot to fix my problem but nothing works, the req.session is undefined, what am I doing wrong ?
In server.js :
const app = express();
const session = require('express-session');
const redis = require('redis');
const redisClient = redis.createClient();
async function connectRedis() {
try {
const redisStore = require('connect-redis')(session);
await redisClient.connect();
app.use(
session({
name: '_redisPractice',
secret: 'myStackOverflowkey',
saveUninitialized: true,
cookie: { maxAge: 1000 * 60 * 60 * 24, secure: false, httpOnly: true },
resave: false,
store: new redisStore({ host: 'localhost', port: 6379, client: redisClient, ttl: 86400 }),
}),
);
} catch (err) {
console.log(err);
}
}
connectRedis();
app.post('/api/auth/signin', (req, res) => {
console.log('Well.....', req.session);
});
The redis-CLI's monitor doesn't show anything, same for my server.
Thank you in advance
Related
I am trying to add Redis to my website for session management but I get the below error:
UnhandledPromiseRejectionWarning: Error: The client is closed
Below is my code:
I have kept only the relevant redis lines to avoid verbosity.
const express = require('express');
const app = express();
const session = require('express-session');
const redis = require('redis');
const connectRedis = require('connect-redis');
const RedisStore = connectRedis(session)
const redisClient = redis.createClient({
host: 'localhost',
port: 6379
})
redisClient.on('error', function (err) {
console.log('Could not establish a connection with redis. ' + err);
});
redisClient.on('connect', function (err) {
console.log('Connected to redis successfully');
});
app.use(session({
store: new RedisStore({ client: redisClient }),
secret: 'secret$%^134',
resave: false,
saveUninitialized: false,
cookie: {
secure: false, // if true only transmit cookie over https
httpOnly: false, // if true prevent client side JS from reading the cookie
maxAge: 1000 * 60 * 10 // session max age in miliseconds
}
}))
app.use(
session({
name: 'AuthCookie',
secret: 'some secret string!',
resave: false,
saveUninitialized: true
})
);
app.listen(port, () => {
console.log("We've now got a server!");
console.log('Your routes will be running on http://localhost:3000');
});
I read that I should add await client.connect() but I am not sure
i am trying to set cookie on apollo Studio explorer, my redis setup successfully store the cookie, but nothing is set on the browser.
Please What am i doing wrong ?
when make a monitoring of redis with redis-cli ,i can see that the token is receive.
i am using : apollo-server-express "^3.3.0", and express-session "^1.17.2"
async function startServer() {
const app = express();
const httpServer = http.createServer(app);
const RedisStore = connectRedis(session);
const redisClient = redis.createClient({
host: "127.0.0.1",
port: 6379,
});
app.use(
session({
name: "pid",
store: new RedisStore({
client: redisClient,
}),
cookie: {
maxAge: 1000 * 60 * 10,
httpOnly: false,
secure: true,
sameSite: "none",
},
saveUninitialized: false,
secret: "EOJ7OmvIAhb2yJpCI947juj6F8CppHCp",
resave: false,
})
);
const server = new ApolloServer({
schema,
context: createContext,
formatError: (error) => {
return {
message: error.message,
};
},
});
await server.start();
server.applyMiddleware({
app,
cors: { credentials: true, origin: "https://studio.apollographql.com" },
});
await new Promise((resolve: any) =>
httpServer.listen({ port: process.env.PORT }, resolve)
);
}
startServer().catch((err) => console.log(err));
In node using express.js, I have a redis-based session set up thusly:
// Redis session
const sessionStore = new RedisStore({
client: getRedisClient(),
prefix: 'bl:',
ttl: parseInt(config.sessionTTL, 10),
logErrors: (err) => {
log.error('Redis session error', {
err_message: err.message,
err_stack: err.stack
});
}
});
app.use(session({
secret: config.sessionSecret,
store: sessionStore,
resave: false,
saveUninitialized: false
}));
The ttl parameter is typically set to 30 minutes, at the end of which the session dies quite nicely.
I now need to advise the user when 5 minutes or less remains of their session but can't find a way of determining when I hit that landmark.
I assumed (rather naively) the amount of time left would be stored in req.session, but when I display that it typically only shows the following:
Session {
cookie: { path: '/', _expires: null, originalMaxAge: null, httpOnly: true },
cookieChoiceConfirmationBannerSeen: 'seen',
accessPage: '/decision/application-reference',
appRef: '12345678'
}
How can I find how much time is left on my session? Should I use maxAge or expiry rather than ttl?
========= EDIT =========
Additial info:
the code for getRedisClient:
const redis = require('ioredis');
const config = require('../config/config');
let client;
const getRedisClient = () => {
if (!client) {
client = redis.createClient({
host: config.redisHost,
port: config.redisPort
});
}
return client;
};
module.exports = {
getRedisClient
};
You should be able to get the ttl of the entry itself by calling your redisClient with the corresponding key, i.e. your defined key-prefix (default sess) and the session-id. Something like this should work:
const prefix = 'bl:';
const redisClient = getRedisClient();
// Redis session
const sessionStore = new RedisStore({
client: redisClient,
prefix: 'bl:',
ttl: parseInt(config.sessionTTL, 10),
logErrors: (err) => {
log.error('Redis session error', {
err_message: err.message,
err_stack: err.stack
});
}
});
app.get('/get-session-ttl', (req, res) => {
redisClient.ttl(`${prefix}${req.session.id}`,((err, reply) => {
console.log("the remaining ttl is "+reply);
res.send("...");
}));
})
I'm trying to use mssql-session-store as nodejs (express) store for session:
https://www.npmjs.com/package/mssql-session-store
This is how it should be configured(from npm page):
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: false,
store: new MssqlStore(options) // see options below
}));
var options = {
connection: existingConnection,
ttl: 3600,
reapInterval: 3600,
reapCallback: function() { console.log('expired sessions were removed);
}
};
My problem is with the options.connection. It should be "Optional instance of a Connection from mssql".
This connection establishment is an async process (from the npm page):
const sql = require('mssql')
async () => {
try {
await sql.connect('mssql://username:password#localhost/database')
const result = await sql.query`select * from mytable where id =
${value}`
console.dir(result)
} catch (err) {
// ... error checks
}
}
This is how express session is being defined in the nodejs initialization:
app.use(session({
name:<session name>,
key: <session key id>,
resave:false,
saveUninitialized:false,
secure: process.env.NODE_ENV ==="production",
secret:<secret string>,
store: new MssqlStore(options), //This is optional - for use when using sql server as a store
cookie:{
//httpOnly: true,
secure: process.env.NODE_ENV ==="production",
expires: config.expressSession.cookieLifeTime
}
}));
The problem is that establishment of the connection is an async process. I've tried several versions to both use the express-session in the application, but doing so just after the connection has been set up (async).
See my basic code (initialization of node.js - servre.js file):
const express = require('express');
const app = express();
const sql = require('mssql');
const session = require ('express-session');
const MssqlStore = require ('mssql-session-store')(session);
var sqlStore = null;
var store = null;
var mssqlConfig =
{
user: <user>
password: <password>,
server: <server name>
database: <database>,
options: {
encrypt: true // Use this if you're on Windows Azure
}
}
I've tried setting the session in the app in the connetion promise:
var sqlConnection = null;
async function getConnectedConnectionOptions()
{
try
{
sqlConnection = await sql.connect(<connection string>);
return await Promise.resolve(sqlconnection: sqlConnection);
} catch (err)
{
sqlConnection = null;
}
}
getConnectedConnectionOptions(),then(result =>
app.use(session({
name:<session name>,
key: <session key id>,
resave:false,
saveUninitialized:false,
secure: process.env.NODE_ENV ==="production",
secret:<secret string>,
store: new MssqlStore(result) ,
cookie:{
//httpOnly: true,
secure: process.env.NODE_ENV ==="production",
expires: config.expressSession.cookieLifeTime
}
}));
but then there's a scope problem where session is not defined in the global app.
Please support.
this is inside example folder in the mssql-session-store module
var dbConfig = {
server: "localhost\\sqlexpress",
database: "sessiontest",
user: "sa",
password: "atonan"
};
var start = function(callback) {
callback = callback || function() {};
sql.connect(dbConfig, function(err) {
if (err) return callback(err);
var app = express();
app.use(session({
secret: '991E6B44882C4593A46C0DDFCA23E06A',
resave: false,
saveUninitialized: false,
store: new MssqlStore({ reapInterval: 10, ttl: 10 })
}));
I'm using express-session for handling user session in Node.js application. The problem is after rewriting it for MySQL storage it seems like after changing route all information disappears and my middleware redirects me for login page again.
My code:
let options = {
host: "localhost",
user: "root",
port: 3306,
password: "",
database: "cursova"
}
var sessionStore = new MySQLStore(options, con);
app.use(session({
key: 'myCookie',
secret: 'secret12345',
store: sessionStore,
resave: false,
saveUninitialized: false,
cookie: {
originalMaxAge: 1000 * 60 * 5,
maxAge: 60000 * 5,
secure: true,
path: '/',
}
}));
console results:
Try initializing the session:
app.use((req, res, next) => {
req.session.init = "init";
next();
});
For session, I have this:
const options = {
host: config.db.host,
port: config.db.port,
user: config.db.user,
password: config.db.password,
database: config.db.database
};
const sessionStore = new MySQLStore(options);
const expiryDate = new Date(Date.now() + 24 * 60 * 60 * 1000); // 1 hour
app.use(session({
store: sessionStore,
secret: process.env.SESSIONSECRET,
resave: false,
saveUninitialized: false,
cookie: {
//secure: true,
//httpOnly: true,
expires: expiryDate
}
}));
I am not passing the connection and do not have a key. I add in the HTTP and secure once I know it works.
Most likely the issue is because of "secure: true" from cookie. This means the cookie is saved only if you use HTTPS. Try setting it to false