Using HTTPOnly Cookie in GET request (Retrieve user info from server using user_id cookie) - node.js

I'm following a tutorial where, after logging in a user, the backend sends a HTTPOnly cookie to the frontend containing the user id. However, HTTPOnly cookies are not accessible from the frontend (ex. document.cookie will not be able to read the cookie).
My question is, how is this cookie able to be used to retrieve user data? My thought process was that you would do something like GET 'server_address'/user/'id' where 'id' would be the user id stored in the cookie. But this obviously cannot work since the frontend can't access the cookie because it's HTTPOnly. A possible workaround I thought of was for the server to send the user id in the JSON response after logging in, but if this is the solution what is the point of even setting a cookie in the first place? That workaround makes it seem like there's no point in using cookies at all to save user sessions if you can just send the id back in the JSON response.
Please bear with me, this is my first time working with cookies. If it helps at all, I am using an Angular 4 frontend and a Node/Express backend

An httponly cookie is stored in the browser and is automatically resent back to the server with any future requests that match the origin of the cookie. So, the cookie can be used by the server to identify which client is making the request. If, for example, it was an authentication cookie that identifies who an authenticated user was, then the server would know which authenticated user this request is coming from and could use that information to authenticate the request and to know which user it was.
As you seem to already know, the httponly cookie cannot be retrieved by browser Javascript. That is the meaning of httponly.
how is this cookie able to be used to retrieve user data?
The cookie is sent to the server with any request from that client so the server can use the cookie to identify which user is making the request.
A possible workaround I thought of was for the server to send the user id in the JSON response after logging in
If the server wants the client to know the userID, then it should return it in the response. Or, it can stop using an httpOnly cookie so that the client can read the cookie. But, usually cookies that denote any sort of authenticated state are encrypted on the server so they often aren't intelligible to the client, even if they aren't httpOnly.
if this is the solution what is the point of even setting a cookie in the first place
Cookies are used for a variety of reasons. They allow the server to set some state that is associated with that particular client and each future request from that client will send that cookie back to the server so the server can have access to that info. The info could be authentication info, userID info, user preferences, etc...
That workaround makes it seem like there's no point in using cookies at all to save user sessions if you can just send the id back in the JSON response.
You don't really tell us much about your application, but cookies are often involved in implementing login and security and because they are automatically sent along with all future requests, they save the client the both of having to attach credentials to every single future request (because the cookie credential are automatically included). And, for requests such as a user clicking on a link in a page, the cookies are required because those types of links won't have credentials in them (and shouldn't).
My thought process was that you would do something like GET 'server_address'/user/'id'
So you plan to have any security associate with that request? If so, then you need an authentication scheme so that not just anyone can request info for any user. That's often what cookies are used for. You login, the server sets a credential into an encrypted cookie. That credential identifies a particular authenticated user so that for future requests from that same client, the server can use that cookie to see who the user is and whether they are authenticated.

We set cookie as httponly to prevent XSS, imagine if there is a security flaw that allow hacker the inject script <script>sendToHackerServer(document.cookie)...</script>, so user's cookie ( include session) will be sent to hacker server, then hacker can gain access to user data with that session. since these httponly cookie will be readable through http request only, session cookie will not be sent by injected script, and ur express backend can read these cookie with req.cookies.

Related

How can I secure my Node.js backend api data?

I may be a little confused about how backend servers work. Let's say I have a frontend React app with a login. The login information is stored in a database (i.e. MSSQL, MySQL, MongoDB) and I have a Node backend with routes for my app to fetch that information when a user is logging in or doing anything. When both my React app and server are hosted, I would make calls to the api and no confidential information (such as passwords) would be sent back to the client (just maybe a "success" message if the login information appears to be correct on the backend). My question is, what is stopping someone from finding the backend route and putting it into Insomnia to get the password or other sensitive information?
My first thought was to use express-session and auth on the backend to require a user to be logged in to an account to make such requests, but I think there are two issues with that:
How will that work when multiple users are logging in at once? Since the users are not technically physically visiting the api routes themselves, does session still know who is signing in to what account on the frontend? Will the second person logging in override the first person's session even though the first hasn't logged out yet?
If the auth doesn't kick in until a person is logged in, wouldn't someone be able to get the response password data from the login route itself?
Sorry if the question sounds dumb I'm just having a little trouble understanding the security aspect.
It sounds like there's a bit of a misunderstanding of how auth sessions work. There are two primary way sessions can work - either storing the sessions on the backend (older way), or storing session data in a cookie, typically a JWT (JSON Web Token). Cookies are bits of data that are passed from the server to the browser and anytime the browser makes a subsequent request to your server, it passes the cookie back too, so your server will always be able to get that data. The way this works for auth is the following:
A user signs into your application with credentials (username and password).
Your server validates the credentials by checking your database or wherever you're storing them and rejects the request if it fails. (Check out Auth0, Firebase Auth, or other auth services as doing this yourself can be a pain and open yourself up to potential vulnerabilities)
If the credentials are valid, the server generates a signed JWT token that includes data, like the username of the user.
The server responds with the body as well as a cookie containing the JWT, which the browser then stores.
The user requests some user-specific data from your server, and the browser sends the cookie with the JWT back to your server.
Your server validates that the JWT is valid by checking the signature. If it is valid, it uses the username from the token to get the user-specific data. If it is not valid, it rejects the request.
Because the signature occurs entirely on the server side (typically with some hashing algorithm and a secret key that you don't vend publicly), it would be nearly impossible for someone to spoof a JWT token signature. Therefor, your server is able to 1. trust that the JWT token is indeed valid if the signature is correct, and 2. find out what user is requesting data.
Here's a video that helps explain and visualize this: https://www.youtube.com/watch?v=soGRyl9ztjI
And here's a library for creating and validating JWTs in Node: https://www.npmjs.com/package/jsonwebtoken
Hopefully that answers your question!

Securely handling refresh token on a Vue application

I have a server backend that provides an access token and a refresh token when a user login is successful, and I want to store them somehow in the client's browser. For the access token, since it's short lived, I can store it in the browser's local storage, without having to worry too much. But for the refresh token, I'd like to set a more secure flow.
I've read this article fragment: Sending refresh token as an HttpOnly cookie, and using a cookie sounds like a safer approach to me, obviously not perfect though, so what I want to do is send the refresh token as a HttpOnly cookie to the Vue application.
So after logging in, for example, I'd like the server to set up that cookie and make the client include it with every request sent to the backend (is that how it should work?).
The problem I think I have, correct me if I am wrong please, is that since only the browser and not the javascript has access to that HttpOnly cookie, I can't make the library I use to make the requests (axios) to send the set refresh token alongside its future requests as a HttpOnly cookie as well.
How can I make that flow properly? Did I misunderstand something about how these cookies work?
Thank you in advance!

after successful login the user is redirected to the home page where the SPA loads. Is using session cookie with JWT a bad idea?

I have an express + postgres backend, and I'm using passport-facebook for FB oauth.
If a user hits my app at / without having a valid token in localStorage, they're taken to /login.
My /login page (where you're greeted with the familiar "Continue with Facebook" message) is server rendered (for various reasons). Upon clicking this button, I either verify the user if they exist and send them a session cookie with the initial JWT, or create a new user and send them a session cookie with the initial JWT. In both cases, the success condition is that they are redirected to / and served the SPA assets.
One of the first things the SPA does is take the JWT from the session cookie and put it into localstorage, and then deletes the cookie.
Is this a terrible approach, or is it valid in my use case?
You are using the session cookie as a means to store the JWT on the client. This means that you create a server session that will remain open until it expires, by spending server resources
Session cookies are not readable from javascript, so I guess you make a request to the server to get the JWT, right?
The process does not seem problematic, but I think you could optimize it by sending in your redirection process directly the JWT in the response using a regular cookie with set-cookie header. The cookie will be stored in client and you could access it directly

Authorization (and security, in general) for web and mobile apps of the same service

Help me to understand how to implement proper security for web and mobile apps, which would be enough for my case.
What I have:
Backend. Some sort of Stateless REST API, which consumes and produces JSON text. Does not store any kind of state.
Web application. Main portal to the service functionality.
Mobile applicaiton. Provides a reduced a set of functions to users of the service
I am not going to store any state on the backend. Instead, I am going to delegate this to both mobile and web browser applications.
Now here comes the question of security. How do I properly secure that?
Since session mechanism does not really work for me, I decided to go with JWT.
In my JWT I am going to store user Id and some other information like, for instance, user's privilegies.
For mobile app, I am going to send this token as a part of a response and the app will store it inside its secure store.
Each request it will send this token as Authorization Header.
For web app, I am going to send this token via HttpOnly cookie. This token, thus, will be included in every request from the client.
The problem now is a possible CSRF-attack. To address that I thought of the following. Each user "session" will be associated with CSRF token.
Since I can't store this token on the server (remember, stateless API), I can send it as encrypted (again, with JWT) token to the client via HttpOnly cookie and non-crypted in a regular cookie.
Now, every request the web client will use non-crypted token from the cookie and send it back to the server. The server will check if this token matches from the Encrypted one which is stored in HttpOnly cookie.
Also, I am going to use different URL endpoints for web and mobile web apps. What for? In order to keep auth mechanisms described above separate - I believe this will help me to keep the service secure.
Do you think it is an OK solution? What problems do you see here?
Thanks in advance.
In general, what you described looks good and pretty standard. However, if I understand correctly, the CSRF protection is flawed.
To make sure I understand correctly: a csrf token would be stored in an encrypted httpOnly cookie, only to be sent back to the server as reference. Another cookie would have the same value but unencrypted, in a plain (non-httpOnly) cookie, and the server would compare these two. What's the point? An attacker would still be able to create a webpage to have a user make an request to your website, and both cookies would still be sent.
The reference cookie is ok to be in the httpOnly cookie for reference, but the other one should not be a cookie. It could for example be a request header value that you add to all requests. The client could receive it in a response, but not as a cookie. With jQuery in the web app, you can use the beforeSend hook to add it to all subsequent requests as a header. This way an attacker could not make valid requests from another domain.

A different way to manage sessions

I'm working in a cookie-less way to manage sessions in my project (expressjs), keeping all session data server side and using a token at client side (previously generated by the server) to validate the session on every request.
A new token will be created on user login and kept hide somewhere in the page, then, on every request this token will be written to the request header and validated server side. at this point server will search for the token in a session store, lets say redis, and get the session data if the token is found or respond with a message of session expired otherwise.
There are some things i'm considering for this:
Redis keys are created on user login with a settled expiration.
Every time session data is found in redis i have to 'touch' the key
so expiration time gets postponed.
Token will be validated along side with the ip address of the client so can't be used by other person.
My question is if this is can be considered a secure way to work with, and if there is anything i'm missing here. Thanks
OK, cookies are required for storing session. Express does it the ideal way.
In express session(not cookiesession) it is completely stored at the server, only a key is sent to the client. The whole session is serialized to a key which is then sent. I assume you want that user cannot tamper with the session cookies. You can use httponly cookies to prevent tampering. They are only handled by browser and cannot be accessed by user. This prevents cookie theft or session hijacking. You can enable httponly cookies with:
app.use(express.session({cookie: { path: '/', httpOnly: true}, secret:'password'}));
Still you should use some encryption to prevent eavesdropping of cookies. Use secure : true for that. You can also mention where you want to store the session with redis, mongo or simply in memory.
The request token validation that you mention is a technique commonly used to prevent Cross-site request forgery. It keeps changing the token dynamically to keep user from getting the token. You can use this in express with csrf middleware.
app.use(express.csrf())
IP matching will not work as IP of user can change over time.

Resources