My backend (Node.js + express.js) uses the following code to delete a cookie:
app.get('/logout', function(req, res) {
res.clearCookie('access_token', { domain:'localhost', path: '/', httpOnly: true, secure: true })
.redirect('http://localhost:4200/login')
});
The problem is when I made the cookie secure the previous code no longer deletes the cookie no matter how I visit the url.
Related
I tried to see if my cookies is working ,so here's my code
const RedisStore = connectRedis(session)
const redisClient = redis.createClient()
app.use(
session({
//name: 'qid',
store: new RedisStore({ //ttl: how long it should last
client: redisClient,
//disableTTL :true, //make sure session last forever
//disableTouch: true, // make sure it does'nt have to update the last time it's ttl
}),
cookie:{
maxAge: 1000*60*60*24*365*10, //10 years
path: "/"
//httpOnly:true, //javascript front end can't access
//sameSite:'none', // csrf
//secure:false
//secure: __prod__ //cookie only works in https
},
saveUninitialized:true, //automatically create a empty session on default
secret: 'some secret', //env
resave: false,
})
)
app.listen(4000,()=>{
console.log('server stared on localhost:4000')
})
app.get('/products', (req,res,next) => {
console.log(req.session);
if(!req.session.userId){
req.session.userId = 1
}else{
req.session.userId = req.session.userId +1
}
console.log(req.session.userId) //test if work
res.send("hello")
})
So here's the thing, when I connect to localhost:4000/products, In the cookie session, I can only see these
But when I print out the results on vscode console, I can see the number is growing like below , so I do have a session, it's just not showing on the browser , can anyone tell me why is that?
server stared on localhost:4000
Session {
cookie: {
path: '/',
_expires: 2031-08-18T12:59:30.827Z,
originalMaxAge: 315360000000,
httpOnly: true
},
userId: 10
}
11
Session {
cookie: {
path: '/',
_expires: 2031-08-18T13:00:37.257Z,
originalMaxAge: 315360000000,
httpOnly: true
},
userId: 11
}
12
So I got a solution after a lot of tests, So if you only set your cookie to same-site:"none" without secure options ,it would be like my situation,but if you want to turn on secure option your endpoint have to be https, so I don't think this was the answer, and you can change to lax or other options it would act normal in your localhost,
Work in local host
lax
(don't set same site)
But due to secure policy https://www.chromium.org/updates/same-site you can't not pass cookie to some certain website (in my case I want to test cookies in my graphql apollo studio) without setting same-site:"none" secure, so I use mkcert to use https in my localhost
https://web.dev/how-to-use-local-https/ , and everything works,
Work
samesite : none
secure : true
https:yourendpoint
I have a question about session cookies over web from express backend. In the front I am using a Vue PWA/SPA that is being mounted on express static via express.use(express.static('static')); to serve the built files.
I did some research that we can attach options to the function with
express.use(cookieParser());
express.use(session({
secret : `${uuid()}`,
proxy: true,
resave: false,
saveUninitialized: false,
cookie: {
maxAge: 1000 * 60 * 30
}
}))
const options = {
dotfiles: 'ignore',
etag: false,
extensions: ['html', 'htm'],
index: false,
maxAge: '1d',
redirect: false,
setHeaders: function(res, path, stat) {
res.set('Set-Cookie', "myCookie=cookieValue;Path=/");
res.set('x-timestamp', Date.now());
}
}
express.use(express.static('static' , options));
After doing those, hoping I can read myCookie=cookieValue on the browser via document.cookie but I don't see those datra being printed on the page.
I have also tried it with __dirname method as well and then do
app.get("/", function(req, res) {
req.session.fullname = "Oh mi gee";
res.render("index");
});
didn't give me what I want. Is there a way for me to add session/cookies so I can somewhat secure the API calls by passing cookie data on the header for confirmation?
Thanks in advance!
I have figured it out, is to place this express.static at the very end of the express configuration.
before we establish express.static we will want to do
app.use('/path', (req, res, next) => {
req.session.views++;
res.cookie('myCookie', 'cookieValue', {
maxAge: 1000 * 60 * 30
});
console.log(req.session);
next();
})
will transfer the cookies to the client side with the expiry of half an hour.
I am having a problem with logging out of my application.
I am using MongoDB to store my sessions.
I log out by using session.destroy and the document gets removed from the collection in the database. However I still remained logged in. Also the cookie in the browser still exists, surely this should expire. I believe my authentication is using the cookie in the browser to check authentication and since that is still there, it keeps me logged in.
Here is my authentication code:
app.js
app.use(session({
secret: 'whatshouldmysecretkeybe',
cookie: {
maxAge: 86400000
},
resave: false,
unset: 'destroy',
saveUninitialized: false,
store: new MongoStore({
mongooseConnection: db
})
}));
loginController.js
// Authenticated Check
exports.requires_login = function (req, res, next) {
if (req.session && req.session.userId) {
return next();
} else {
return res.redirect('/cms/unauthenticated');
return;
}
}
exports.logout = function (req, res, next) {
if (req.session) {
// delete session object
req.session.destroy(function (err) {
if (err) {
return next(err);
} else {
return res.redirect('/cms/');
}
});
}
}
Route file
I put the login_controller.requires_login middleware on the route to check for authentication on every route that needs authentication. I hope this is the best way to do this.
/* GET Login authenticate */
router.get('/users/logout', login_controller.requires_login, login_controller.logout);
/* GET User listing page */
router.get('/users', login_controller.requires_login, user_controller.list);
Thank you.
Looks like the issue was due to mongoose 5 not being fully compatible with connect-mongo.
This github issue explains more:
https://github.com/jdesboeufs/connect-mongo/issues/277
To fix you have to use your mongo url in the url property instead of mongooseConnection.
Example:
app.use(session({
secret: 'whatshouldmysecretkeybe',
resave: false,
unset: 'destroy',
saveUninitialized: false,
store: new MongoStore({
url: YOUR_MONGO_URL
})
}));
In my app I restrict some access to some actions and pages if a user is not logged in. I have:
var restrict = function(req, res, next) {
if (!req.user) {
console.log("USER isn't logged in.")
return res.status(403).send('Access or action denied, please log in');
}
next();
}
app.get('/stocks', restrict, MainHandler.findAllStocksFromUser);
app.get('/stocks/:id', MainHandler.findStockByIdAndDates);
app.put('/stocks/:id/stockActions', restrict, MainHandler.handleStockAction);
I'm essentially trying to refresh a session everytime the client makes a request to the server so that the server doesn't logout the user/destroy the session when it shouldn't. For testing, I want the session to expire/the user to be logged out if 20 seconds go by without the user making an requests to the server. I have:
app.use(session({secret: 'secret', saveUninitialized: true, resave: true, expires: new Date(Date.now() + (20000))}));
Then I try to use middleware to refresh the expiration date every time the use makes a request:
// Session-persisted message middleware
app.use(function(req, res, next){
req.session.cookie.expires = new Date(Date.now() + 20000);
next();
});
But if I log in from the client, and click around, causing requests to the server, I still get the log-in error on the client after 20 seconds, despite trying to "refresh" the session in the middleware. I have also tried using maxAge using the same strategy with the middleware. Any ideas? Thanks!
You can try define your session as follows
app.use (
session ({
secret: "secret",
saveUninitialized: true,
resave: true,
cookie: {
expires: 20 * 1000
}
})
);
and then refresh the session using
req.session.touch()
or you could define your session as
app.use (
session ({
secret: "secret",
saveUninitialized: false,
resave: true,
rolling: true,
cookie: {
expires: 20 * 1000
}
})
);
and it will renew the session automatically and it will only expire when it has been idle for the value in the expires variable
express-session supports a duration-based maxAge setting, which will work better than setting a fixed date for all sessions. So your middleware usage should instead look like:
app.use(session({
secret: 'secret',
saveUninitialized: true,
resave: true,
maxAge: 20000
}));
Next, to update the expiration of the session, you can just call req.session.touch(); if that is all you're doing to the session and its contents.
The documentation has a lot of other good information on controlling session expiration and related topics.
I am using passport-twitter to set up a twitter connect on my site. Users can connect by clicking on 'login' or on 'add new item'. The only difference between the 2 is that if they click on add new item, a modal window is supposed to open once theyre logged in.
To know on button they click, I store the url in req.session.referrer:
// route for twitter authentication and login
app.get('/auth/twitter', function(req, res, next){
req.session.referrer = req.url;
console.log(req.session);
passport.authenticate('twitter')(req, res, next);
});
app.get('/auth/twitter/new', function(req, res, next){
req.session.referrer = req.url;
console.log(req.session);
passport.authenticate('twitter')(req, res, next);
});
// handle the callback after twitter has authenticated the user
app.get('/auth/twitter/callback', function(req, res, next){
var options = {
successRedirect : '/twitter-user/signin',
failureRedirect : '/'
};
console.log(req.session);
if (req.session.referrer && req.session.referrer.indexOf('new') > -1) options.successRedirect = '/twitter-user/new';
passport.authenticate('twitter', options)(req, res, next)
});
Everything works fine in my development environment but once online I get this error message:
Express
500 Error: Failed to find request token in session
at Strategy.OAuthStrategy.authenticate (/app/node_modules/passport-twitter/node_modules/passport-oauth1/lib/strategy.js:142:54)
...
My settings are set up properly in Twitter. Here is what I get with the logs:
For the request:
{ cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true },
passport: {},
referrer: '/auth/twitter' }
For the callback:
{ cookie:
{ path: '/',
_expires: null,
originalMaxAge: null,
httpOnly: true },
passport: {} }
Maybe it could be due to subdomain problem ( http://example.com vs http://www.example.com) as I don't have the pb locally.
How can I fix this?
Many thanks
EDIT: My API key is set up like this (as per this tutorial: http://scotch.io/tutorials/javascript/easy-node-authentication-twitter):
passport.use(new TwitterStrategy({
consumerKey : configAuth.twitterAuth.consumerKey,
consumerSecret : configAuth.twitterAuth.consumerSecret,
callbackURL : configAuth.twitterAuth.callbackURL
},function(token, tokenSecret, profile, done) {
...
});
First if your callback is localhost and you are using express-session make sure the cookie secure option is set to false. e.g
// Express session
let sess = {
secret: 'secret',
resave: true,
saveUninitialized: true,
cookie: {
secure: false,
}
}
You can also change that in production by
if (process.env.NODE_ENV === 'production') {
app.set('trust proxy', 1) // trust first proxy
sess.cookie.secure = true // serve secure cookies
}
If that didn't work then check if you have set the cookie sameSite option to Strict. Change it to Lax. e.g
let sess = {
secret: 'secret',
resave: true,
saveUninitialized: true,
cookie: {
secure: false,
sameSite: 'Lax'
}
}
I got the same Error but solved it.. and here's what my issue was and the solution.
Actuality, it didn't like my redirect url "http:// localhost /auth/twitter/callback". I changed it to "http:// 127.0.0.1 /auth/twitter/callback". In my actual code, I had to keep it as localhost or I'd get errors about a missing token