How to save persistent data in Express? - express

I have a simple requirement to store an access token/refresh token in Express (without using localStorage or anything). I'd like to store them in a persistent httpOnly cookie so any time a user visits the page who has previously visited the page can see if the access token is already there, and if so, make API calls and log in and so on.
I've spend some time looking at express-session and cookie-session and simply can't figure out the proper way to do it. express-session requires a store for production, and I don't want to set up a store to simply store an access token. So something like this works in devleopment:
app.use(
session({
secret: 'conduit',
cookie: {
path: '/',
maxAge: 60 * 60 * 1000,
httpOnly: true,
secure: isProduction,
},
resave: false,
saveUninitialized: false,
})
)
Using this to set it on request:
request.session.accessToken = accessToken
request.session.save()
But if it's not going to work in a production environment, it's not helpful. I haven't been able to get it working with cookie-session, or I don't know how to set/retrieve the cookies, and the documentation isn't very helpful.
So I'm asking: how can I store a few strings on an Express server/httpOnly cookie in a persistent way, without using a Store/Redis/MemCache/etc?

I had to use cookieParser.
const cookieParser = require('cookie-parser')
app.use(cookieParser())
// set a cookie
response.cookie('nameOfCookie', 'cookieValue', {
maxAge: 60 * 60 * 1000, // 1 hour
httpOnly: true,
secure: isProduction,
})
// get a cookie
request.cookies.nameOfCookie
// destroy cookie
response.clearCookie('nameOfCookie')

Related

express-session cookies blocked in browsers

I know this question is redundant, but I have been searching and reading articles all around for hours now. I am using express-session to control user sessions for the express server. It works when I try to console req.session.user from a postman request. When I try to fire the same request from the browser, it returns undefined. Everyone is talking about Chrome security updates and third-party cookies restrictions. I've tried to stick to chrome guidelines on cookie options but didn't help. If I deployed my client or server to a secure domain would it help?
Here are my options
app.use(cors())
app.set('trust proxy', 1) // trust first proxy
app.use(session({
store: new (require('connect-pg-simple')(session))({pool}),
secret: process.env.SESSION_SECRET,
resave: true,
rolling: true,
cookie: {
maxAge: 30 * 60 * 1000, // 30 minutes
secure: false,
sameSite: 'none'
},
saveUninitialized: false,
}));

Express-session changes session id on refresh (Guest login attempt)

I'm trying to create a guest account for a portfolio website so that recruiters can play with it without having to register and set things up, but I need the account to be session or IP specific so that users can have their own guest account without interfering with each other.
I thought about achieving that by using the sessionID within ApolloServer's context.req as the account name but I've noticed I get a different sessionID on every request/refresh.
My backend's session setup looks like this:
const app = express();
// Initialize redis sessions server
const redisConfig = app.get('env') === 'production' ? { host: 'redis' } : undefined; // Change host from default to the name of the docker service (redis) when in production
const RedisStore = connectRedis(session);
const redisClient = redis.createClient(redisConfig); // This would take the connection parameters, but we leave the default values: https://redislabs.com/lp/node-js-redis/
// Tell express that we have a proxy in front of our app so that sessions work when using Nginx: http://expressjs.com/en/guide/behind-proxies.html#express-behind-proxies
if (app.get('env') === 'production') app.set("trust proxy", 1);
app.use(
cors({
origin: process.env.CORS_ORIGIN,
credentials: true
})
);
app.use(
session({
name: COOKIE_NAME,
store: new RedisStore({
client: redisClient,
disableTTL: true, // TTL: time to live, how long the session is active, if we want our sessions to be active permanently until manually disabled.
disableTouch: true, // Prevent that the TTL is reset every time a user interacts with the server.
}),
cookie: {
maxAge: 10 * 365 * 24 * 60 * 60 * 1000, // How long in miliseconds until the cookie expires (10 years)
httpOnly: app.get('env') === 'production', // Prevents JS in the frontend from accessing the cookie.
// domain: app.get('env') === 'production' ? 'websitename.com' : undefined,
secure: app.get('env') === 'production', // Cookie only works in https
sameSite: 'lax',
},
saveUninitialized: false, // Prevents that empty sessions are created.
secret: `${process.env.SECRET}`,
resave: false, // False to prevent constant pinging to Redis
})
);
And in my frontend:
const client = new ApolloClient({
cache: new InMemoryCache(),
link: new HttpLink({
uri: process.env.API_URL,
credentials: 'include', // Required for sessions. Sends our cookie back to the server with every request.
})
});
This happens both in my local dev environment and in my deployed https website. I've seen similar issues with suggestions about changing the secure and samesite parameters or the CORS config, but that hasn't worked for me so far.
Any idea of what the issue might be? Is this just not the right approach to do what I'm after?
Sorry if it's something super-obvious, haven't touched my server in months and my backend skills are a bit rusty '^^.

Express cookie-session not saving cookie when SameSite is set to 'none' and secure is set to true

I am using cookie-session and passportjs to authenticate users in my express app. When I initialize my cookieSession like this:
app.use(cookieSession({
maxAge: 24 * 60 * 60 * 1000,
keys: ['key1']
}));
my cookie is successfully saved to the client. However, the project I am working on requires cross-site requests. Therefore, the secure attribute for the cookie must be set to true and the SameSite attribute must be set to none. In the documentation, these values are able to be set as follows:
app.use(cookieSession({
maxAge: 24 * 60 * 60 * 1000,
secure: true,
sameSite: 'none',
keys: ['key1']
}));
however, when I do this, the cookie fails to save to the client. I'm wondering if anyone knows how to fix this or why this might be happening?
Thank you in advance.
The answer by Luka Darsalia showed me that, in my case at least, the server was refusing to send secure:true cookies to the client, because it thought the client was insecure (due to the request.protocol being http rather than https).
At first I was confused by this, because my address-bar showed https. But then I remembered that the https was only for the connection between my browser and Cloudflare CDN -- the connection between Cloudflare CDN and my actual server was still using http.
Thus, to fix it, I simply had to assure cookie-session (more specifically, this line in the cookies package) that the connection was secure, and thus to go ahead with sending the cookie with the secure:true flag.
To do this, I simply added the following middleware after the cookieSession middleware:
// your existing cookieSession init here
app.use(cookieSession({
[...]
secure: true,
sameSite: "none",
}));
// enable the "secure" flag on the sessionCookies object
app.use((req, res, next)=>{
req["sessionCookies"].secure = true;
next();
});
After authentication use this:
passport.authenticate("local");
req.session.save((error) => {
if (err) {
console.log(err);
} else {
res.redirect("/");
}
});

ExpressJs Sessions Not Lasting After the Window Closes

In Expressjs, i have some code to use cookie session, which is a middleware that is like express-session, but it keeps the session even after the server restarts. I was looking at other questions, but they all said that you should add a maxAge attr to the cookie. I did this, and the session still expires after the browser closes. Here:
const express = require('express');
const app = express();
const session = require('cookie-session');
app.use(session({
name: 'session',
secret: `secret`,
httpOnly: true,
expires: new Date(Date.now() + 999999999999999999999999999999999999999999999999999999999999999999999999999*9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999*999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999),
maxAge: 999999999999999999999999999999999999999999999999999999999999999999999999999*9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999*999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999,
signed: true
}));
This is was shown in other questions, (besides the expires and maxAge being very long). So, what is my problem? Again, i would like to make the session last even after the window closes, right now it lasts after the tab closes but not the entire window. This only needs to work in Chrome. Thanks!
You can try:
app.use(session({
secret: "session",
resave: true,
resave: false,
saveUninitialized: true,
key: 'express.sid'
}));
Otherwise, I would save the cookie to database, and always compare user's cookie with cookies in db.
P.S.
Note If both expires and maxAge are set in the options, then the last one defined in the object is what is used.
source: https://www.npmjs.com/package/express-session

how do I can generate sessions in server for logged in users only , with Express, Express-session, Passport and Connect-mongo?

I'm using express-session, passport, connect-mongo and mongodb-atlas last versions, for create sessions and save them on the server, the
problem is when app.use(passport.session()), this session is created even if the user is not logged in.
app.use(session({
// key: "id",
secret: process.env.SESSION_SECRET,
cookie: {
httpOnly: true,
sameSite: true,
// secure: process.env.IN_PROD,
maxAge: 10800000,
}, // three hours in miliseconds
store: new MongoStore({
mongooseConnection: mongoose.connection,
autoReconnect: true,
collection: "admin.mySessions",
serialize: serialize
}),
resave: false,
saveUninitialized: false,
name: 'Id'
}));
this causes that when passport is initialized and the passport session
the cookie is saved with session id and the session is saved in the
mongodb
mi question is how save session only for users logged in
Hello mate I am not aware of mongo-session, but from your explanation I understand that you are creating token for users even if they don't login. I suggest you create a new token each time a user hits login API and expire the token once he logs out.By following this token is generated only for active users.