0.2.3 • Published 4 years ago

svelte-kit-cookie-session v0.2.3

Weekly downloads
-
License
MIT
Repository
github
Last release
4 years ago

Svelte Kit Cookie Session License Latest Stable Version

⚒️ Encrypted "stateless" cookie sessions for SvelteKit


This SvelteKit backend utility allows you to create a session to be stored in the browser cookies via a encrypted seal. This provides strong client/"stateless" sessions.

The seal stored on the client contains the session data, not your server, making it a "stateless" session from the server point of view. This is a different take than express-session where the cookie contains a session ID to then be used to map data on the server-side.


By default the cookie has an ⏰ expiration time of 7 days, set via expires which should be a number in days.


Installation

npm i svelte-kit-cookie-session

yarn add svelte-kit-cookie-session

Usage

You can find real-world examples in the examples folder.

The secret is a private key you must pass at runtime, it has to be at least 32 characters long. Use Password Generator to generate strong passwords.

⚠️ You should always store passwords in secret environment variables on your platform.

Initializing

src/hooks.ts || src/hooks/index.ts

import { initializeSession } from "svelte-kit-cookie-session";
import type { GetContext, GetSession, Handle } from "@sveltejs/kit";

export const getContext: GetContext = async function ({ headers }) {
  const session = initializeSession(headers, {
    secret: "SOME_SECRET_AT_LEAST_32_CHARACTERS_LONG",
    cookie: { path: "/" },
  });

  return {
    session,
    db,
  };
};

export const getSession: GetSession<{}> = async function ({ context }) {
  return context.session.data;
};

export const handle: Handle<{}> = async function (request, render) {
  const response = await render(request);

  return {
    ...response,
    headers: {
      ...response.headers,
      ...(request.context as { session: { "Set-Cookie": string } }).session,
    },
  };
};

Setting The Session

src/routes/login.ts

import type { RequestHandler } from "@sveltejs/kit";

export const post: RequestHandler = function ({ context }) {
  context.session.data = {
    user: "test",
    email: "test@test.com",
  };

  /** Session Cookie will by encrypted and automatically set onto the Set-Cookie Header, thanks to JS Proxies */

  return {
    body: {
      success: true,
    },
  };
};

Destroying the Session

src/routes/logout.ts

import type { RequestHandler } from "@sveltejs/kit";

export const post: RequestHandler = function ({ context }) {
  context.session.destroy = true;

  /** Session Cookie will by destroyed */

  return {
    body: {
      success: true,
    },
  };
};

Refreshing the Session with new Data but keep the expiration date

src/routes/refresh.ts

import type { RequestHandler } from "@sveltejs/kit";

export const get: RequestHandler = async function ({ context }) {
  const session = context.session.data;

  if (!session?.theme) {
    (context.session as { data: { theme: string } }).data = { theme: "dark" };
  }

  if (session.theme === "dark") {
    session.theme = "light";
  } else {
    session.theme = "dark";
  }

  context.session.data = session;
  context.session.refresh = true;

  return {
    body: {
      theme: context.session.data.theme,
    },
  };
};

Advanced Usage

src/lib/session.ts

Create a custom session store which handles persisting the session

import { session as sessionStore } from "$app/stores";

/** @type {(method: 'POST' | 'PUT' | 'DELETE', value: any) => any} */
function handleSession(method, value) {
  fetch("/session", {
    method,
    body: method !== "DELETE" ? JSON.stringify(value) : undefined,
    credentials: "include",
    headers: {
      "Content-Type": "application/json",
    },
    cache: "no-cache",
  }).then(() => {});
}

/** @type {{set: (value: any) => void, update: (value: any) => void, destroy: () => void, subscribe: import("svelte/store").Writable['subscribe']}} */
export const session = {
  set: (value) => {
    sessionStore.set(value);
    handleSession("POST", value);
  },
  update: (value) => {
    sessionStore.set(value);
    handleSession("PUT", value);
  },
  destroy: () => {
    sessionStore.set({});
    handleSession("DELETE");
  },
  subscribe: sessionStore.subscribe,
};

src/routes/session/index.js

This is the corresponding endpoint for the custom session store, which handles the different methods.

⚠️ You probably want to secure this somehow, im up for suggestions!

/** @type {import('@sveltejs/kit').RequestHandler} */
export async function post({ context, body }) {
  context.session.data = body;

  return {
    body: context.session.data,
  };
}

/** @type {import('@sveltejs/kit').RequestHandler} */
export async function put({ context, body }) {
  context.session.data = body;
  context.session.refresh = true;

  return {
    body: context.session.data,
  };
}

/** @type {import('@sveltejs/kit').RequestHandler} */
export async function del({ context }) {
  context.session.destroy = true;

  return {
    body: {
      ok: true,
    },
  };
}
3.4.0

2 years ago

3.4.1

2 years ago

3.3.1

3 years ago

3.3.0

3 years ago

3.3.2

3 years ago

3.2.2

3 years ago

3.2.1

3 years ago

3.2.0

3 years ago

3.1.2

3 years ago

3.1.1

3 years ago

3.1.0

3 years ago

3.1.0-next.6

3 years ago

3.1.0-next.1

3 years ago

3.1.0-next.5

3 years ago

3.1.0-next.4

3 years ago

3.1.0-next.3

3 years ago

3.1.0-next.2

3 years ago

3.0.0-next.2

3 years ago

3.0.0-next.1

3 years ago

3.0.0-next.4

3 years ago

3.0.0-next.3

3 years ago

3.0.0-next.5

3 years ago

3.0.4

3 years ago

3.0.3

3 years ago

3.0.2

3 years ago

3.0.1

3 years ago

3.0.6

3 years ago

3.0.5

3 years ago

3.0.0

3 years ago

2.1.4

3 years ago

2.1.3

3 years ago

1.4.0

4 years ago

1.4.0-next.4

4 years ago

2.0.3

3 years ago

2.0.2

3 years ago

2.0.5

3 years ago

2.0.4

3 years ago

2.0.1

4 years ago

2.0.0

4 years ago

2.1.0-next.2

3 years ago

2.1.0-next.1

3 years ago

2.1.0-next.3

3 years ago

2.1.2

3 years ago

2.1.1

3 years ago

2.1.0

3 years ago

1.4.0-next.1

4 years ago

1.4.0-next.2

4 years ago

1.4.0-next.3

4 years ago

1.3.2-0.1

4 years ago

1.3.2-0.2

4 years ago

1.3.3

4 years ago

1.3.2

4 years ago

1.3.1

4 years ago

1.3.0

4 years ago

1.2.4

4 years ago

1.2.3

4 years ago

1.2.0

4 years ago

1.2.2

4 years ago

1.2.1

4 years ago

1.1.1

4 years ago

1.1.0

4 years ago

1.1.5

4 years ago

1.1.4

4 years ago

1.1.3

4 years ago

1.1.2

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.6

4 years ago

1.0.5

4 years ago

1.0.4

4 years ago

1.0.3

4 years ago

1.0.0

4 years ago

0.3.9

4 years ago

0.3.11

4 years ago

0.3.10

4 years ago

0.4.5

4 years ago

0.4.4

4 years ago

0.4.7

4 years ago

0.3.8

4 years ago

0.4.6

4 years ago

0.4.1

4 years ago

0.4.0

4 years ago

0.4.3

4 years ago

0.4.2

4 years ago

0.3.0

4 years ago

0.3.6

4 years ago

0.3.5

4 years ago

0.2.9

4 years ago

0.3.7

4 years ago

0.3.2

4 years ago

0.3.1

4 years ago

0.3.4

4 years ago

0.3.3

4 years ago

0.2.1

4 years ago

0.2.0

4 years ago

0.2.7

4 years ago

0.1.8

4 years ago

0.2.6

4 years ago

0.1.7

4 years ago

0.2.8

4 years ago

0.2.3

4 years ago

0.1.4

4 years ago

0.2.2

4 years ago

0.2.4

4 years ago

0.1.5

4 years ago

0.1.2

4 years ago

0.1.1

4 years ago

0.1.0

4 years ago

0.0.2

4 years ago

0.0.1

4 years ago