pixelmund / svelte-kit-cookie-session

⚒️ Encrypted "stateless" cookie sessions for SvelteKit
MIT License
184 stars 12 forks source link

Support for SvelteKit@next-415+ #42

Closed Starmism closed 2 years ago

Starmism commented 2 years ago

SvelteKit 415 had this extremely breaking change.

Any plans to update to either make your own version of a session, a la Lucia, or another replacement?

Zamiell commented 2 years ago

For people looking to encrypt their cookies right now, I guess the solution is to manually encrypt your own cookie data in "hooks.ts" using AES or something (e.g. crypto-js).

(This library seems to use zencrypt over crypto-js, which seems like a much worse option at first glance, I'm not sure why it was chosen.)

Here's an example of what I've done:

hooks.ts

import { SESSION_KEY } from "$env/static/private";
import type { Handle } from "@sveltejs/kit";
import * as cookie from "cookie";
import aes from "crypto-js/aes";

const COOKIE_NAME = "discordAccessToken";

export const handle: Handle = async ({ event, resolve }) => {
  // Before running the route logic.
  {
    const cookieHeader = event.request.headers.get("cookie") ?? "";
    const cookies = cookie.parse(cookieHeader);
    const discordAccessTokenEncrypted = cookies[COOKIE_NAME];

    if (
      // The type definition for "cookie.parse" is bugged, as non-existent cookies will be
      // undefined.
      // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
      discordAccessTokenEncrypted === undefined ||
      discordAccessTokenEncrypted === ""
    ) {
      event.locals.discordAccessToken = null;
    } else {
      const discordAccessToken = aes.decrypt(
        discordAccessTokenEncrypted,
        SESSION_KEY,
      );

      event.locals.discordAccessToken = discordAccessToken.toString();
    }
  }

  // Run the route logic.
  const response = await resolve(event);

  // After running the route logic.
  if (
    event.locals.shouldSetCookie &&
    event.locals.discordAccessToken !== null
  ) {
    const discordAccessTokenEncrypted = aes
      .encrypt(event.locals.discordAccessToken, SESSION_KEY)
      .toString();
    response.headers.set(
      "set-cookie",
      cookie.serialize(COOKIE_NAME, discordAccessTokenEncrypted, {
        path: "/",
        httpOnly: true,
        secure: true,
        sameSite: true,
      }),
    );
  }

  return response;
};
ranjanified commented 2 years ago

I am interested too in getting this addressed. Please let us know your plans at least, so that we can either try to look for alternatives or wait for the fix. On client side, user-profile and user session related state is implemented and stored in an encrypted cookie using this library ... which then I read on server to implement few critical functionalities.

pixelmund commented 2 years ago

First of all, zencrypt uses the WebCrypto API under the hood which SvelteKit already polyfills and is available in the different environments kit supports. It should also be faster than crypto-js, which might be more battle tested, for sure.

I marked your comment as off-topic because it's not what this issue was talking about.

pixelmund commented 2 years ago

I'm actually not sure what to do with the session store for now.
You can still access your sessions in the +page.server.js etc. files and return them for the client in the root +layout.server.js like so:

 export const load = (event) => {
  return {
     session: event.locals.session.data // This could also use your previous getSession function
  }
}

Access them via:

<script>
      import { page } from "$app/stores";
     $: console.log($page.data.session)
</script>
pixelmund commented 2 years ago

I've updated the project to use the new Kit Routing and also gone ahead and updated the README accordingly. I might consider adding a session store back but i think that's kinda tricky.

ranjanified commented 2 years ago

@pixelmund ... Date object is failing serialization if returned in load response.

check_serializability has kept Date out of consideration and so is throwing.

The expires populated on event.locals.session.data is adding to this ... Any thoughts please?

pixelmund commented 2 years ago

@ranjanified expires is now excluded from the event.locals.session.data getter, it's still beeing tracked internally but doesn't get exposed to the user anymore, you can try it with version 3.1.2.

ranjanified commented 2 years ago

Thanks a lot 🙏 @pixelmund ... Indeed, with 3.1.2 it's working fine now!!!