{"id":14156035,"url":"https://github.com/mozilla/node-client-sessions","last_synced_at":"2025-08-06T02:31:17.221Z","repository":{"id":2122958,"uuid":"3065622","full_name":"mozilla/node-client-sessions","owner":"mozilla","description":"secure sessions stored in cookies","archived":true,"fork":false,"pushed_at":"2024-03-25T21:05:07.000Z","size":151,"stargazers_count":760,"open_issues_count":43,"forks_count":104,"subscribers_count":49,"default_branch":"master","last_synced_at":"2024-10-29T11:01:09.620Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"jacksbox/jquery.fractionslider","license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mozilla.png","metadata":{"files":{"readme":"README.md","changelog":"ChangeLog","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}},"created_at":"2011-12-28T23:02:07.000Z","updated_at":"2024-10-11T11:27:26.000Z","dependencies_parsed_at":"2024-04-20T20:46:49.385Z","dependency_job_id":"0511c35c-971d-4b11-a53d-f71d5d505e0c","html_url":"https://github.com/mozilla/node-client-sessions","commit_stats":{"total_commits":140,"total_committers":27,"mean_commits":5.185185185185185,"dds":0.7,"last_synced_commit":"efc5e47fa92400a5df14a816bfa6121793d9e8ce"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mozilla%2Fnode-client-sessions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mozilla%2Fnode-client-sessions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mozilla%2Fnode-client-sessions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mozilla%2Fnode-client-sessions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mozilla","download_url":"https://codeload.github.com/mozilla/node-client-sessions/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226722401,"owners_count":17671425,"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":[],"created_at":"2024-08-17T08:05:10.117Z","updated_at":"2024-12-09T03:30:56.894Z","avatar_url":"https://github.com/mozilla.png","language":"JavaScript","readme":"[![build status](https://secure.travis-ci.org/mozilla/node-client-sessions.png)](http://travis-ci.org/mozilla/node-client-sessions)\n\nclient-sessions is connect middleware that implements sessions in encrypted tamper-free cookies.  For a complete introduction to encrypted client side sessions, refer to [Francois Marier's blog post on the subject][];\n\n[Francois Marier's blog post on the subject]: https://hacks.mozilla.org/2012/12/using-secure-client-side-sessions-to-build-simple-and-scalable-node-js-applications-a-node-js-holiday-season-part-3/\n\n**NOTE:** It is not recommended using both this middleware and connect's built-in session middleware.\n\n## Installation\n`npm install client-sessions`\n\n## Usage\n\nBasic usage:\n\n```js\nvar sessions = require(\"client-sessions\");\napp.use(sessions({\n  cookieName: 'mySession', // cookie name dictates the key name added to the request object\n  secret: 'blargadeeblargblarg', // should be a large unguessable string\n  duration: 24 * 60 * 60 * 1000, // how long the session will stay valid in ms\n  activeDuration: 1000 * 60 * 5 // if expiresIn \u003c activeDuration, the session will be extended by activeDuration milliseconds\n}));\n\napp.use(function(req, res, next) {\n  if (req.mySession.seenyou) {\n    res.setHeader('X-Seen-You', 'true');\n  } else {\n    // setting a property will automatically cause a Set-Cookie response\n    // to be sent\n    req.mySession.seenyou = true;\n    res.setHeader('X-Seen-You', 'false');\n  }\n});\n```\n\nYou can control more specific cookie behavior during setup:\n\n```js\napp.use(sessions({\n  cookieName: 'mySession', // cookie name dictates the key name added to the request object\n  secret: 'blargadeeblargblarg', // should be a large unguessable string\n  duration: 24 * 60 * 60 * 1000, // how long the session will stay valid in ms\n  cookie: {\n    path: '/api', // cookie will only be sent to requests under '/api'\n    maxAge: 60000, // duration of the cookie in milliseconds, defaults to duration above\n    ephemeral: false, // when true, cookie expires when the browser closes\n    httpOnly: true, // when true, cookie is not accessible from javascript\n    secure: false // when true, cookie will only be sent over SSL. use key 'secureProxy' instead if you handle SSL not in your node process\n  }\n}));\n```\n\nYou can have multiple cookies:\n\n```js\n// a 1 week session\napp.use(sessions({\n  cookieName: 'shopping_cart',\n  secret: 'first secret',\n  duration: 7 * 24 * 60 * 60 * 1000\n}));\n\n// a 2 hour encrypted session\napp.use(sessions({\n  cookieName: 'authenticated',\n  secret: 'first secret',\n  duration: 2 * 60 * 60 * 1000\n}));\n```\n\nIn this example, there's a 2 hour authentication session, but shopping carts persist for a week.\n\nFinally, you can use requestKey to force the name where information can be accessed on the request object.\n\n```js\nvar sessions = require(\"client-sessions\");\napp.use(sessions({\n  cookieName: 'mySession',\n  requestKey: 'forcedSessionKey', // requestKey overrides cookieName for the key name added to the request object.\n  secret: 'blargadeeblargblarg', // should be a large unguessable string or Buffer\n  duration: 24 * 60 * 60 * 1000, // how long the session will stay valid in ms\n}));\n\napp.use(function(req, res, next) {\n  // requestKey forces the session information to be\n  // accessed via forcedSessionKey\n  if (req.forcedSessionKey.seenyou) {\n    res.setHeader('X-Seen-You', 'true');\n  }\n  next();\n});\n```\n\n## Cryptography\n\nA pair of encryption and signature keys are derived from the `secret` option\nvia HMAC-SHA-256; the `secret` isn't used directly to encrypt or compute the\nMAC.\n\nThe key-derivation function, in pseudocode:\n\n```text\n  encKey := HMAC-SHA-256(secret, 'cookiesession-encryption');\n  sigKey := HMAC-SHA-256(secret, 'cookiesession-signature');\n```\n\nThe **AES-256-CBC** cipher is used to encrypt the session contents, with an\n**HMAC-SHA-256** authentication tag (via **Encrypt-then-Mac** composition).  A\nrandom 128-bit Initialization Vector (IV) is generated for each encryption\noperation (this is the AES block size regardless of the key size).  The\nCBC-mode input is padded with the usual PKCS#5 scheme.\n\nIn pseudocode, the encryption looks like the following, with `||` denoting\nconcatenation. The `createdAt` and `duration` parameters are decimal strings.\n\n```text\n  sessionText := cookieName || '=' || sessionJson\n  iv := secureRandom(16 bytes)\n  ciphertext := AES-256-CBC(encKey, iv, sessionText)\n  payload := iv || '.' || ciphertext || '.' || createdAt || '.' || duration\n  hmac := HMAC-SHA-256(sigKey, payload)\n  cookie := base64url(iv) || '.' ||\n    base64url(ciphertext) || '.' ||\n    createdAt || '.' ||\n    duration || '.' ||\n    base64url(hmac)\n```\n\nFor decryption, a constant-time equality operation is used to verify the HMAC\noutput to avoid the plausible timing attack.\n\n### Advanced Cryptographic Options\n\nThe defaults are secure, but may not suit your requirements. Some example scenarios:\n- You want to use randomly-generated keys instead of using the key-derivation\n  function used in this module.\n- AES-256 is overkill for the type of data you store in the session (e.g. not\n  personally-identifiable or sensitive) and you'd like to trade-off decreasing\n  the security level for CPU economy.\n- SHA-256 is maybe too weak for your application and you want to have more\n  MAC security by using SHA-512, which grows the size of your cookies slightly.\n\nIf the defaults don't suit your needs, you can customize client-sessions.\n**Beware: Changing keys and/or algorithms will make previously-generated\nCookies invalid!**\n\n#### Configuring Keys\n\nTo configure independent encryption and signature (HMAC) keys:\n\n```js\napp.use(sessions({\n  encryptionKey: loadFromKeyStore('session-encryption-key'),\n  signatureKey: loadFromKeyStore('session-signature-key'),\n  // ... other options discussed above ...\n}));\n```\n\n#### Configuring Algorithms\n\nTo specify custom algorithms and keys:\n\n```js\napp.use(sessions({\n  // use WEAKER-than-default encryption:\n  encryptionAlgorithm: 'aes128',\n  encryptionKey: loadFromKeyStore('session-encryption-key'),\n  // use a SHORTER-than-default MAC:\n  signatureAlgorithm: 'sha256-drop128',\n  signatureKey: loadFromKeyStore('session-signature-key'),\n  // ... other options discussed above ...\n}));\n```\n\n#### Encryption Algorithms\n\nSupported CBC-mode `encryptionAlgorithm`s (and key length requirements):\n\n| Cipher | Key length |\n| ------ | ---------- |\n| aes128 | 16 bytes   |\n| aes192 | 24 bytes   |\n| aes256 | 32 bytes   |\n\nThese key lengths are exactly as required by the [Advanced Encryption\nStandard](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard).\n\n#### Signature (HMAC) Algorithms\n\nSupported HMAC `signatureAlgorithm`s (and key length requirements):\n\n| HMAC           | Minimum Key Length | Maximum Key Length |\n| -------------- | ------------------ | ------------------ |\n| sha256         | 32 bytes           | 64 bytes           |\n| sha256-drop128 | 32 bytes           | 64 bytes           |\n| sha384         | 48 bytes           | 128 bytes          |\n| sha384-drop192 | 48 bytes           | 128 bytes          |\n| sha512         | 64 bytes           | 128 bytes          |\n| sha512-drop256 | 64 bytes           | 128 bytes          |\n\nThe HMAC key length requirements are derived from [RFC 2104 section\n3](https://tools.ietf.org/html/rfc2104#section-3). The maximum key length can\nbe exceeded, but it doesn't increase the security of the signature.\n\nThe `-dropN` algorithms discard the latter half of the HMAC output, which\nprovides some additional protection against SHA2 length-extension attacks on\ntop of HMAC. The same technique is used in the upcoming [JSON Web Algorithms\n`AES_CBC_HMAC_SHA2` authenticated\ncipher](http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-19#section-5.2).\n\n#### Generating Keys\n\nOne can easily generate both AES and HMAC-SHA2 keys via command line: `openssl\nrand -base64 32` for a 32-byte (256-bit) key.  It's easy to then parse that\noutput into a `Buffer`:\n\n```js\nfunction loadKeyFromStore(name) {\n  var text = myConfig.keys[name];\n  return Buffer.from(text, 'base64');\n}\n```\n\n#### Key Constraints\n\nIf you specify `encryptionKey` or `signatureKey`, you must supply the other as\nwell.\n\nThe following constraints must be met or an `Error` will be thrown:\n\n1. both keys must be `Buffer`s.\n2. the keys must be _different_.\n3. the encryption key are _exactly_ the length required (see above).\n4. the signature key has _at least_ the length required (see above).\n\nBased on the above, please note that if you specify a `secret` _and_ a\n`signatureAlgorithm`, you need to use `sha256` or `sha256-drop128`.\n\n## License\n\n\u003e This Source Code Form is subject to the terms of the Mozilla Public\n\u003e License, v. 2.0. If a copy of the MPL was not distributed with this\n\u003e file, You can obtain one at http://mozilla.org/MPL/2.0/.\n","funding_links":[],"categories":["others"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmozilla%2Fnode-client-sessions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmozilla%2Fnode-client-sessions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmozilla%2Fnode-client-sessions/lists"}