When I wrote my first JWT-based authentication implementation, it was local storage/cookie-based (I don’t remember very clearly).
Very soon I stumbled upon a blog post that told me not to use mechanisms that store information client side as they are vulnerable to XSS as well as to libraries and code on the front end simply accessing their contents using document.cookie or window.localStorage (I know right, everything is just so complicated).
The bulletproof solution to these problems was to store information in HTTPOnly Cookies (Or otherwise referred to as Server Cookies).
HTTPOnly Cookies are cookies that are set by your server on your client via a response, but the catch is these cookies cannot be accessed via any client-side code.
The catch is that for someone who was new to this space, it didn’t make a lot of sense. I had obviously worked with PHP sessions, but at that time I didn’t know that those sessions were also created via HTTPOnly Cookies. Even for Node.js based session-libraries, HTTPOnly cookies are the most common way of implementing sessions.
Even today I find it difficult to find a post or an article explaining HTTPOnly-based authentication. So I decided to write this small note on how to do so for all the developers who are confused today like I was back then a few years ago.

If you’re using Node.js with Express as your server framework, cookies can be set very easily using a single line of code:
response.cookie("jwt", jwtValue, { httpOnly: true, domain: '...yourdomain' });
When you need to read the cookies from a request later, express even parses all the cookies and converts them into an object.
req.cookies["jwt"] // or req.cookies.jwt
Check the reference to set a cookie via a response here.
Check the reference for accessing the cookie here.
Cookie setting from the backend to the frontend is only possible if the backend and frontend share the same domain or subdomain, otherwise, the browser itself blocks the cookies from being set and accessed.
So make sure you have a way (Like a proxy) to share your front end and back end on the same domain.
I wanted to mention this caveat since in your development environment, you would most likely be testing on localhost so this issue would not show up. It’s only you’ve pushed the setup to a deployed link that you notice what’s wrong and it has personally been a tale of a lot of confusion and frustration for me in the past.