{"id":13484181,"url":"https://github.com/fastify/fastify-cookie","last_synced_at":"2025-05-14T09:12:33.478Z","repository":{"id":25037823,"uuid":"103030737","full_name":"fastify/fastify-cookie","owner":"fastify","description":"A Fastify plugin to add cookies support","archived":false,"fork":false,"pushed_at":"2025-05-01T11:35:13.000Z","size":373,"stargazers_count":278,"open_issues_count":5,"forks_count":67,"subscribers_count":17,"default_branch":"main","last_synced_at":"2025-05-12T09:24:21.098Z","etag":null,"topics":["fastify","fastify-plugin"],"latest_commit_sha":null,"homepage":"https://npmjs.com/package/@fastify/cookie","language":"JavaScript","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/fastify.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,"zenodo":null},"funding":{"github":"fastify","open_collective":"fastify"}},"created_at":"2017-09-10T13:17:29.000Z","updated_at":"2025-05-12T04:58:58.000Z","dependencies_parsed_at":"2024-01-23T20:11:27.157Z","dependency_job_id":"5344bf63-318b-4dee-a01b-8c51d1a332d3","html_url":"https://github.com/fastify/fastify-cookie","commit_stats":{"total_commits":313,"total_committers":67,"mean_commits":"4.6716417910447765","dds":0.7731629392971247,"last_synced_commit":"f2aed09e4098aebac09dc5531d27229ac0737bb6"},"previous_names":[],"tags_count":76,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-cookie","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-cookie/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-cookie/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fastify%2Ffastify-cookie/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fastify","download_url":"https://codeload.github.com/fastify/fastify-cookie/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253943582,"owners_count":21988294,"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":["fastify","fastify-plugin"],"created_at":"2024-07-31T17:01:20.317Z","updated_at":"2025-05-14T09:12:33.455Z","avatar_url":"https://github.com/fastify.png","language":"JavaScript","readme":"# @fastify/cookie\n\n[![CI](https://github.com/fastify/fastify-cookie/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/fastify/fastify-cookie/actions/workflows/ci.yml)\n[![NPM version](https://img.shields.io/npm/v/@fastify/cookie.svg?style=flat)](https://www.npmjs.com/package/@fastify/cookie)\n[![neostandard javascript style](https://img.shields.io/badge/code_style-neostandard-brightgreen?style=flat)](https://github.com/neostandard/neostandard)\n\nA plugin for [Fastify](http://fastify.dev/) that adds support for reading and\nsetting cookies.\n\nThis plugin's cookie parsing works via Fastify's `onRequest` hook. Therefore,\nyou should register it before any other `onRequest` hooks that will depend\nupon this plugin's actions.\n\nIt is also possible to [import the low-level cookie parsing and serialization functions](#importing-serialize-and-parse).\n\n## Install\n```sh\nnpm i @fastify/cookie\n```\n\n### Compatibility\n| Plugin version | Fastify version |\n| ---------------|-----------------|\n| `\u003e=10.x`       | `^5.x`          |\n| `\u003e=7.x \u003c10.x`  | `^4.x`          |\n| `\u003e=4.x \u003c7.x`   | `^3.x`          |\n| `\u003e=2.x \u003c4.x`   | `^2.x`          |\n| `^1.x`         | `^1.x`          |\n\nPlease note that if a Fastify version is out of support, then so are the corresponding versions of this plugin\nin the table above.\nSee [Fastify's LTS policy](https://github.com/fastify/fastify/blob/main/docs/Reference/LTS.md) for more details.\n\n## Example\n\n```js\nconst fastify = require('fastify')()\n\nfastify.register(require('@fastify/cookie'), {\n  secret: \"my-secret\", // for cookies signature\n  hook: 'onRequest', // set to false to disable cookie autoparsing or set autoparsing on any of the following hooks: 'onRequest', 'preParsing', 'preHandler', 'preValidation'. default: 'onRequest'\n  parseOptions: {}  // options for parsing cookies\n})\n\nfastify.get('/', (req, reply) =\u003e {\n  const aCookieValue = req.cookies.cookieName\n  // `reply.unsignCookie()` is also available\n  const bCookie = req.unsignCookie(req.cookies.cookieSigned);\n  reply\n    .setCookie('foo', 'foo', {\n      domain: 'example.com',\n      path: '/'\n    })\n    .cookie('baz', 'baz') // alias for setCookie\n    .setCookie('bar', 'bar', {\n      path: '/',\n      signed: true\n    })\n    .send({ hello: 'world' })\n})\n```\n\n## TypeScript Example\n\n```ts\nimport type { FastifyCookieOptions } from '@fastify/cookie'\nimport cookie from '@fastify/cookie'\nimport fastify from 'fastify'\n\nconst app = fastify()\n\napp.register(cookie, {\n  secret: \"my-secret\", // for cookies signature\n  parseOptions: {}     // options for parsing cookies\n} as FastifyCookieOptions)\n```\n\n## Importing `serialize` and `parse`\n\n```js\nconst { serialize, parse } = require('@fastify/cookie')\nconst fastify = require('fastify')()\n\nfastify.get('/', (req, reply) =\u003e {\n  const cookie = serialize('lang', 'en', {\n    maxAge: 60_000,\n  })\n\n  reply.header('Set-Cookie', cookie)\n\n  reply.send('Language set!')\n})\n```\n\n## Options\n\n- `secret` (`String` | `Array` | `Buffer` | `Object`):\n  - A `String` or `Buffer` can be passed to use as secret to sign the cookie using [`cookie-signature`](http://npm.im/cookie-signature).\n  - An `Array` can be passed if key rotation is desired. Read more about it in [Rotating signing secret](#rotating-secret).\n  - More sophisticated cookie signing mechanisms can be implemented by supplying an `Object`. Read more about it in [Custom cookie signer](#custom-cookie-signer).\n\n- `hook`: the [Fastify Hook](https://fastify.dev/docs/latest/Reference/Lifecycle/#lifecycle) to register the parsing of cookie into. Default: `onRequest`.\n\n- `algorithm`: the [algorithm](https://nodejs.org/api/crypto.html#cryptogethashes) to use to sign the cookies. Default: `sha256`.\n\n- `parseOptions`: An `Object` to modify the serialization of set cookies.\n\n### :warning: Security Considerations :warning:\n\nIt is recommended to use `sha256` or stronger hashing algorithm as well as a `secret` that is at least 20 bytes long.\n\n#### parseOptions\n\n##### domain\n\nSpecifies the value for the [`Domain` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.3). By default, no\ndomain is set, and most clients will consider the cookie to apply to only the current domain.\n\n##### encode\n\nSpecifies a function that will be used to encode a cookie's value. Since the value of a cookie\nhas a limited character set (and must be a simple string), this function can be used to encode\na value into a string suited for a cookie's value.\n\nThe default function is the global `encodeURIComponent`, which will encode a JavaScript string\ninto UTF-8 byte sequences and then URL-encode any that fall outside of the cookie range.\n\n##### expires\n\nSpecifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.1).\nBy default, no expiration is set, and most clients will consider this a \"non-persistent cookie\" and\nwill delete it on a condition like exiting a web browser application.\n\n**Note:** the [cookie storage model specification](https://datatracker.ietf.org/doc/html/rfc6265#section-5.3) states that if both `expires` and\n`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients obey this,\nso if both are set, they should point to the same date and time.\n\n##### httpOnly\n\nSpecifies the `boolean` value for the [`HttpOnly` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.6). When truthy,\nthe `HttpOnly` attribute is set, otherwise, it is not. By default, the `HttpOnly` attribute is not set.\n\n**Note:** be careful when setting this to `true`, as compliant clients will not allow client-side\nJavaScript to see the cookie in `document.cookie`.\n\n##### maxAge\n\nSpecifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.2).\nThe given number will be converted to an integer by rounding down. By default, no maximum age is set.\n\n**Note:** the [cookie storage model specification](https://datatracker.ietf.org/doc/html/rfc6265#section-5.3) states that if both `expires` and\n`maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients obey this,\nso if both are set, they should point to the same date and time.\n\n##### partitioned\n\nSpecifies the `boolean` value for the [`Partitioned` `Set-Cookie`](https://datatracker.ietf.org/doc/html/draft-cutler-httpbis-partitioned-cookies#section-2.1)\nattribute. When truthy, the `Partitioned` attribute is set, otherwise it is not. By default, the\n`Partitioned` attribute is not set.\n\n⚠️ **Warning:** [This is an attribute that has not yet been fully standardized](https://github.com/fastify/fastify-cookie/pull/261#issuecomment-1803234334), and may change in the future without reflecting the semver versioning. This also means many clients may ignore the attribute until they understand it.\n\nMore information about this can be found in [the proposal](https://github.com/privacycg/CHIPS).\n\n\n##### priority\n\nSpecifies the `string` to be the value for the [`Priority` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1).\n\n  - `'low'` will set the `Priority` attribute to `Low`.\n  - `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set.\n  - `'high'` will set the `Priority` attribute to `High`.\n\nMore information about the different priority levels can be found in\n[the specification](https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1).\n\n⚠️ **Warning:** This is an attribute that has not yet been fully standardized, and may change in the future without reflecting the semver versioning. This also means many clients may ignore the attribute until they understand it.\n\n##### path\n\nSpecifies the value for the [`Path` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.4). By default, the path\nis considered the [\"default path\"](https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.4).\n\n##### sameSite\n\nSpecifies the `boolean` or `string` to be the value for the [`SameSite` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7).\n\n  - `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement.\n  - `false` will not set the `SameSite` attribute.\n  - `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.\n  - `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.\n  - `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.\n\nMore information about the different enforcement levels can be found in\n[the specification](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7).\n\n**Note:** This is an attribute that has not yet been fully standardized, and may change in the future.\nThis also means many clients may ignore this attribute until they understand it.\n\n##### secure\n\nSpecifies the `boolean` value for the [`Secure` `Set-Cookie` attribute](https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.5). When truthy,\nthe `Secure` attribute is set, otherwise, it is not. By default, the `Secure` attribute is not set.\n\n**Note:** be careful when setting this to `true`, as compliant clients will not send the cookie back to\nthe server in the future if the browser does not have an HTTPS connection.\n\n## API\n\n### Parsing\n\nCookies are parsed in the `onRequest` Fastify hook and attached to the request\nas an object named `cookies`. Thus, if a request contains the header\n`Cookie: foo=foo` then, within your handler, `req.cookies.foo` would equal\n`'foo'`.\n\nYou can pass options to the [cookie parse](https://github.com/jshttp/cookie#cookieparsestr-options) by setting an object named `parseOptions` in the plugin config object.\n\n### Sending\n\nThe method `setCookie(name, value, options)`, and its alias `cookie(name, value, options)`, are added to the `reply` object\nvia the Fastify `decorateReply` API. Thus, in a request handler,\n`reply.setCookie('foo', 'foo', {path: '/'})` will set a cookie named `foo`\nwith a value of `'foo'` on the cookie path `/`.\n\n+ `name`: a string name for the cookie to be set\n+ `value`: a string value for the cookie\n+ `options`: an options object as described in the [cookie serialize][cs] documentation\n+ `options.signed`: the cookie should be signed\n+ `options.secure`: if set to `true` it will set the Secure-flag. If it is set to `\"auto\"` Secure-flag is set when the connection is using tls.\n\n#### Securing the cookie\n\nFollowing are _some_ of the precautions that should be taken to ensure the integrity of an application:\n\n- It's important to use `options.httpOnly` cookies to prevent attacks like XSS.\n- Use signed cookies (`options.signed`) to ensure they are not getting tampered wit client-side by an attacker.\n- Use `__Host-` [Cookie Prefix](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Attributes) to avoid Cookie Tossing attacks.\n- It is important to [use HTTPS for your website/app](https://letsencrypt.org/) to avoid a bunch of other potential security issues like [MITM](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) etc.\n\n### Clearing\n\nThe method `clearCookie(name, options)` is added to the `reply` object\nvia the Fastify `decorateReply` API. Thus, in a request handler,\n`reply.clearCookie('foo', {path: '/'})` will clear a cookie named `foo`\non the cookie path `/`.\n\n+ `name`: a string name for the cookie to be cleared\n+ `options`: an options object as described in the [cookie serialize][cs]\ndocumentation. It is optional to pass an `options` object\n\n### Manual cookie parsing\n\nThe method `parseCookie(cookieHeader)` is added to the `fastify` instance\nvia the Fastify `decorate` API. Thus, `fastify.parseCookie('sessionId=aYb4uTIhdBXC')`\nwill parse the raw cookie header and return an object `{ \"sessionId\": \"aYb4uTIhdBXC\" }`.\n\n[cs]: https://www.npmjs.com/package/cookie#options-1\n\n\u003ca id=\"rotating-secret\"\u003e\u003c/a\u003e\n### Rotating signing secret\n\nKey rotation is when an encryption key is retired and replaced by generating a new cryptographic key. To implement rotation, supply an `Array` of keys to `secret` option.\n\n**Example:**\n```js\nfastify.register(require('@fastify/cookie'), {\n  secret: [key1, key2]\n})\n```\n\nThe plugin will **always** use the first key (`key1`) to sign cookies. When parsing incoming cookies, it will iterate over the supplied array to see if any of the available keys are able to decode the given signed cookie. This ensures that any old signed cookies are still valid.\n\nNote:\n- Key rotation is **only** achieved by redeploying the server again with the new `secret` array.\n- Iterating through all secrets is an expensive process, so the rotation list should contain as few keys as possible. Ideally, only the current key and the most recently retired key.\n- Although previously signed cookies are valid even after rotation, cookies should be updated with the new key as soon as possible. See the following example for how to accomplish this.\n\n**Example:**\n```js\nfastify.get('/', (req, reply) =\u003e {\n  const result = reply.unsignCookie(req.cookies.myCookie)\n\n  if (result.valid \u0026\u0026 result.renew) {\n    // Setting the same cookie again, this time the plugin will sign it with a new key\n    reply.setCookie('myCookie', result.value, {\n      domain: 'example.com', // same options as before\n      path: '/',\n      signed: true\n    })\n  }\n})\n```\n\n\u003ca id=\"custom-cookie-signer\"\u003e\u003c/a\u003e\n### Custom cookie signer\n\nThe `secret` option optionally accepts an object with `sign` and `unsign` functions. This allows for implementing a custom cookie signing mechanism. See the following example:\n\n**Example:**\n```js\nfastify.register(require('@fastify/cookie'), {\n  secret: {\n    sign: (value) =\u003e {\n      // sign using custom logic\n      return signedValue\n    },\n    unsign: (value) =\u003e {\n      // unsign using custom logic\n      return {\n        valid: true, // the cookie has been unsigned successfully\n        renew: false, // the cookie has been unsigned with an old secret\n        value: 'unsignedValue'\n      }\n    }\n  }\n})\n```\n\n### Manual cookie unsigning\n\nThe method `unsignCookie(value)` is added to the `fastify` instance, to the `request` and the `reply` object\nvia the Fastify `decorate`, `decorateRequest`, and `decorateReply` APIs, if a secret was provided as an option.\nUsing it on a signed cookie will call the provided signer's (or the default signer if no custom implementation is provided) `unsign` method on the cookie.\n\n**Example:**\n\n```js\nfastify.register(require('@fastify/cookie'), { secret: 'my-secret' })\n\nfastify.get('/', (req, rep) =\u003e {\n  if (fastify.unsignCookie(req.cookie.foo).valid === false) {\n    rep.send('cookie is invalid')\n    return\n  }\n\n  rep.send('cookie is valid')\n})\n```\n\n### Other cases of manual signing\n\nSometimes the service under test should only accept requests with signed cookies, but it does not generate them itself.\n\n**Example:**\n\n```js\n\ntest('Request requires signed cookie', async () =\u003e {\n    const response = await app.inject({\n        method: 'GET',\n        url: '/',\n        headers: {\n          cookies : {\n            'sid': app.signCookie(sidValue)\n          }\n        },\n    });\n\n    expect(response.statusCode).toBe(200);\n});\n```\n\n### Manual signing/unsigning with low-level utilities\n\nWith Signer:\n\n```js\nconst { Signer } = require('@fastify/cookie');\n\nconst signer = new Signer('secret');\nconst signedValue = signer.sign('test');\nconst {valid, renew, value } = signer.unsign(signedValue);\n```\n\nWith sign/unsign utilities:\n\n```js\nconst { fastifyCookie } = require('@fastify/cookie');\n\nconst signedValue = fastifyCookie.sign('test', 'secret');\nconst unsignedvalue = fastifyCookie.unsign(signedValue, 'secret');\n```\n\n\n## License\n\nLicensed under [MIT](./LICENSE).\n","funding_links":["https://github.com/sponsors/fastify","https://opencollective.com/fastify"],"categories":["JavaScript","\u003ch2 align=\"center\"\u003eAwesome Fastify\u003c/h2\u003e"],"sub_categories":["\u003ch2 align=\"center\"\u003eEcosystem\u003c/h2\u003e"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffastify%2Ffastify-cookie","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffastify%2Ffastify-cookie","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffastify%2Ffastify-cookie/lists"}