Not being able to remove cookies on nextjs in production - node.js

I am creating an application in NextJs and I set the cookie authorization when the user make login:
res.setHeader("Set-Cookie", [
cookie.serialize("authorization", `Bearer ${jwtGenerated}`, {
httpOnly: true,
secure: process.env.NODE_ENV !== "development",
sameSite: true,
maxAge: 60 * 60 * 12,
path: "/",
})
]);
This part of the code works perfectly, it sets the cookie in the browser. However when I log out, I make a request to the url /api/logout that executes this code:
import cookie from "cookie";
export default (req, res) => {
res.setHeader("Set-Cookie", [
cookie.serialize("authorization", "false", {
httpOnly: true,
secure: process.env.NODE_ENV !== "development",
sameSite: true,
maxAge: 5,
path: "/",
})
]);
return res.status(200).json({ roles: null, auth: false });
};
however it seems that it does not work in production. When I'm at localhost it removes cookies and changes their value. However in production nothing is changed. The expiration remains the same, value and everything else.
Am I doing something wrong? Is there any other way to remove this cookie when the user make logout?

Are you using Vercel as the deployment platform? This bug is caused because Next.js's serverless features always return a 304 Not Modified. Quite frankly I don't know why this happens on the server, but I believe that it has something to do with HTTP requests on Next.js's internals.
In order to fix this problem, I made the logout request a POST request with a static key. This will prevent 304 Not Modified error from happening.
import cookie from "cookie";
export default (req, res) => {
if (req.method !== 'POST') return res.status(405).json({ status: 'fail', message: 'Method not allowed here!' });
if (req.body.key === 'static_key') {
res.setHeader("Set-Cookie", [
cookie.serialize("authorization", "false", {
httpOnly: true,
secure: process.env.NODE_ENV !== "development",
sameSite: true,
maxAge: 5,
path: "/",
})
]);
return res.status(200).json({ roles: null, auth: false });
}
return res.status(400).json({ status: 'fail', message: 'Bad request happened!' });
};

Related

BadRequestError: checks.state argument is missing - What changed?

Tabled a development project back in November and picked it back up.
The authorization that was working is not working any longer and gives me the following error.
BadRequestError: checks.state argument is missing
at /base/node_modules/express-openid-connect/middleware/auth.js:121:31
at processTicksAndRejections (internal/process/task_queues.js:95:5)
Originally I was running my server in development over http, but I thought maybe the issue was that my local server was not HTTP, so now I'm accessing it over HTTPs with a self signed certificate, if perhaps that is the issue.
I am using an ngrok proxy to support the callback to my development environment and have
OIDC_RP_URI=https://myproxy.ngrok.io
OIDC_COOKIE_DOMAIN=myproxy.ngrok.io
auth = {
authRequired: true, // validate<boolean>('DISABLE_SSO', Boolean(env.DISABLE_SSO), isBoolean, false),
baseURL: validate<string>('OIDC_RP_URI', env.OIDC_RP_URI, isString),
clientID: validate<string>('OIDC_CLIENT_ID', env.OIDC_CLIENT_ID, isString),
issuerBaseURL: validate<string>('OIDC_OP_URI', env.OIDC_OP_URI, isString),
routes: {
callback: validate<string>('OIDC_REDIRECT_PATH', env.OIDC_REDIRECT_PATH, isString),
logout: '/logout',
postLogoutRedirect: 'https://xx/Logout'
},
secret: validate<string>('EXPRESS_SESSION_SECRET', env.EXPRESS_SESSION_SECRET, isString),
session: {
cookie: {
domain: validate<string>('OIDC_COOKIE_DOMAIN', env.OIDC_COOKIE_DOMAIN, isString),
httpOnly: true,
path: '/',
sameSite: 'None' as const, // 'Lax' as const,
secure: true
},
absoluteDuration: 60 * 60 * 8,
rollingDuration: 60 * 60
}

webpack-dev-server returns 504 while backend returns 204

Here is an error text (app crashes at all 204 reponses):
[HPM] Error occurred while trying to proxy request /rest/profiles/change-password from site.loc:3005 to https://site.loc (ECONNRESET) (https://nodejs.org/api/errors.html#errors_common_system_errors)
Debugged backend response. It returns 204 status code with empty body (data = null). If I build an app everything is working fine. One more moment: it doesn't occur at other developer's MAC OS.
My webpack devServer config:
devServer: {
contentBase: PATHS.dist,
host: appDomain,
proxy: {
'/rest': {
target: appUrl,
secure: false,
changeOrigin: true
},
...
}
My enviroment:
Windows 10 Pro x64
node version: v12.18.4
webpack-dev-server: "^3.11.0",
Please, help!
I spent about 3 days on that error, myabe this answer could help anyone...
I didn't figure out why this error occur, good people helped me with this code:
proxy: {
'/rest': {
target: appUrl,
secure: false,
changeOrigin: true,
onProxyRes: function (proxyRes, req, res) {
console.log(proxyRes.statusCode);
},
onError: function (err, req, res) {
console.log(`req.body: ${req.body}`); // here it returned undefined
console.log(`err.code: ${err.code}`);
if (err.code === 'ECONNRESET') {
res.writeHead(204, {'Content-Type': 'application/json'});
res.end();
}
},
},
Previously tried to do this using webpack-dev-server bypass method, axios interceptors, but with no success.

Set user info with cookie-session

I'm using cookie-session to store all my session information.
After my users login, I store his information inside req.session.user like this
req.session.user = _.omit(client.dataValues, [
"password",
"createdAt",
"updatedAt"
]);
Using console.log I can see that everything is setted ok, but when I try to use req.session.user in another route, I get undefined.
My cookie is setted like this
app.use(
cookiesession({
name: "name",
keys: ["key1", "key2"],
maxAge: 24 * 60 * 60 * 1000,
httpOnly: false,
options: {
secure: false,
secret: "secrete",
overwrite: true
}
})
);

sails.js session data not saved into db

I might be doing something wrong. Please guide me in right direction.
I am trying to implement sails session feature with 'connect-mongo'. I did the implementation same as explained in the docs Sails session mongo. After successful authentication I am trying to save session data into mongoDb. But in my case it is not saved in mongo collection and collection always remains empty.
My configurations in session.js
url: 'mongodb+srv://username:password#cluster0-tkjwp.mongodb.net/mydbname?retryWrites=true',
collection: 'sessions',
auto_reconnect: false,
ssl: false,
stringify: true,
cookie: {
secure: false,
maxAge: 24 * 60 * 60 * 1000
}
and how I am trying to save.
if(user.length && user[0].id){
// save in DB
req.session.authenticated = true;
req.session.authinfo = user[0];
req.session.save(function(err) {
console.log(req.session);
return res.json({
status: 1,
msg: 'Successfull.'
});
})
}else{
return res.send({
status: 0,
msg: 'Invalid'
});
}
Also I am not getting any error
Its working now. Only thing I missed the adapter option. But now I am using it with mysql. Below I posting my working code with MySql.
In session.js
adapter: 'express-mysql-session',
host: 'localhost',
port: 3306,
user: 'root',
password: 'xxxxxxxxx',
database: 'xyz',
ssl: false,
stringify: true,
cookie: {
maxAge: 24 * 60 * 60 * 1000
},

ExpressJS res.render() error (JSON.stringify can't work on circular reference)

What's wrong here?
res.render('/somepage', {user:req.session.user})
It leads to Converting circular structure to JSON errors, (results in session element that has a circular user reference.)
exports.home = function (req, res) {
var entityFactory = new require('../lib/entity-factory.js').EntityFactory();
entityFactory.get_job_task_lists({
callback : function (err, job_task_lists) {
res.render('home.jade', {
locals:{
title: 'Logged in.',
user:req.session.user, // does not work
job_task_lists:job_task_lists || []
}
});
}
});
};
I added some logging in node_modules/express/node_modules/connect/lib/middleware/session/memory.js
MemoryStore.prototype.set = function(sid, sess, fn){
var self = this;
process.nextTick(function(){
console.log(sess); //this is giving the output listed
self.sessions[sid] = JSON.stringify(sess);
...
This is what I expect the session to look like, in terms of structure:
{ lastAccess: 1330979534026,
cookie:
{ path: '/',
httpOnly: true,
_expires: Tue, 06 Mar 2012 00:32:14 GMT,
originalMaxAge: 14399999 },
user: // this is the object I added to the session
{ id: 1,
username: 'admin',
password: '8e3f8d3a98481a9073d2ab69f93ce73b',
creation_date: Mon, 05 Mar 2012 18:08:55 GMT } }
But here's what I find:
{ lastAccess: 1330979534079, // new session
cookie:
{ path: '/',
httpOnly: true,
_expires: Tue, 06 Mar 2012 00:32:14 GMT,
originalMaxAge: 14399999 },
user: // but here it is again, except now it's a mashup,
// containing members it shouldn't have, like locals,
// and, well, everything but the first 4 properties
{ id: 1,
username: 'admin',
password: '8e3f8d3a98481a9073d2ab69f93ce73b',
creation_date: '2012-03-05T18:08:55.701Z',
locals:
{ title: 'Logged in.',
user: [Circular], //and now it's circular
job_task_lists: [Object] },
title: 'Logged in.',
user: [Circular],
job_task_lists: [ [Object], [Object], [Object], getById: [Function] ],
attempts: [ '/home/dan/development/aqp/views/home.jade' ],
scope: {},
parentView: undefined,
root: '/home/dan/development/aqp/views',
defaultEngine: 'jade',
settings:
{ env: 'development',
hints: true,
views: '/home/dan/development/aqp/views',
'view engine': 'jade' },
app:
{ stack: [Object],
connections: 6,
allowHalfOpen: true,
_handle: [Object],
_events: [Object],
httpAllowHalfOpen: false,
cache: [Object],
settings: [Object],
redirects: {},
isCallbacks: {},
_locals: [Object],
dynamicViewHelpers: {},
errorHandlers: [],
route: '/',
routes: [Object],
router: [Getter],
__usedRouter: true },
partial: [Function],
hint: true,
filename: '/home/dan/development/aqp/views/home.jade',
layout: false,
isPartial: true } }
node.js:201
throw e; // process.nextTick error, or 'error' event on first tick
^
TypeError: Converting circular structure to JSON
at Object.stringify (native)
at Array.0 (/home/dan/development/aqp/node_modules/express/node_modules/connect/lib/middleware/session/memory.js:77:31)
at EventEmitter._tickCallback (node.js:192:40)
See how the user object is nested?
Note that this time I did not send values in explicitly with 'locals' but it ended up in one (thats the source of the circular reference.
It looks like the session is being used to transfer objects to the view.
Here's my only middleware (it only reads from the session):
function requiresAuthentication(req, res, next){
if (req.session.user){
next();
} else {
next(new Error('Unauthorized. Please log in with a valid account.'))
}
}
and the only time I modify the req.session is in this route:
app.post('/home', function (req,res,next) {
var auth = require('./lib/authentication');
auth.authenticate_user(req.body.user, function (user) {
if (user){
req.session.user = user;
console.log('authenticated');
res.redirect(req.body.redir || '/home');
//next();
} else {
console.log('not authenticated');
res.render('logins/new.jade', {title: 'Login Failed', redir:''})
}
});
});
I don't have much else going on in my application yet, as it's still quite young. I know I'm not mangling the session anywhere myself; I checked.
I did some more testing, and it appears this is only an issue when I then try to use the local variable on a page. For instance, here is my view home.jade
div(data-role="page")
div(data-role="header")
a(href='/logout', data-icon='delete', data-ajax="false") Log out
h1= title
a(href='/account', data-icon='info', data-ajax="false") Account
!= partial('user', user)
each jtl in job_task_lists
div(id=jtl.name, class = 'draggable_item', style='border:2px solid black;')
#{jtl.name} - #{jtl.description}
a(data-icon='plus')
div(data-role="footer")
h3 footer
script(src="/javascripts/home.js")
If I comment out the user partial, it renders, else I get this Converting circular structure to JSON issue.
UPDATE
So after hooking up eclipse and the v8 debugger, I have been stepping through the code and I know where the mashup of session and user objects is occurring,
in node_modules/connect/lib/middleware/session/session.js
utils.union ends up mashing the members of the user object into the session, causing the circular reference. I'm just not sure why (admittedly probably my code)
This was a problem with session data being modified in a view.
After much digging, I found that it was a bug in the way partials are handled in 2.5.8. I submitted an issue, and subsequently a patch. (in case anyone needs this info at a future date) as npm is still serving up Express 2.5.8 AFAIK.
Thanks for your help #freakish and #Ryan

Resources