{"id":20315791,"url":"https://github.com/flipeador/node-http-cookies","last_synced_at":"2025-03-04T08:47:19.982Z","repository":{"id":157621900,"uuid":"594822099","full_name":"flipeador/node-http-cookies","owner":"flipeador","description":"Node.js HTTP cookie parsing middleware.","archived":false,"fork":false,"pushed_at":"2024-02-11T08:08:51.000Z","size":81,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"v2.0","last_synced_at":"2025-01-14T12:53:12.663Z","etag":null,"topics":["cookie-parser","express","http-cookie","javascript","middleware","nodejs"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/flipeador.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":"2023-01-29T18:39:28.000Z","updated_at":"2024-02-11T08:09:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"47e1a23c-a237-4371-a63b-13b994d2514c","html_url":"https://github.com/flipeador/node-http-cookies","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flipeador%2Fnode-http-cookies","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flipeador%2Fnode-http-cookies/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flipeador%2Fnode-http-cookies/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flipeador%2Fnode-http-cookies/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/flipeador","download_url":"https://codeload.github.com/flipeador/node-http-cookies/tar.gz/refs/heads/v2.0","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241818872,"owners_count":20025210,"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-parser","express","http-cookie","javascript","middleware","nodejs"],"created_at":"2024-11-14T18:21:48.458Z","updated_at":"2025-03-04T08:47:19.960Z","avatar_url":"https://github.com/flipeador.png","language":"JavaScript","readme":"# HTTP Cookies\n\nSimplifies the handling of [HTTP cookies][httpcookie].\n\n### Features\n\n- Create string or JSON cookies with an optional signature.\n- Parse the [Cookie][cookie] header into a key-value Object.\n- Use the cookie parser as a middleware in [Express][express].\n\n\u003e [!NOTE]\n\u003e This is a lightweight alternative library to [cookie-parser][cookie-parser] with no dependencies.\n\n## Installation\n\n```\nnpm i flipeador/node-http-cookies#semver:^2.0.0\n```\n\n## Cookie Attributes\n\nCookies are mainly used for storing credentials, user preferences, site settings, and tracking data.\n\n- The cookie name can contain any US-ASCII characters except for control characters, space, tab, and separators (`( ) \u003c \u003e @ , ; : \\ \" / [ ] ? = { }`).\n- The cookie value can optionally be wrapped in double quotes and include any US-ASCII character excluding control characters, whitespace, double quotes, commas, semicolons, and backslashes.\n- The cookie name or value can be [URI encoded][uriencode] to satisfy the allowed character requirement.\n- The cookie value can be a number, or a [JSON-stringified][stringify] object prefixed with `j:`.\n- The cookie value can be [signed][createhmac] to ensure that it has not been tampered with, and prefixed with `s:`.\n\nThe server sends cookies to the browser by setting the [Set-Cookie header][setcookie]:\n\n```js\n[\n    '\u003ccookie-name\u003e=\u003ccookie-value\u003e; attribute1; attribute2; ...',\n    ...\n]\n```\n\nThe browser sends cookies back to the server by setting the [Cookie header][cookie]:\n\n```js\n'\u003ccookie-name\u003e=\u003ccookie-value\u003e; ...'\n```\n\nCookie names can have specific semantics via the following prefixes:\n\n| Prefix | Description |\n| :---: | --- |\n| `__Secure-` | Require the cookie to be set from a secure page (HTTPS). |\n| `__Host-` | Make the cookie bound to the hostname (and not the registrable domain). |\n\nThe following are the cookie attributes recognized by the library:\n\n| Attribute | Default | Description | Note |\n| :---: | ---: | --- | --- |\n| [`Domain`][setcookie] | — | Defines the host to which the cookie will be sent. | — |\n| [`Path`][setcookie] | `/` | Restrict the cookie to a specific path, including subpaths. | — |\n| [`Secure`][setcookie] | `false` | Set the cookie over HTTPS only, except on localhost. | — |\n| [`HttpOnly`][setcookie] | `false` | Make the cookie inaccessible to the JavaScript [`Document.cookie`][doccookie] API. | — |\n| [`SameSite`][setcookie] | `lax` | Origin relationship between request and resource. | Values: `strict` `lax` `none`. |\n| [`Partitioned`][setcookie] | `false` | The cookie should be stored using partitioned storage. | Requires the `Secure` attribute. |\n| [`Expires`][setcookie] | — | The exact expiration [date][date] in the [RFC 7231][rfc7231] format. | [`new Date().toUTCString()`][toutcstr] |\n| [`Max-Age`][setcookie] | — | Number of seconds until the cookie expires. | Invalidates [`Expires`][setcookie]. |\n\n\u003e [!NOTE]\n\u003e - The value `true` will cause the attribute to be added to the cookie with no value assigned.\n\u003e - The values `false` `NaN` `''` will cause the attribute not to be added to the cookie.\n\u003e - The values `null` `undefined` will cause the attribute to keep the default value, if any.\n\nThe following are special attributes used as options:\n\n| Option | Description |\n| :---: | --- |\n| `secret` | Secret to use to sign the cookie value. |\n\n### Cookie Lifetime\n\nBy specifying the `Expires` or `Max-Age` attribute, you can create a **persistent cookie**.\nIf the server does not provide information about the expiration of the cookie by specifying the exact date or after a specific length of time, it becomes a **session cookie** and is removed when the browser shuts down.\n\nA cookie can be removed by specifying a zero or negative number in the `Max-Age` attribute, wich will expire the cookie immediately.\n\n### Partitioned Attribute\n\nCookies Having Independent Partitioned State (CHIPS) allows developers to opt a cookie into partitioned storage, with separate cookie jars per top-level site, which restricts the contexts in which a cookie is available to only those whose top-level document is same-site with the top-level document that initiated the request that created the cookie. Partitioned cookies allows to embedded sites which are cross-site with the top-level frame to have access to HTTP state which cannot be used for tracking across multiple top-level sites.\n\n#### Google Chrome (≥118):\n- Visit \u003cchrome://flags/#test-third-party-cookie-phaseout\u003e and enable partitioned cookies.\n- The Application tab shows both partition and unparitioned stored cookies, even if they are not accessible in the current page.\n- Unpartitioned third-party cookies will not be available to embedded sites on different top-level sites.\n- You can better visualize unpartitioned cookies that are being blocked by checking `Only show cookies with an issue` in the DevTools.\n\n#### Further reading:\n- https://developer.mozilla.org/docs/Web/Privacy/Partitioned_cookies\n- https://developers.google.com/privacy-sandbox/3pcd/chips\n- https://www.ietf.org/archive/id/draft-cutler-httpbis-partitioned-cookies-01.html\n- https://github.com/privacycg/CHIPS\n\n### SameSite Attribute\n\nThe `SameSite` attribute allows to declare if the cookie should be restricted to a **same-site** or **cross-site** context, providing some protection against [Cross-site Request Forgery][csrf] (CSRF) attacks.\nIf the server stores a session token with full access to the user's account in the cookies, you don't want the browser to send it in a malicious request from an unauthorized site.\nThe included cookie is **first-party** when the request is made in a **same-site** context, and **third-party** when the request is made in a **cross-site** context.\n\n| SameSite | Description |\n| :---: | --- |\n| [`Strict`][setcookie] | Cookies will only be sent in a **same-site** context. |\n| [`Lax`][setcookie] | Like [`Strict`][setcookie], except the browser also sends the cookie when the user navigates to the cookie's origin site (e.g. by following a link from an external/different site). |\n| [`None`][setcookie] | Cookies will be sent in both **cross-site** and **same-site** contexts. Requires the `Secure` attribute. |\n\n\u003e [!IMPORTANT]\n\u003e If the `SameSite` attribute is set to `None`, browsers that have enabled the **third-party cookie phaseout** will require the [`Partitioned`](#partitioned-attribute) attribute to be present, otherwise unparitioned cookies will be blocked in third-party contexts.\n\n[Top-level domains][tld] (TLD) are listed in the [Root Zone Database][rzd].\nThe [Public Suffix List][psl] (PSL) is a catalog of certain Internet domain names, whose [entries in the list][psld] are also referred to as **effective Top-Level Domains** (eTLD). The [PSL][psl] is used for some domains where the [TLD][tld] is not granular enough to identify the site.\n\n[User agents][ua] group [URI][uri]s together into protection domains called origins. Two [URI][uri]s are part of the same origin if they have the same scheme, host, and port ([RFC 6454][rfc6454]).\nAll **cross-site** requests are necessarily **cross-origin**, but not all **cross-origin** requests are **cross-site**.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/flipeador/node-http-cookies/assets/url.png\"/\u003e\n\u003c/p\u003e\n\nThe **same-site** context treats all subdomains of the `eTLD+1` to be equivalent to the root domain.\n\n| Origin | eTLD+1 | Same-Site | Cross-Site |\n| --- | --- | --- | --- |\n| `http://www.example.com` | `.example.com` | `http://example.com` `http://x.example.com` `http://x.y.example.com` | `https://www.example.com` `example.net` `username.github.io` |\n| `username.github.io` | `username.github.io` | `x.username.github.io` `x.y.username.github.io` | `otheruser.github.io` |\n\n\u003e [!IMPORTANT]\n\u003e - If you are dealing with **third-party** cookies (e.g. for tracking purposes), make sure to specify the [Partitioned](#partitioned-attribute) attribute.\n\u003e - The definition of **site** extends beyond the host and [require scheme matches as well][sitesch], although some browsers may not yet be URL scheme-aware, see [Browser Compatibility][setcookbc].\n\n\u003e [!NOTE]\n\u003e The [Sec-Fetch-Site][secfetchsite] header can be used to determine if the request is **same-origin**, **same-site**, **cross-site**, or it is a user-originated operation (e.g. entering a URL into the address bar, opening a bookmark, or a drag-and-drop operation).\n\n#### Further reading:\n- \u003chttps://github.com/flipeador/node-http-cors\u003e\n- \u003chttps://jub0bs.com/posts/2021-01-29-great-samesite-confusion\u003e\n- \u003chttps://jub0bs.com/posts/2022-08-04-scraping-the-bottom-of-the-cors-barrel-part1\u003e\n\n## Example\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ch4\u003eExpress\u003c/h4\u003e\u003c/summary\u003e\n\n```js\nimport express from 'express';\nimport {\n    cookieParser,\n    parseJsonCookie,\n    parseSignedCookie\n} from '@flipeador/node-http-cookies';\n\nconst app = express();\n\n// Add the middleware here and not individually to the routes.\n// This does not have a significant impact on performance,\n// as the cookies are not parsed immediately for every request.\n// Cookies are parsed only once on first access to the 'req.cookies' property.\n// The middleware also sets a function 'res.cookie()' that allows cookies to be added.\napp.use(cookieParser());\n\napp.get('/set-cookie', (req, res) =\u003e {\n    res.cookie('string', 'value', {\n        secure: true,\n        sameSite: 'none',\n        partitioned: true,\n        // Restrict the cookie to the current path and subpaths.\n        path: `${req.baseUrl}${req.path}`\n    });\n    res.cookie('json', ['value']);\n    res.cookie('signed', 'value', { secret: 'XXX' });\n    res.json(req.cookies);\n});\n\napp.get('/get-cookie', (req, res) =\u003e {\n    res.json({\n        string: req.cookies.string ??\n        'not accessible due to different path',\n        json: parseJsonCookie(req.cookies.json),\n        signed: parseSignedCookie(req.cookies.signed, 'XXX')\n    });\n});\n\napp.listen(3000, () =\u003e {\n    console.log('Server is running!');\n    console.log('http://localhost:3000/set-cookie');\n    console.log('http://localhost:3000/get-cookie');\n});\n```\n\n\u003c/details\u003e\n\n## License\n\nThis project is licensed under the **Apache License 2.0**. See the [license file](LICENSE) for details.\n\n\u003c!-- REFERENCE LINKS --\u003e\n[express]: https://github.com/expressjs/express\n[cookie-parser]: https://github.com/expressjs/cookie-parser\n\n[ua]: https://developer.mozilla.org/docs/Glossary/User_agent\n[csrf]: https://en.wikipedia.org/wiki/Cross-site_request_forgery \"Cross-Site Request Forgery\"\n[uri]: https://en.wikipedia.org/wiki/Uniform_Resource_Identifier \"Uniform Resource Identifier\"\n[url]: https://en.wikipedia.org/wiki/URL \"Uniform Resource Locator\"\n\n[httpcookie]: https://en.wikipedia.org/wiki/HTTP_cookie \"HTTP Cookie\"\n[cookie]: https://developer.mozilla.org/docs/Web/HTTP/Headers/Cookie \"Cookie Request Header\"\n[setcookie]: https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie \"Set-Cookie Response Header\"\n[setcookbc]: https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie#browser_compatibility\n[samesite]: https://developer.mozilla.org/docs/Web/HTTP/Headers/Set-Cookie/SameSite\n[secfetchsite]: https://developer.mozilla.org/docs/Web/HTTP/Headers/Sec-Fetch-Site \"Sec-Fetch-Site Request Header\"\n[date]: https://developer.mozilla.org/docs/Web/HTTP/Headers/Date \"Date Header\"\n\n[doccookie]: https://developer.mozilla.org/docs/Web/API/Document/cookie\n[stringify]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify \"JSON-stringify\"\n[uriencode]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent \"encodeURIComponent()\"\n[toutcstr]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date/toUTCString\n[createhmac]: https://nodejs.org/api/crypto.html#cryptocreatehmacalgorithm-key-options \"Node.js crypto#createHmac\"\n\n[tld]: https://developer.mozilla.org/docs/Glossary/TLD \"Top-Level Domain\"\n[etld]: https://publicsuffix.org \"Effective Top-Level Domain\"\n[rzd]: https://www.iana.org/domains/root/db \"Root Zone Database\"\n[psl]: https://publicsuffix.org \"Public Suffix List\"\n[psld]: https://github.com/publicsuffix/list/blob/master/public_suffix_list.dat \"Public Suffix List (file)\"\n\n[rfc6454]: https://www.rfc-editor.org/rfc/rfc6454#section-3.2 \"RFC 6454 Section 3.2\"\n[rfc7231]: https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.1.1 \"RFC 7231 Section 7.1.1.1\"\n[sitesch]: https://github.com/whatwg/url/issues/448\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflipeador%2Fnode-http-cookies","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fflipeador%2Fnode-http-cookies","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflipeador%2Fnode-http-cookies/lists"}