I am developing an application in Angular 5 which connects to my server in NodeJS.
I add the user in the req.session object after the user is logged in.
When I make a second request from Angular 5 app to retrieve something from the API, the req.session doesn't contain the user and the req.sessionId is always different.
How can I make the session persistent?
Here are the session and cookieParser middlewares:
app.use(cookieParser(config.secret))
app.use(session({
secret: config.secret,
saveUninitialized: false,
resave: false,
cookie: {
httpOnly: true,
secure: false
}
}))
It was a CORS related issue. I needed to include { withCredentials: true } in the http request options in Angular.
Related
New sessions are created for every page, I'm setting the token in the server-side session after the login. But it is not available on the next page a new session is created on that page How to avoid this? The database disconnects after the API call on the page. Every time the database connection is made before calling the API. I require the token throughout the login.
src/index.ts
...
const session = require("express-session")
app.use(session({
name : 'Server_ID',
secret : 'something',
resave:false,
saveUninitialized: true,
rolling: false,
cookie: {
same site: true,
// secure: "development",
httpOnly: true,
secure: false,
maxAge:1000 * 60 * 10
}
}));
...
you must set credentials flag with your API call
for example if you're using axios, you do this:
axios.defaults.withCredentials = true;
with this approach cookie is going to sent along with your request call
make sure you have correct CORS settings too.
I'm building a project with authentication. I'm using Node+React. I set an express session cookie on the back-end and I want a component in react to read that cookie to see if the user is authenticated or not. For some reason I can not access that cookie from the react(client-side)... Maybe someone could help out?
BACK:
app.use(session({
name: process.env.SESS_NAME,
resave: false,
saveUninitialized: false,
secret: process.env.SESS_SECRET,
cookie: {
maxAge: parseInt(process.env.SESS_LIFETIME),
sameSite: true, //strict,
secure: process.env.NODE_ENV === "production"
}
}))
FRONT:
import Cookies from "js-cookie";
...
console.log("cookie", Cookies.get("sid"));
I have a cookie named "sid" in this case and I can see it in my console in the browser... but when I try to access it its undefiend
thanks!
Your issue is that you have not set the httpOnly property on the cookie when configuring session. The default value is true which will prevent client browsers from reading the cookie.
Note be careful when setting this to true, as compliant clients will not allow client-side JavaScript to see the cookie in document.cookie.
app.use(session({
name: process.env.SESS_NAME,
resave: false,
saveUninitialized: false,
secret: process.env.SESS_SECRET,
cookie: {
maxAge: parseInt(process.env.SESS_LIFETIME),
sameSite: false, // this may need to be false is you are accessing from another React app
httpOnly: false, // this must be false if you want to access the cookie
secure: process.env.NODE_ENV === "production"
}
}))
See the cookie options in docs
I've deployed my front-end(React with Typescript) and backend (Nodejs with Typescript) to Heroku separately. I'm using express-session and connect-redis to maintain the user session, for which I'm using an external Redis service called Redistogo.
When I run my apps locally, req.session is present, and upon authenticating the user during login, I'm able to set the user's session in req.session.user. However, when running the backend on Heroku in the exact same way, req.session remains undefined.
if(process.env.NODE_ENV === 'production') {
this.app.set('trust proxy', 1)
const rtg = url.parse(process.env.REDISTOGO_URL);
const redisClient = redis.createClient(rtg.port, rtg.hostname);
redisClient.auth(rtg.auth.split(":")[1]);
this.app.use(session({
name: 'random_pur',
store: new RedisStore({
redisClient
}),
secret: 'meow',
resave: true,
saveUninitialized: false,
cookie: {
secure: false,
sameSite: false,
maxAge: 36000000,
httpOnly: false,
}
}));
}
So I'm not sure what I'm missing here - it doesn't give any problems on localhost. Any help would be appreciated. Thanks!
I'm using NodeJS + express + express-session to persist a userID from anywhere in the application.
On the first route, my session is defined
userProfileRoutes.route('/authentication').post((req, res) => {
req.session.userID = 10; //example
console.log(req.session)
}
The result of the console.log is:
Session {
cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true,
secure: true },
userID: 10 } // this is the right value
But then, from a different route, I can't see the value:
userProfileRoutes.route('/edit').get(function (req, res) {
console.log('After the nav edit route');
console.log(req.session);
}
And this prints
Session {
cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true,
secure: true }
} // ID VARIABLE DISAPEARS HERE
I am configuring express-session using these parameters:
app.use(session({
secret: 'secret',
proxy: true,
resave: false,
saveUninitialized: true,
withCredentials: true,
cookie: { secure: true },
store: new MongoStore({ mongooseConnection: db })
}));
Why is my userID not persisted between requests and on all routes?
You are setting cookie: {secure: true} but trying to access your server using HTTP.
From the express-session documentation:
cookie.secure
Note be careful when setting this to true, as compliant clients will not send the cookie back to the server in the future if the browser does not have an HTTPS connection.
Please note that secure: true is a recommended option. However, it requires an https-enabled website, i.e., HTTPS is necessary for secure cookies. If secure is set, and you access your site over HTTP, the cookie will not be set.
Make sure you are either using HTTPS (always in production!) or you set cookie.secure to false (maybe, and for development only!)
The secure flag in cookies
The secure flag is an option that can be set by the application server when sending a new cookie to the user within an HTTP Response. The purpose of the secure flag is to prevent cookies from being observed by unauthorized parties due to the transmission of a the cookie in clear text.
To accomplish this goal, browsers which support the secure flag will only send cookies with the secure flag when the request is going to a HTTPS page. Said in another way, the browser will not send a cookie with the secure flag set over an unencrypted HTTP request.
By setting the secure flag, the browser will prevent the transmission of a cookie over an unencrypted channel.
from https://www.owasp.org/index.php/SecureFlag
Cookies in express-session
Following common practice, express-session uses cookies to store a session ID and server side storage (mongoDB in your case) to store session data. If the browser does not send your session ID because it can't find a valid cookie, your server will assume there is no session, and save the user id on a new session on every request.
When you got to /authentication it will save the ID on a new session. When you try to read in in a different request, the session ID has changed and you have no value in userID.
It looks like express-session is not setting cookies when working locally or on Safari but they are working fine on Chrome when deployed on Heroku. Never come across this issue before. Below is how I have set up my app.session():
app.use(session({
genid: function(req) {
return genuuid();
},
secret: consts.SECRET_KEY,
resave: false,
saveUninitialized: false,
resave: false
}));
When the user logs in I set req.session.user = aValue and then a resolve on my router checks to see if the server is getting a 200 or 401 back.