connect-memcached
Advanced tools
Comparing version
@@ -1,2 +0,1 @@ | ||
module.exports = require('./lib/connect-memcached'); | ||
module.exports = require('./lib/connect-memcached'); |
@@ -42,8 +42,2 @@ /*! | ||
} | ||
if (options.secret) { | ||
(this.crypto = require("crypto")), (this.secret = options.secret); | ||
} | ||
if (options.algorithm) { | ||
this.algorithm = options.algorithm; | ||
} | ||
@@ -53,2 +47,9 @@ options.client = new Memcached(options.hosts, options); | ||
if (options.secret) { | ||
options.algorithm = options.algorithm || 'aes-256-gcm'; | ||
options.hashing = options.hashing || 'sha512'; | ||
this.kruptein = require("kruptein")(options); | ||
this.secret = options.secret; | ||
} | ||
this.client = options.client; | ||
@@ -77,3 +78,4 @@ } | ||
MemcachedStore.prototype.get = function(sid, fn) { | ||
(secret = this.secret), (self = this), (sid = this.getKey(sid)); | ||
var self = this, sid = this.getKey(sid), | ||
parseable_string; | ||
@@ -88,9 +90,15 @@ this.client.get(sid, function(err, data) { | ||
} | ||
if (secret) { | ||
parseable_string = decryptData.call(self, data.toString()); | ||
if (self.secret) { | ||
self.kruptein.get(self.secret, data, function(err, ct) { | ||
if (err) | ||
return fn(err, {}); | ||
parseable_string = JSON.parse(ct); | ||
}); | ||
} else { | ||
parseable_string = data.toString(); | ||
parseable_string = data; | ||
} | ||
fn(null, JSON.parse(parseable_string)); | ||
fn(null, parseable_string); | ||
} catch (e) { | ||
@@ -117,13 +125,12 @@ fn(e); | ||
this.ttl || ("number" == typeof maxAge ? (maxAge / 1000) | 0 : oneDay); | ||
var sess = JSON.stringify( | ||
this.secret | ||
? encryptData.call( | ||
this, | ||
JSON.stringify(sess), | ||
this.secret, | ||
this.algorithm | ||
) | ||
: sess | ||
); | ||
if (this.secret) { | ||
this.kruptein.set(this.secret, sess, function(err, ct) { | ||
if (err) | ||
return fn(err); | ||
sess = ct; | ||
}); | ||
} | ||
this.client.set(sid, sess, ttl, ensureCallback(fn)); | ||
@@ -180,68 +187,3 @@ } catch (err) { | ||
function encryptData(plaintext) { | ||
var pt = encrypt.call(this, this.secret, plaintext, this.algo), | ||
hmac = digest.call(this, this.secret, pt); | ||
return { | ||
ct: pt, | ||
mac: hmac | ||
}; | ||
} | ||
function decryptData(ciphertext) { | ||
ciphertext = JSON.parse(ciphertext); | ||
var hmac = digest.call(this, this.secret, ciphertext.ct); | ||
if (hmac != ciphertext.mac) { | ||
throw "Encrypted session was tampered with!"; | ||
} | ||
return decrypt.call(this, this.secret, ciphertext.ct, this.algo); | ||
} | ||
function digest(key, obj) { | ||
var hmac = this.crypto.createHmac("sha512", key); | ||
hmac.setEncoding("hex"); | ||
hmac.write(obj); | ||
hmac.end(); | ||
return hmac.read(); | ||
} | ||
function encrypt(key, pt, algo) { | ||
algo = algo || "aes-256-ctr"; | ||
pt = Buffer.isBuffer(pt) ? pt : new bufferFrom(pt); | ||
var iv = this.crypto.randomBytes(16); | ||
var hashedKey = this.crypto | ||
.createHash("sha256") | ||
.update(key) | ||
.digest(); | ||
var cipher = this.crypto.createCipheriv(algo, hashedKey, iv), | ||
ct = []; | ||
ct.push(iv.toString("hex")); | ||
ct.push(cipher.update(pt, "buffer", "hex")); | ||
ct.push(cipher.final("hex")); | ||
return ct.join(""); | ||
} | ||
function decrypt(key, ct, algo) { | ||
algo = algo || "aes-256-ctr"; | ||
var dataBuffer = bufferFrom(ct, "hex"); | ||
var iv = dataBuffer.slice(0, 16); | ||
var hashedKey = this.crypto | ||
.createHash("sha256") | ||
.update(key) | ||
.digest(); | ||
var cipher = this.crypto.createDecipheriv(algo, hashedKey, iv), | ||
pt = []; | ||
pt.push(cipher.update(dataBuffer.slice(16), "hex", "utf8")); | ||
pt.push(cipher.final("utf8")); | ||
return pt.join(""); | ||
} | ||
return MemcachedStore; | ||
}; |
{ | ||
"name": "connect-memcached", | ||
"version": "1.0.0", | ||
"version": "2.0.0", | ||
"description": "Memcached session store for Connect", | ||
@@ -19,4 +19,20 @@ "keywords": [ | ||
"buffer-from": "1.1.0", | ||
"kruptein": "3.0.x", | ||
"memcached": "2.2.x" | ||
}, | ||
"devDependencies": { | ||
"express": "^4.17.3", | ||
"express-session": "^1.17.2", | ||
"jest": "^27.5.1", | ||
"supertest": "^6.2.2" | ||
}, | ||
"scripts": { | ||
"test": "NODE_ENV=test jest --testTimeout=10000" | ||
}, | ||
"jest": { | ||
"testEnvironment": "node", | ||
"coveragePathIgnorePatterns": [ | ||
"/node_modules/" | ||
] | ||
}, | ||
"engines": { | ||
@@ -23,0 +39,0 @@ "node": ">= 0.10.0" |
@@ -7,8 +7,14 @@ # connect-memcached | ||
via npm: | ||
npm: | ||
```bash | ||
$ npm install connect-memcached | ||
```shell | ||
npm install connect-memcached express-session | ||
``` | ||
yarn: | ||
```shell | ||
yarn add connect-memcached express-session | ||
``` | ||
## Example | ||
@@ -19,8 +25,5 @@ | ||
session = require("express-session"), | ||
cookieParser = require("cookie-parser"), | ||
http = require("http"), | ||
app = express(), | ||
MemcachedStore = require("connect-memcached")(session); | ||
app.use(cookieParser()); | ||
app.use( | ||
@@ -35,3 +38,3 @@ session({ | ||
hosts: ["127.0.0.1:11211"], | ||
secret: "123, easy as ABC. ABC, easy as 123" // Optionally use transparent encryption for memcache session data | ||
secret: "123, easy as ABC. ABC, easy as 123" // Optionally use transparent encryption for memcached session data | ||
}) | ||
@@ -50,3 +53,3 @@ }) | ||
http.createServer(app).listen(9341, function() { | ||
app.listen(9341, function() { | ||
console.log("Listening on %d", this.address().port); | ||
@@ -58,11 +61,16 @@ }); | ||
- `hosts` Memcached servers locations, can be string, array, hash. | ||
- `prefix` An optional prefix for each memcache key, in case you are sharing your memcached servers with something generating its own keys. | ||
- `ttl` An optional parameter used for setting the default TTL (in seconds) | ||
- `secret` An optional secret can be used to encrypt/decrypt session contents. | ||
- `algorithm` An optional algorithm parameter may be used, but must be valid based on returned `crypto.getCiphers()`. The current default is `aes-256-ctr` and was chosen based on the following [information](http://www.daemonology.net/blog/2009-06-11-cryptographic-right-answers.html) | ||
- ... Rest of given option will be passed directly to the node-memcached constructor. | ||
- `hosts` (Optional) Memcached servers locations, can be string, array or hash. Default is `127.0.0.1:11211`. | ||
- `prefix` (Optional) Prefix for each memcached key, in case you are sharing your memcached servers with something generating its own keys. | ||
- `ttl` (Optional) Default TTL parameter for the session data (in seconds). | ||
- `secret` (Optional) Secret used to encrypt/decrypt session contents. Setting it enables data encryption, which is handled by [kruptein](https://github.com/jas-/kruptein) module. | ||
- `algorithm` (Optional) Cipher algorithm from `crypto.getCiphers()`. Default is `aes-256-gcm`. | ||
- `hashing` (Optional) Hash algorithm from `crypto.getHashes()`. Default is `sha512`. | ||
- ... Rest of given options will be passed directly to the [node-memcached](http://github.com/3rd-Eden/node-memcached) and [kruptein](https://github.com/jas-/kruptein) constructors, see their appropriate docs for extra configurability. | ||
For details see [node-memcached](http://github.com/3rd-Eden/node-memcached). | ||
## Upgrading to v2.x.x | ||
When upgrading from pre v2 and using data encryption please flush all the session entries from memcached before rolling the update. | ||
Sessions without data encryption are not affected. | ||
## Upgrading from v0.x.x -> v1.x.x | ||
@@ -69,0 +77,0 @@ |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
14583
17.19%11
37.5%320
18.96%105
8.25%1
-50%3
50%4
Infinity%4
300%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added