{"id":17480893,"url":"https://github.com/paratron/next-server-session","last_synced_at":"2026-02-26T02:41:49.205Z","repository":{"id":141688194,"uuid":"315148407","full_name":"Paratron/next-server-session","owner":"Paratron","description":"Functions to handle serverside session data and csrf tokens","archived":false,"fork":false,"pushed_at":"2021-01-27T22:03:42.000Z","size":524,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-19T01:16:26.718Z","etag":null,"topics":["csrf-tokens","nextjs","react","security","serverside-sessions","session-lifetime"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Paratron.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2020-11-22T22:53:14.000Z","updated_at":"2022-11-26T07:20:55.000Z","dependencies_parsed_at":null,"dependency_job_id":"d796db8e-ea7a-4d62-be33-5aaa457d3719","html_url":"https://github.com/Paratron/next-server-session","commit_stats":{"total_commits":75,"total_committers":1,"mean_commits":75.0,"dds":0.0,"last_synced_commit":"aff2e2ba33ff5f2557707dfb6d4a75ce99365c31"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Paratron%2Fnext-server-session","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Paratron%2Fnext-server-session/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Paratron%2Fnext-server-session/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Paratron%2Fnext-server-session/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Paratron","download_url":"https://codeload.github.com/Paratron/next-server-session/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238573672,"owners_count":19494596,"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":["csrf-tokens","nextjs","react","security","serverside-sessions","session-lifetime"],"created_at":"2024-10-18T22:06:25.240Z","updated_at":"2025-10-27T23:31:21.152Z","avatar_url":"https://github.com/Paratron.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# next-server-session\nFunctions to handle serverside session data and csrf tokens for nextJS 10.x\n\nThey can be used both in `getServerSideProps` as well as in API routes.\n\n\u003e __Heads up!__    \n\u003e This module provides a simple and effective mechanism to protect your application against [cross site request forgery](https://owasp.org/www-community/attacks/csrf) attacks.\n\n------------------------------------\n## API\n- [configure()](#configure)\n- [getSessionData()](#getSessionData)\n- [setSessionData()](#setSessionData)\n- [replaceSessionData()](#replaceSessionData)\n- [pluckSessionProperty()](#pluckSessionProperty)\n- [destroySession()](#destroySession)\n- [getCSRFToken()](#getCSRFToken)\n- [validateCSRFToken()](#validateCSRFToken)\n\n## Additional API\n- [createMemorySessionStore()](#createMemorySessionStore)\n- [createRedisSessionStore()](#createRedisSessionStore)\n- [createCookieHandler()](#createCookieHandler)\n\n## `configure()`\nIn order to be able to use the session mechanism, it needs to be initialized once on server startup. The most basic\nexample is this:\n\n```javascript\nconst { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_SERVER } = require(\"next/constants\");\n\nmodule.exports = (phase, { defaultConfig }) =\u003e {\n    if(phase === PHASE_PRODUCTION_SERVER || phase === PHASE_DEVELOPMENT_SERVER){\n        require(\"next-server-session\").configure();\n    }\n\n    return defaultConfig;\n}\n```\n\nBy calling `configure()` without providing any probs, you default to a in-memory session management with a default session\nlifetime of 30 minutes. If you want to modify the session lifetime, pass a session duration as `sessionMaxAgeMS`.\n\nYou should monitor your servers RAM consumption carefully when using this. If you notice a high load, you can swith to an\nexternal session storage like redis, memcached, a mySQL database or just the harddrive. \n\nIf you want to host your application on multiple servers behind a load balancer, you need to have a central external session store as well.\n\n\n\u003ch2 id=\"getSessionData\"\u003e\u003ccode\u003egetSessionData([polymorph]): Promise\u003c{}\u003e\u003c/code\u003e\u003c/h2\u003e\nThis method returns the current session object. If no session has been established so far, an empty object will be returned.\nCalling this method will _not_ establish a session and will _not_ set a cookie for your visitors.\n\n\u003e Typescript tip:    \n\u003e You can tell TS about the interface of your returned session object: `getSessionData\u003cT\u003e(...): Promise\u003cT\u003e`\n\n### Example usage in `getServerSideProps()`\nFetching the currently logged in user - if any.\n```typescript\nexport async function getServerSideProps(context: GetServerSidePropsContext){\n    const {user = null} = await getSessionData(context);\n    return {\n        props: {\n            user    \n        }    \n    }\n}\n```\n\n### Example usage in API routes\nReturn user data from an API endpoint, when logged in.\n```typescript\nexport default async function handler(req: NextApiRequest, res: NextApiResponse){\n    const {user = null} = await getSessionData(req, res);\n    if(!user){\n        res.status(403).end(\"Forbidden\");\n        return;        \n    }\n    res.json(fetchUserData(user));\n    res.end();        \n}\n```\n \n\u003ch2 id=\"setSessionData\"\u003e\u003ccode\u003esetSessionData([polymorph]): Promise\u0026lt;void\u0026gt;\u003c/code\u003e\u003c/h2\u003e\nThis method takes an object and merges it into a existing session object. Only given keys will be overwritten, the rest\nof the session object will be preserved. Calling the method will establish a new session, if none exists and write a session\ncookie.\n\n### Example usage in `getServerSideProps()`\nLog some actions of the user to modify the experience in other places.\n```typescript\nexport async function getServerSideProps(context: GetServerSidePropsContext){\n    await setSessionData({viewedPricingPage: true});    \n\n    return {\n        props: {\n            data: getPricingData()        \n        }    \n    }\n}\n```\n\n### Example usage in API routes\nPlace products in a cart and persist it in the session.\n```typescript\nexport default async function handler(req: NextApiRequest, res: NextApiResponse){\n    const {cart = {}} = await getSessionData(req, res);\n    const {article, amount} = req.body;\n    if(validateArticle(article)){\n        cart[article] = (cart[article] || 0) + parseInt(amount, 10);\n        await setSessionData(req, res, {cart});   \n    }    \n    res.end(\"ok\");      \n}\n```\n\n\u003ch2 id=\"replaceSessionData\"\u003e\u003ccode\u003ereplaceSessionData([polymorph]): Promise\u0026lt;void\u0026gt;\u003c/code\u003e\u003c/h2\u003e\nThis method will replace the whole session object with a new one. This will overwrite/remove all existing session data, so \nbe careful when using it.\n\n### Example usage in `getServerSideProps()`\nResets a multi-step form and all helper data. Still be careful with this!\n```typescript\nexport async function getServerSideProps(context: GetServerSidePropsContext){\n    await replaceSessionData({step: 1});    \n\n    return {\n        props: {\n        }    \n    }\n}\n```\n\n### Example usage in API routes\nA login example where any stale data from previous user sessions is reset.\n```typescript\nexport default async function handler(req: NextApiRequest, res: NextApiResponse){\n    const {username, password} = req.body;\n    let result = login(username, password);\n    if(result.user){\n        await replaceSessionData({user: result.user});\n        res.end(\"ok\");\n        return;\n    }\n    res.end(result.error);\n}\n```\n\n\u003ch2 id=\"pluckSessionProperty\"\u003e\u003ccode\u003epluckSessionProperty([polymorph]): Promise\u0026lt;any | null\u0026gt;\u003c/code\u003e\u003c/h2\u003e\nRemoves a property from the session object and returns it. Will return `null`, if the property does not exist.\n\n\u003e Typescript tip:    \n\u003e You can tell TS about the type of the returned value: `pluckSessionProperty\u003cT\u003e(...): Promise\u003cT | null\u003e`\n\n### Example usage in `getServerSideProps()`\nAn API handler might store any errors in the session and redirect back to the form. The errors are plucked from the session\nand displayed in the form once.\n```typescript\nexport async function getServerSideProps(context: GetServerSidePropsContext){\n    const formErrors = await pluckSessionProperty(context, \"formErrors\");\n\n    return {\n        props: {\n            formErrors        \n        }    \n    }\n}\n```\n\n### Example usage in API routes\nA user came from a referral link to a shop. The referral ID is applied ONCE to a purchase, then removed from the session.\n```typescript\nexport default async function handler(req: NextApiRequest, res: NextApiResponse){\n      const referrer = pluckSessionProperty(req, res, \"refId\");\n      res.end(processPurchase(referrer));\n}\n```\n\n\u003ch2 id=\"destroySession\"\u003e\u003ccode\u003edestroySession([polymorph]): Promise\u0026lt;void\u0026gt;\u003c/code\u003e\u003c/h2\u003e\nThis will drop the session data from the session store and mark the cookie to be expired and removed by the browser.\n\n### Example usage in `getServerSideProps()`\nThis will logout the current user, if a valid CSRF token has been passed. Will render the page, if the logout failed.\n```typescript\nexport async function getServerSideProps(context: GetServerSidePropsContext){\n    if(await validateCSRFToken(context.params.csrf)){\n        await destroySession();\n        return {\n            redirect: {\n                to: \"/\"\n            }    \n        }        \n    }\n\n    return {\n        props: {    \n        }    \n    }\n}\n```\n\n### Example usage in API routes\nSame logout example, but with a pure API route.\n```typescript\nexport default async function handler(req: NextApiRequest, res: NextApiResponse){\n    const {csrf} = req.body;\n    if(await validateCSRFToken(csrf)){\n        destroySession();\n        res.redirect(\"/\");\n        return;\n    }\n    res.redirect(\"/\");      \n}\n```\n\n\u003ch2 id=\"getCSRFToken\"\u003e\u003ccode\u003egetCSRFToken([polymorph]): Promise\u0026lt;string\u0026gt;\u003c/code\u003e\u003c/h2\u003e\nThis method generates a random string, stores it in the session and returns it. Use the CSRF token to prevent [cross site request forgery](https://owasp.org/www-community/attacks/csrf).\n\n### Example usage in `getServerSideProps()`\nThis generates a CSRF token that can be passed with any forms or requests to the API.\n```typescript\nexport async function getServerSideProps(context: GetServerSidePropsContext){\n    return {\n        props: {    \n            csrfToken: await getCSRFToken(context)\n        }    \n    }\n}\n```\n\n### Example usage in API routes\nA single page application might automatically receive new tokens from each API call to sign the\nnext request.\n```typescript\nexport default async function handler(req: NextApiRequest, res: NextApiResponse){\n    const {action, csrfToken} = req.body;\n    if(await validateCSRFToken(csrfToken)){\n        res.json({\n            result: performAction(action),\n            nextToken: await getCSRFToken(req, res)\n        });\n        res.end();\n        return;\n    }\n    res.status(400).end(\"Bad request\"); \n}\n```\n\n\u003ch2 id=\"validateCSRFToken\"\u003e\u003ccode\u003evalidateCSRFToken([polymorph]): Promise\u0026lt;boolean\u0026gt;\u003c/code\u003e\u003c/h2\u003e\nThis method validates a given csrf token against a previously generated random token already stored in the session.\nThis is used to prevent [cross site request forgery](https://owasp.org/www-community/attacks/csrf) attacks. Use this to protect any requests that perform\nactions in behalf of a user.\n\n### Example usage in `getServerSideProps()`\nAny page or request that performs an action for a user needs to be protected by a CSRF token.\n```typescript\nexport async function getServerSideProps(context: GetServerSidePropsContext){\n    if(await validateCSRFToken(context, context.param.csrf)){\n        const {user = null} = getSessionData(context);\n        performSomeAction(user);    \n    }\n        \n    return {\n        props: {    \n        }    \n    }\n}\n```\n\n### Example usage in API routes\n```typescript\nexport default async function handler(req: NextApiRequest, res: NextApiResponse){\n    if(await validateCSRFToken(req, res, req.body.csrfToken)){\n        performSomeAction();\n        res.end(\"ok\");    \n    }\n    res.status(400).end(\"Bad request\");   \n}\n```\n\n-----------------------\n\nThe following methods are internal factory functions for the default store and cookie handler.\n\n## `createMemorySessionStore(maxSessionAgeMS: number): SessionStore`\nReturns a new session store for in-memory storage of session objects. By default, it will keep\nsession objects for 30 minutes after they have been interacted with the last time (by getting or setting).\n\nIn case you want to modify the default max session age, you need to call this method and pass the result\nto the [`configure()`](#configure) method:\n\n```javascript\nconst { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_SERVER } = require(\"next/constants\");\n\nmodule.exports = (phase, { defaultConfig }) =\u003e {\n    if(phase === PHASE_PRODUCTION_SERVER || phase === PHASE_DEVELOPMENT_SERVER){\n        require(\"next-server-session\").configure({\n            sessionStore: createMemorySessionStore(10 * 60 * 1000) // 10 Minutes\n        });\n    }\n\n    return defaultConfig;\n}\n```\n\nI recomment that you implement your own session store when you want to keep your session data any place\nelse than in the memory of your current machine.\n\nTo create a compatible session store, you need to implement its TS interface:\n\n```typescript\ninterface SessionStore {\n    id: () =\u003e Promise\u003cstring\u003e;\n    get: (sessionId: string) =\u003e Promise\u003cany | null\u003e;\n    set: (sessionId: string, data: any) =\u003e Promise\u003cvoid\u003e;\n    merge: (sessionId: string, data: any) =\u003e Promise\u003cvoid\u003e;\n    destroy: (sessionId: string) =\u003e Promise\u003cany\u003e\n}\n```\n\nWhen implementing your own session store, you can resort to [the tests I wrote](https://github.com/Paratron/next-server-session/blob/master/src/index.test.ts#L51) for the memory\nsession store. \n\n## `createCookieHandler(cookieName: string = \"nextSession\", cookieConfig: any)`\nThis factory function creates a new cookie handler based on the [cookie](https://www.npmjs.com/package/cookie) package.\n\nIf you want to change the used cookie name or update any configuration, call the method and pass the\nresult to the [`configure()`](#configure) method.\n\nThe default cookie config is:\n\n```json\n{\n    \"httpOnly\": true,\n    \"sameSite\": true,\n    \"path\": \"/\",\n    \"secure\": false\n}\n```\n\nYou can pass any options, the `cookie` module can understand.\n\n```javascript\nconst { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_SERVER } = require(\"next/constants\");\n\nmodule.exports = (phase, { defaultConfig }) =\u003e {\n    if(phase === PHASE_PRODUCTION_SERVER || phase === PHASE_DEVELOPMENT_SERVER){\n        require(\"next-server-session\").configure({\n            cookieHandler: createCookieHandler(\"sId\", {\n              \"httpOnly\": true,\n              \"sameSite\": true,\n              \"path\": \"/basedir\",\n              \"secure\": true\n          })\n        });\n    }\n\n    return defaultConfig;\n}\n```\n\n\n## `createRedisSessionStore(maxSessionAgeMS: number, host?: string, port?: number, db?: number): SessionStore`\nIn version 1.2, I added a redis session store that works if you have the `redis` module from npm installed in your project.\n\nIt works like the memory session store, but connects and saves all session data on a given redis server.\n\n```javascript\nconst { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_SERVER } = require(\"next/constants\");\nconst { createRedisSessionStore } = require(\"next-server-session/dist/redisSessionStore\");\n\nmodule.exports = (phase, { defaultConfig }) =\u003e {\n    if(phase === PHASE_PRODUCTION_SERVER || phase === PHASE_DEVELOPMENT_SERVER){\n        require(\"next-server-session\").configure({\n            sessionStore: createRedisSessionStore(\n                10 * 60 * 1000, // 10 Minutes\n                \"192.168.178.1\",\n                6379\n            )\n        });\n    }\n\n    return defaultConfig;\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparatron%2Fnext-server-session","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fparatron%2Fnext-server-session","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparatron%2Fnext-server-session/lists"}