I'm using express-session to store session cookie. I can see Set-Cookie connect.ssid under the response header but for some reason it is not getting stored in the cookie.
I'm wondering if this is a CORS issue, my app file looks like this. Should I change something here to make it work.
const session = require('express-session');
const config = require('config');
var MemoryStore = require('memorystore')(session);
module.exports = function (app) {
// app.use(
// session({
// secret: 'key sign',
// resave: false,
// saveUninitialized: false
// })
// );
app.use(express.json());
app.use(cors({ credentials: true }));
enter code here
app.set('trust proxy', 1);
app.use(
session({
saveUninitialized: false,
cookie: { maxAge: 86400000 },
store: new MemoryStore({
checkPeriod: 86400000
}),
resave: false,
cookie: { secure: false },
secret: config.get('sessionStorage')
})
);
app.use('/api/users', users);
Here is how I fixed this.
Add SSL to both frontend and backend.
If it is self-signed, ensure browser trust it. For example, if you're using mac, go to keychain, select specific certificate and select always trust option.
Restart the system. Only then SSL will be properly set otherwise there would still be insecure badge in the navigations.
Related
I was making a React project, and I was using Express for backend. I set http://mini-api.moonlab.ga as a virtual host for Express server.
I sent a HTTP Request to express server with Fetch:
fetch("http://mini-api.moonlab.ga/login/", {
credentials: "include"
})
and as I expected there was a CORS error. So I installed cors package, and I set code like this in Node.js:
app.use(cors({
origin: true,
credential: true
}));
And I respond to client from server like this:
app.get("/login", (req, res) => {
const session = req.session;
if (session.miniAccount == undefined) {
session.miniAccount = Math.floor(Math.random() * 1000000);
}
res.writeHead(200, {"Access-Control-Allow-Credentials": true});
res.write(String(session.miniAccount));
res.end();
})
After I did like this, there wasn't any CORS error, but the session don't persist. When I send a request again, the session data keeps changes.
Well how to make session persist?
Server's session code:
app.use(express_session({
secret: secret.app_key,
resave: false,
saveUninitialized: true
}));
You may try setting a maxAge value inside cookie
...
const session = require("express-session");
...
app.use(
session({
secret: secret.app_key,
resave: false,
saveUninitialized: true
cookie: {
maxAge: 3600000 //session expires in 1 hr
}
})
);
I solved it myself by editing package.json.
I added "proxy": "mini-api.moonlab.ga" in package.json.
Than I edited fetch().
previous
fetch("http://mini-api.moonlab.ga/login")
new
fetch("/login")
And it worked.
I been search a lot and dont found solutions,
when I send request in postman everything goes well
but in my react app every request I send i get new session and I lossing my User info (using passport)
there is my backend session configuration:
app.use(cors({
credentials: true,
origin: 'http://localhost:3000',
methods:['GET','POST', 'DELETE', 'PUT'],
}));
//SESSION CONFIGURATION
const sessionStore = new MongoStore({
mongooseConnection: connection,
collection: 'sessions'
})
const sessionConfig = {
store: sessionStore,
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: true,
cookie: { maxAge: 3600000, httpOnly: true, secure: false}
};
app.use(session(sessionConfig));
there is my axios configuration (fontend):
const instance = axios.create({
baseURL: 'http://127.0.0.1:5000/',
withCredentials: true
});
I really exhausted from this problem need some help thanks in advance
UPDATED
problem not solved but I see that my client side dont store any coockie in the browser and I get the coockie in the auth response
The node application uses passport-ldap for authentication, and the issue is that it works like a charm in the development environment, but the are problems in the production one. When the route is being changed, I lose the user's session because the connect.sid (the cookie) of the Application is being changed, because I have a new setCookie response.
I am using express 4.17.1 and express-session 1.16.2, so from my research I found that i do not have to use cookieParser. I also think that there is no issue with the serialize and deserialize of the user and passport functionality.
// Static folder set
app.use(express.static(path.join(__dirname, 'public')));
// Body parser middleware
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.set('trust proxy', 1) //trust first proxy
// Express session midleware
app.use(session({
secret: 'abc',
resave: true,
saveUninitialized: true,
cookie: { secure: true }
}));
// Passport middleware
app.use(passport.initialize());
app.use(passport.session());
...
// Use routes of the application
app.use('/users', users);
I found the solution and i post it for future reference, in case someone else faces a similar issue.
I used the cors module and set it like that
app.use(cors({credentials: true}));
also in production enviroment you have to use a store to hold the cookie. This was obvious but i missed it. So i used
const MongoStore = require('connect-mongo')(session);
app.use(session({
secret: 'abc',
resave: false,
saveUninitialized: false,
cookie: { secure: true,
maxAge: 6*60*60*1000 },
store: new MongoStore({ mongooseConnection: mongoose.connection })
}));
In my directory i have app.js And Index.htmml ; I am trying to set cookies from App.js; I have tried:-
var express = require('express'),
app = express(),
http = require('http'),
cookieparser = require ('cookie-parser'),
httpServer = http.Server(app);
app.use(express.static(__dirname + '/data'));
app.get('/', function(req, res) {
let options = {
maxAge: 60000, // would expire after 1 minutes
httpOnly: true,
signed: true ,
secret: 'secret'
}
// Set cookie
app.use(require('express-session')({ secret: 'keyboard cat', resave: true, saveUninitialized: true }));
res.cookie('cookieName', 'Success', options)
res.sendFile(__dirname + '/index.html');
});
app.listen(8080);
When i run app.js from Cmd It dissappoints me with this error
Thanks in advance for help
Error: cookieParser("secret") required for signed cookies
You need to specify a secret key which will be used while signing the cookie.
You can do this by adding the following line to your code.
app.use(cookieparser("secret"));
According to the snippet, you are using the express-session module like so:
app.use(require('express-session')({ secret: 'keyboard cat', ... }));
That is already saying that you want cookies to be signed. Therefore, in your cookie options you can remove the option signed: true since it will be redundant.
And on a last note, you need to improve that code.
I am trying to include sessions only for some routes (the authentication ones) but I am having a problem because of the error page routes:
I have this:
app.use(session({
secret: config.secrets.session,
saveUninitialized: false,
resave: false,
store: sessionStore,
proxy: true,
cookie: {
maxAge: config.token_duration,
secure: false
}
// rolling: false
}));
app.use('/api/user', require('./api/user'));
app.use('/api/auth', require('./api/auth'));
app.route(['/error/500','/error/404','/user/settings'])
.get((req, res) => {
res.sendFile(path.resolve(app.get('appPath') + '/index.html'));
});
app.route('/*/*')
.get(errors[404]);
app.use(errors[500]);
So, If I use it like this, all the pages in my application will create a session (which I don't want). If I move the session section after the error routes, I will never get to the api routes because it will reach the 404 route.
Thanks in advance
Middleware can be associated with only certain routes and the order in which it is specified matters. There are a number of ways to do that and how to best implement it depends upon the paths your site uses and how you can most easily create a link between path and whether it should or should not have the session middleware on it.
One simple thing to do would be to put your error route handlers BEFORE your session middleware. Then, those route handlers would "handle" the request first and the session middleware would never get called.
app.route(['/error/500','/error/404','/user/settings'])
.get((req, res) => {
res.sendFile(path.resolve(app.get('appPath') + '/index.html'));
});
app.use(session({
secret: config.secrets.session,
saveUninitialized: false,
resave: false,
store: sessionStore,
proxy: true,
cookie: {
maxAge: config.token_duration,
secure: false
}
// rolling: false
}));
Other things you can do:
Put a path on your session middleware so it is only invoked for certain paths in your site (all authenticated pages should be below that path).
Create your own middleware handler that checks to see if the path is /error and if not, then it invokes the session middleware handler. If it is /error, then don't invoke the session middleware.
This last one could be done like this:
const sessionHandler = session({
secret: config.secrets.session,
saveUninitialized: false,
resave: false,
store: sessionStore,
proxy: true,
cookie: {
maxAge: config.token_duration,
secure: false
}
// rolling: false
});
app.use(function(req, res, next) {
// if path does not start with /error/, then invoke session middleware
if (req.url.indexOf("/error/") !== 0) {
return sessionHandler(req, res, next);
} else {
next();
}
});
You can also chain/compose multiple middleware using Express.router() as mentioned in this example: Express: composing middleware
And then apply that composed router (of chained middleware) as a specific route handler.