pixelmund / svelte-kit-cookie-session

⚒️ Encrypted "stateless" cookie sessions for SvelteKit
MIT License
182 stars 11 forks source link

Express/Connect Integration #21

Closed pixelmund closed 2 years ago

pixelmund commented 3 years ago

This is available under 1.4.0-next.3 if anyone want's to give it a shot.

rafaucau commented 2 years ago

I am trying to use this with socket.io, but the socket.request.session is an empty object while in SvelteKit the same session has all the data

const wrap = (middleware) => (socket, next) => middleware(socket.request, {}, next);
io.use(wrap(sessionMiddleware({ secret: VITE_SESSION_SECRET })));
pixelmund commented 2 years ago

Hm i'm not familiar with socket.io. Can you share a repo i can look into?

rafaucau commented 2 years ago

Unfortunately this is not an open source project.

I made my own server file for adapter-node and everything works except websocket session

I will show parts of the code:

//svelte.config.js
//...
kit: {
  adapter: node({
    entryPoint: 'src/server/index.ts',
  }),
}
//...

https://github.com/sveltejs/kit/tree/master/packages/adapter-node#middleware

//index.ts
import { assetsMiddleware, prerenderedMiddleware, kitMiddleware } from '../../build/middlewares.js';
import polka from 'polka';
import websockets from './websockets';
import { Server } from 'socket.io';

const { PORT = 3000 } = process.env;
const app = polka();

app.all('*', assetsMiddleware, prerenderedMiddleware, kitMiddleware);
app.listen(PORT, () => console.log(`> Running on localhost:${PORT}`));

const { server } = app;
websockets(new Server(server));

https://socket.io/docs/v4/middlewares/#compatibility-with-express-middleware

//websockets.ts
import type { Server } from 'socket.io';;
import { sessionMiddleware } from 'svelte-kit-cookie-session';

export default function (io: Server): void {
    const { VITE_SESSION_SECRET } = process.env;

    const wrap = (middleware) => (socket, next) => middleware(socket.request, {}, next);
    io.use(wrap(sessionMiddleware({ secret: VITE_SESSION_SECRET })));

    io.on('connection', (socket) => {
        socket.on('message', async ({ text, room }) => {
            console.log(socket.request);
            console.log(socket.request.session);
        });
    });
}

Preempting questions, console.log(VITE_SESSION_SECRET) returns the same secret in SvelteKit and in the custom server. The session is created in SvelteKit. Here I just want to read it.

Theoretically, if the svelte-kit-cookie-session library works with Express, it should also work with socket.io

pixelmund commented 2 years ago

@rafaucau I've created a project to reproduce it and added a console.log(socket.request.session.data). The socket.request.session is expected to be empty since it's just a JS Proxy behind the scenes and accessing the data property "fills" or gets the data. Don't know if this makes sense. Try adding the console.log(socket.request.session.data).

pixelmund commented 2 years ago

I have updated the documentation, since this was the seconds time users where confused about session.request beeing empty on console.log, going to merge this now.

rafaucau commented 2 years ago

Ok, so console.log(socket.request.session.data); is {} when I send a message to websockets while the user is logged in the SvelteKit - there locals.session.data is not an empty object.

As if they are different sessions. I see that the kit.session cookie is in the request.

pixelmund commented 2 years ago

https://github.com/pixelmund/kit-cookie-session-socket.io-repro check out this repo, i have a very similar setup to what you provided. Set the session via the /session endpoint the counter should increase everytime you hit it. Now try connecting via socket.io-client and you should see the correct count.

Are you sure VITE_SESSION_SECRET is the same in kit and your custom entrypoint? This would be my only guess, because if i use a different secret in my websockets file the session data is just {}. And from the socket connection the cookie won't be deleted if the secret is wrong.

rafaucau commented 2 years ago

I found the cause. I use a single .env file. In Svelte I use import.meta.env while in my own server I have to use process.env. I run the application using env-cmd node build. It turned out that env-cmd removes the \ characters from the string, so the secrets were different.

Sorry for the inconvenience!