0

I have the following question. I have a NestJS back-end and a VueJS front-end. I want to notify the front-end when the back-end is done with a long running task. I thought using socket.io for this is a good solution.

I implemented the socket.io server on the back-end and the socket.io-client on the front-end and I can emit and receive messages.

At the back-end I use passport jwt for user authenthication and I save the user's JWT access_token inside a httpOnly (set-cookie) token. The front-end send the token (inside httpOnly cookie) with every request after successfull login.

Question: How can I send the access_token inside de httpOnly cookie to socket.io to authenticate the user and secure the connection?

Please provide me with some documentation or code examples. I'm stuck on this for 3 days.

Kind regards, Mike

Mike Evers
  • 185
  • 1
  • 4
  • 15
  • Does this answer your question? https://stackoverflow.com/questions/23851603/socket-io-not-sending-cookies-in-the-handshake-causing-the-request-to-stall – Michal Trojanowski Feb 16 '22 at 15:13
  • Applying withCrednetials: true does not set the cookie with the upgrade to 'websocket' transport. It only sends the cookie when transport is 'polling'. Can I set a NestJS (JWT) Guard on a NestJS WebSocketGateway? – Mike Evers Feb 16 '22 at 15:22

1 Answers1

0

This is how I'm using it in socket.io 4.4 with HTTPOnly cookies:

For client->server cookie transport: socket.request.headers.cookie contains the cookies that were present in the browser at the time the connection was established (when using the websocket transport). If your session cookie changes during a session (ex: due to session ID rotation), your client has to reconnect to force it to send the latest cookies. Make sure any in-progress messages finish before reconnecting.

For server->client cookie transport: This cannot be done through socket.io, so what I do is send the client a websocket message saying that there is a new session cookie waiting, then the client sends an ajax/http query to the server, which adds the new cookie to the response, which the browser then automatically saves. After that the client reconnects as explained above, so the server can see the new cookie with subsequent WS requests.

Note that this assumes everything runs on the same site.

I have not tested whether you also need to reconnect to update the cookie if you're using the polling transport rather than the websocket transport.

  • I have set `withCredentials: true` on my client side, but I am unable to see any cookies in my request header. I checked in my DevTools and also tried to log in the backend. Can you help me out on how exactly did you manage to send cookies? – Satej Bidvai Sep 21 '22 at 09:18
  • 1
    @SatejBidvai Do you see your cookies in the browser dev tools, and if you make an ordinary get/post to the server, do you see your cookies in those headers? That has to work before you'll be able to see them in socket.io in `socket.request.headers.cookie`. – Thunderbelch Sep 22 '22 at 10:29
  • I am able to see that the cookies have been set. I am able to see cookies in my request headers in my normal API calls to the server but not for my socket IO network calls. – Satej Bidvai Sep 22 '22 at 10:44
  • 1
    Did you perhaps set the path parameter on your cookie to something that wouldn't include the socket.io endpoint? My cookie settings are `path=/; Secure; SameSite=Lax; HTTPOnly`. I then read the cookie with: `socketClient.on('message', async function (requestJSON, respond) { //find cookies in: socketClient.request.headers.cookie }` – Thunderbelch Sep 23 '22 at 11:04
  • Also, what socket.io transport are you using? I believe the above worked with both the websocket and polling transports. Also check your socket.io version. I'm using 4.4.0. – Thunderbelch Sep 23 '22 at 11:08
  • I have the exact same cookie, only the secure is false. I am using WebSocket transport. In all my API calls, I am able to see cookies in my headers but not for my WebSocket calls. Do check out this question for more details: https://stackoverflow.com/questions/73787800/not-able-to-send-httponly-cookies-using-socket-io-client – Satej Bidvai Sep 23 '22 at 15:45
  • 1
    It works for me even with `withCredentials: false`, so not sure what the issue is. I was very happy to find a way to use HTTPOnly cookies with web sockets for better security. Are you only checking for the cookie in the browser's network tab, or have you tried the server side code I posted 3 comments above? Is your socket.io path & domain the same as in the cookie? – Thunderbelch Sep 24 '22 at 12:39
  • So actually my server is running on localhost:5000 but the socket server URL which I am using is the hosted one. Does the cookie only work for the origin it was created from? Like if I have my socket server also at localhost:5000 it should work? – Satej Bidvai Sep 24 '22 at 14:52
  • 1
    Yes, that is correct! – Thunderbelch Sep 25 '22 at 21:40