You need authentication in nodejs.
JWT is a half-baked solution. Don't pretend it is secure because it is popular.
Either way you need to learn session based authentication once and for all.
Setup
The basic MERN app setup.
- Create a basic express app, a react frontend
- Connect mongodb
- Add routes, controllers, models et cetra
- Connect to mongo via atlas, host db (render.com), host your frontend (netlify).
My cors config in server.js looks like this
app.use(
cors({
origin: 'your site',
methods: ['GET', 'POST', 'PATCH', 'DELETE'],
allowedHeaders: ['Origin', 'Content-Type', 'Accept'],
credentials: true,
})
)
Also, on the frontend, requests are sent with the credentials flag.
await axios.post(`${baseUrl}/tasks`, payload, {
withCredentials: true,
headers: {
'Content-Type': 'application/json',
}})
Pretty straightforward.
You can view the entire repo here.
Authentication
Spoiler.
Mind f##k.
For simplicity, we'll only talk about login here.
Every time I login, meaning after all the validations have passed and I finally move to the code where the session for the user needs to be created and stored. I do it with this logic.
// finally login and create a session
const session_id = crypto.randomUUID()
res.cookie('session_id', session_id.toString(), {
maxAge: 86400000,
httpOnly: true,
secure: true,
sameSite: 'none',
partitioned: true,
// sameSite: 'strict',
})
addSession(session_id, doc._id)
The addSession is a helper function that uses the native crypto package to register a session in the server memory.
So auth is straightforward.
Frontend creds -> validations -> set cookie in headers as a response -> the client sends that cookie w every request, making it clear that it is signed in
sameSite attribute
Cookies with
sameSite: none
are third party cookies
Notice that I've the sameSite:'strict'
property commented out. This is because my frontend and backend are on different domains, so this is a cross-site request according to CORS and will naturally get blocked.
But this brings with it, it's own set of problems.
CSRF attacks
Not to mention, Chrome won't even ALLOW my cookies now. This is because I've got third party cookies blocked.
But there's a way to solve this problem.
CHIPS
As of 2024, Chrome has started a gradual blockage of 3rd party cookies.
Cookies withsameSite=none; Secure and Partitioned attribute unset
operating in cross-contexts are now counted as third party cookies and CHIPS, the Storage Access API, and Related Website Sets are the only ways to read and write cookies from cross-contexts.
This can be a real problem if your server is on a different domain than your websites.
This can be a real problem if your server is on a different domain than your websites.
CHIPS or Cookies Having Independent Partitioned State.
Basically set the partitioned attr to true in your cookie options and voila it should work.
Express bug
Unfortunately, it's not always roses and sunshine.
res.cookie()
has a bug which doesn't set the partition attribute. So my code above, doesn't set the partitioned attribute to true in the response header.
Browser behaviours
Here are the errors that I've encountered.
Firefox
In firefox, it somehow works
Even though I've got my third party cookie blockage set to true. This might even be a firefox bug.
It shows this warning
Chrome
In chrome, with 3rd party cookies blocked. Nothing works.
Sessions authentication will not work. Period.
However with 3rd party cookies enabled, I get this warning.
Conclusion
I just wanted to implement session based authentication.
GET
requests will work, regardless of even if sameSite is set to strict (i guess). But what do i do now.
Either express fixes the cookie issue
or
I find a way to bypass cors altogether.
either way, stackoverflow
here I come.
Top comments (0)