{"id":13599178,"url":"https://github.com/pixelmund/svelte-kit-cookie-session","last_synced_at":"2025-05-16T06:04:17.690Z","repository":{"id":37411092,"uuid":"352368757","full_name":"pixelmund/svelte-kit-cookie-session","owner":"pixelmund","description":"⚒️ Encrypted \"stateless\" cookie sessions for SvelteKit","archived":false,"fork":false,"pushed_at":"2025-01-07T09:47:07.000Z","size":553,"stargazers_count":188,"open_issues_count":0,"forks_count":12,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-09T06:07:25.746Z","etag":null,"topics":["cookie","cookie-session","session","session-handler","svelte","svelte-kit","sveltekit"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pixelmund.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-03-28T15:41:20.000Z","updated_at":"2025-03-02T19:00:58.000Z","dependencies_parsed_at":"2024-01-16T23:26:00.383Z","dependency_job_id":"8a5c0310-df78-49a8-960e-c108198c2d00","html_url":"https://github.com/pixelmund/svelte-kit-cookie-session","commit_stats":{"total_commits":152,"total_committers":2,"mean_commits":76.0,"dds":0.07894736842105265,"last_synced_commit":"c05dd88b7e63d80d10b298ca08b9e21d373e65a3"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelmund%2Fsvelte-kit-cookie-session","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelmund%2Fsvelte-kit-cookie-session/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelmund%2Fsvelte-kit-cookie-session/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pixelmund%2Fsvelte-kit-cookie-session/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pixelmund","download_url":"https://codeload.github.com/pixelmund/svelte-kit-cookie-session/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254478186,"owners_count":22077675,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cookie","cookie-session","session","session-handler","svelte","svelte-kit","sveltekit"],"created_at":"2024-08-01T17:01:00.537Z","updated_at":"2025-05-16T06:04:17.668Z","avatar_url":"https://github.com/pixelmund.png","language":"TypeScript","funding_links":[],"categories":["Enhancers/Extensions"],"sub_categories":["The _How To's?_"],"readme":"# Svelte Kit Cookie Session [![License](https://img.shields.io/github/license/pixelmund/svelte-kit-cookie-session.svg)](https://github.com/pixelmund/svelte-kit-cookie-session) [![Latest Stable Version](https://img.shields.io/npm/v/svelte-kit-cookie-session.svg)](https://www.npmjs.com/package/svelte-kit-cookie-session)\n\n⚒️ Encrypted \"stateless\" cookie sessions for SvelteKit\n\n---\n\n**This [SvelteKit](https://kit.svelte.dev) backend utility** allows you to create a session to be stored in the browser cookies via an encrypted seal. This provides strong client/\"stateless\" sessions.\n\nThe 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.\n\n---\n\n## 📚\u0026nbsp;\u0026nbsp;Table of Contents\n\n1. [Upgrading](#upgrading)\n1. [Installation](#installation)\n1. [Usage](#usage)\n1. [Initializing](#initializing)\n1. [Secret Rotation](#secret-rotation)\n1. [Setting the Session](#setting-the-session)\n1. [Accessing the Session](#accessing-the-session)\n1. [Destroying the Session](#destroying-the-session)\n1. [Refreshing the Session](#refresh-the-session-with-the-same-data-but-renew-the-expiration-date)\n1. [Configure Expiry Date](#configure-expiry-date)\n1. [Save unsaved session with the initial data](#save-unsaved-session-with-the-initial-data)\n\n**By default the cookie has an ⏰ expiration time of 7 days**, set via [`expires`] which should be a `number` in either `days | hours | minutes | seconds` configurable by the `expires_in` option.\n\n## Upgrading\n\n#### Version 3.x to 4.x\n\nThe internal encryption library changed to the [@noble/ciphers](https://github.com/paulmillr/noble-ciphers) which is up to 35% faster than the previous implementation. The encryption should also now be even more secure.\nBecause of the change of the encryption library we have an major version bump. You now have to provide a secret with an exact length of 32 characters or bytes. You can use [Password Generator](https://1password.com/password-generator/) to generate strong secrets. \n\n## Installation\n\nInstall into `dependencies`\n\n```bash\nnpm i svelte-kit-cookie-session\n\nyarn add svelte-kit-cookie-session\n\npnpm add svelte-kit-cookie-session\n```\n\nUpdate your `app.d.ts` file to look something like:\n\n```ts\nimport type { Session } from 'svelte-kit-cookie-session';\n\ntype SessionData = {\n\tviews: number;\n};\n\n// See https://kit.svelte.dev/docs/types#app\n// for information about these interfaces\ndeclare global {\n\tnamespace App {\n\t\t// interface Error {}\n\t\tinterface Locals {\n\t\t\tsession: Session\u003cSessionData\u003e;\n\t\t}\n\t\tinterface PageData {\n\t\t\t// can add any properties here, return it from your root layout\n\t\t\tsession: SessionData;\n\t\t}\n\t\t// interface Platform {}\n\t}\n}\n\nexport {};\n```\n\n## Usage\n\nYou can find some examples in the src/routes/tests folder [Tests](/src/routes/tests).\n\nThe secret is a private key or list of private keys you must pass at runtime, it should be `32 characters` long. Use [Password Generator](https://1password.com/password-generator/) to generate strong secrets.\n\n⚠️ You should always store secrets in secret environment variables on your platform.\n\n### Initializing\n\n\u003e src/hooks.server.ts\n\n```js\nimport { handleSession } from 'svelte-kit-cookie-session';\n\n// You can do it like this, without passing a own handle function\nexport const handle = handleSession({\n\t// Optional initial state of the session, default is an empty object {}\n\t// init: (event) =\u003e ({\n\t// \tviews: 0\n\t// }),\n\t// chunked: true // Optional, default is false - if true, the session will be chunked into multiple cookies avoiding the browser limit for cookies\n\tsecret: 'SOME_COMPLEX_SECRET_32_CHARSLONG'\n});\n\n// Or pass your handle function as second argument to handleSession\n\nexport const handle = handleSession(\n\t{\n\t\tsecret: 'SOME_COMPLEX_SECRET_32_CHARSLONG'\n\t},\n\t({ event, resolve }) =\u003e {\n\t\t// event.locals is populated with the session `event.locals.session`\n\n\t\t// Do anything you want here\n\t\treturn resolve(event);\n\t}\n);\n```\n\nIn case you're using [sequence()](https://kit.svelte.dev/docs/modules#sveltejs-kit-hooks-sequence), do this\n\n```js\nconst sessionHandler = handleSession({\n\tsecret: 'SOME_COMPLEX_SECRET_32_CHARSLONG'\n});\nexport const handle = sequence(sessionHandler, ({ resolve, event }) =\u003e {\n\t// event.locals is populated with the session `event.locals.session`\n\t// event.locals is also populated with all parsed cookies by handleSession, it would cause overhead to parse them again - `event.locals.cookies`.\n\t// Do anything you want here\n\treturn resolve(event);\n});\n```\n\n### Secret rotation\n\nis supported. It allows you to change the secret used to sign and encrypt sessions while still being able to decrypt sessions that were created with a previous secret.\n\nThis is useful if you want to:\n\n- rotate secrets for better security every two (or more, or less) weeks\n- change the secret you previously used because it leaked somewhere (😱)\n\nThen you can use multiple secrets:\n\n**Week 1**:\n\n```js\nexport const handle = handleSession({\n\tsecret: 'SOME_COMPLEX_SECRET_32_CHARSLONG'\n});\n```\n\n**Week 2**:\n\n```js\nexport const handle = handleSession({\n\tsecret: [\n\t\t{\n\t\t\tid: 2,\n\t\t\tsecret: 'SOME_OTHER_COMPLEX_SECR_32_CHARS'\n\t\t},\n\t\t{\n\t\t\tid: 1,\n\t\t\tsecret: 'SOME_COMPLEX_SECRET_32_CHARSLONG'\n\t\t}\n\t]\n});\n```\n\nNotes:\n\n- `id` is required so that we do not have to try every secret in the list when decrypting (the `id` is part of the cookies value).\n- The secret used to encrypt session data is always the first one in the array, so when rotating to put a new secret, it must be first in the array list\n- Even if you do not provide an array at first, you can always move to array based secret afterwards, knowing that your first password (`string`) was given `{id:1}` automatically.\n\n### Setting The Session\n\nSetting the session can be done in two ways, either via the `set` method or via the `update` method.\n\n`If the session already exists, the data gets updated but the expiration time stays the same`\n\n\u003e src/routes/counter/+page.server.js\n\n```js\n/** @type {import('@sveltejs/kit').Actions} */\nexport const actions = {\n\tdefault: async ({ locals }) =\u003e {\n\t\tconst { counter = 0 } = locals.session.data;\n\n\t\tawait locals.session.set({ counter: counter + 1 });\n\n\t\treturn {};\n\t}\n};\n```\n\n`Sometimes you don't want to get the session data first only to increment a counter or some other value, that's where the update method comes in to play.`\n\n\u003e src/routes/counter/+page.server.ts\n\n```js\n/** @type {import('@sveltejs/kit').Actions} */\nexport const actions = {\n\tdefault: async ({ locals, request }) =\u003e {\n\t\tawait locals.session.update(({ count }) =\u003e ({ count: count ? count + 1 : 0 }));\n\t\treturn {};\n\t}\n};\n```\n\n### Accessing The Session\n\n`After initializing the session, your locals will be filled with a session object, we automatically set the cookie if you set the session via locals.session.set({}) to something and receive the current data via locals.session.data only.`\n\n\u003e src/routes/+layout.server.js\n\n```js\n/** @type {import('@sveltejs/kit').LayoutServerLoad} */\nexport function load({ locals, request }) {\n\treturn {\n\t\tsession: locals.session.data\n\t};\n}\n```\n\n\u003e src/routes/+page.svelte\n\n```svelte\n\u003cscript\u003e\n\timport { page } from '$app/stores';\n\t$: session = $page.data.session;\n\u003c/script\u003e\n```\n\n\u003e src/routes/auth/login/+page.server.js\n\n```js\n/** @type {import('@sveltejs/kit').PageData} */\nexport function load({ parent, locals }) {\n\tconst { session } = await parent();\n\t// or\n\t// locals.session.data.session;\n\n\n\t// Already logged in:\n\tif(session.userId) {\n\t\tthrow redirect(302, '/')\n\t}\n\n\treturn {};\n}\n```\n\n### Destroying the Session\n\n\u003e src/routes/logout/+page.server.js\n\n```js\n/** @type {import('@sveltejs/kit').Actions} */\nexport const actions = {\n\tdefault: async () =\u003e {\n\t\tawait locals.session.destroy();\n\t\treturn {};\n\t}\n};\n```\n\n### Refresh the session with the same data but renew the expiration date\n\n\u003e src/routes/refresh/+page.server.js\n\n```js\n/** @type {import('@sveltejs/kit').Actions} */\nexport const actions = {\n\tdefault: async () =\u003e {\n\t\tawait locals.session.refresh(/** Optional new expiration time in days */);\n\t\treturn {};\n\t}\n};\n```\n\n### Refresh the session expiration on every request `Rolling` -\u003e default is false!\n\nYou can also specify a percentage from 1 to 100 which refreshes the session when a percentage of the expiration date is met.\n\n\u003e Note this currently only fires if a session is already existing\n\n```js\nhandleSession({\n\trolling: true // or 1-100 for percentage o the expiry date met,\n});\n```\n\n### Configure Expiry Date\n\nYou can configure the expiry date of the session cookie via the `expires` option. It should be a `number` in either `days | hours | minutes | seconds`.\n\n```js\nhandleSession({\n\texpires: 160, // 160 minutes\n\texpires_in: 'minutes', // minutes | hours | days | seconds\n});\n```\n\n### Save unsaved session with the initial data\n\nYou can save unsaved sessions with the initial data via the `saveUninitialized` option. It should be a `boolean` and the default is `false`.\n\n```js\nhandleSession({\n\tinit: () =\u003e ({ views: 0 }),\n\tsaveUninitialized: true,\n});\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpixelmund%2Fsvelte-kit-cookie-session","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpixelmund%2Fsvelte-kit-cookie-session","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpixelmund%2Fsvelte-kit-cookie-session/lists"}