UNPKG

14.5 kBMarkdownView Raw
1# connect-mongo
2
3MongoDB session store for [Connect](https://github.com/senchalabs/connect) and [Express](http://expressjs.com/) written in Typescript.
4
5[![npm version](https://img.shields.io/npm/v/connect-mongo.svg)](https://www.npmjs.com/package/connect-mongo)
6[![downloads](https://img.shields.io/npm/dm/connect-mongo.svg)](https://www.npmjs.com/package/connect-mongo)
7[![Sanity check](https://github.com/jdesboeufs/connect-mongo/actions/workflows/sanity.yml/badge.svg)](https://github.com/jdesboeufs/connect-mongo/actions/workflows/sanity.yml)
8[![Coverage Status](https://coveralls.io/repos/jdesboeufs/connect-mongo/badge.svg?branch=master&service=github)](https://coveralls.io/github/jdesboeufs/connect-mongo?branch=master)
9
10> Breaking change in V4 and rewritten the whole project using Typescript. Please checkout the [migration guide](MIGRATION_V4.md) and [changelog](CHANGELOG.md) for details.
11
12- [Install](#install)
13- [Compatibility](#compatibility)
14- [Usage](#usage)
15 - [Express or Connect integration](#express-or-connect-integration)
16 - [Connection to MongoDB](#connection-to-mongodb)
17- [Known issues](#known-issues)
18 - [Native autoRemove causing error on close](#native-autoremove-causing-error-on-close)
19 - [MongoError exports circular dependency](#mongoerror-exports-circular-dependency)
20 - [Existing encrypted v3.2.0 sessions are not decrypted correctly by v4](#existing-encrypted-v320-sessions-are-not-decrypted-correctly-by-v4)
21- [Events](#events)
22- [Session expiration](#session-expiration)
23- [Remove expired sessions](#remove-expired-sessions)
24 - [Set MongoDB to clean expired sessions (default mode)](#set-mongodb-to-clean-expired-sessions-default-mode)
25 - [Set the compatibility mode](#set-the-compatibility-mode)
26 - [Disable expired sessions cleaning](#disable-expired-sessions-cleaning)
27- [Lazy session update](#lazy-session-update)
28- [Transparent encryption/decryption of session data](#transparent-encryptiondecryption-of-session-data)
29- [Options](#options)
30 - [Connection-related options (required)](#connection-related-options-required)
31 - [More options](#more-options)
32 - [Crypto-related options](#crypto-related-options)
33- [Development](#development)
34 - [Example application](#example-application)
35 - [Release](#release)
36- [License](#license)
37
38## Install
39
40```
41npm install connect-mongo
42yarn add connect-mongo
43```
44
45* You may also need to run install `mongodb` if you do not have it installed already because `mongodb` is not a `peerDependencies` instead.
46* If you are upgrading from v3.x to v4, please checkout the [migration guide](./MIGRATION_V4.md) for details.
47* If you are upgrading v4.x to latest version, you may check the [example](./example) and [options](#options) for details.
48
49## Compatibility
50
51* Support Express up to `5.0`
52* Support [native MongoDB driver](http://mongodb.github.io/node-mongodb-native/) `>= 4.0`
53* Support Node.js 12, 14 and 16
54* Support [MongoDB](https://www.mongodb.com/) `3.2+`
55
56For extended compatibility, see previous versions [v3.x](https://github.com/jdesboeufs/connect-mongo/tree/v3.x).
57But please note that we are not maintaining v3.x anymore.
58
59## Usage
60
61### Express or Connect integration
62
63Express `4.x`, `5.0` and Connect `3.x`:
64
65```js
66const session = require('express-session');
67const MongoStore = require('connect-mongo');
68
69app.use(session({
70 secret: 'foo',
71 store: MongoStore.create(options)
72}));
73```
74
75```ts
76import session from 'express-session'
77import MongoStore from 'connect-mongo'
78
79app.use(session({
80 secret: 'foo',
81 store: MongoStore.create(options)
82}));
83```
84
85### Connection to MongoDB
86
87In many circumstances, `connect-mongo` will not be the only part of your application which need a connection to a MongoDB database. It could be interesting to re-use an existing connection.
88
89Alternatively, you can configure `connect-mongo` to establish a new connection.
90
91#### Create a new connection from a MongoDB connection string
92
93[MongoDB connection strings](http://docs.mongodb.org/manual/reference/connection-string/) are __the best way__ to configure a new connection. For advanced usage, [more options](http://mongodb.github.io/node-mongodb-native/driver-articles/mongoclient.html#mongoclient-connect-options) can be configured with `mongoOptions` property.
94
95```js
96// Basic usage
97app.use(session({
98 store: MongoStore.create({ mongoUrl: 'mongodb://localhost/test-app' })
99}));
100
101// Advanced usage
102app.use(session({
103 store: MongoStore.create({
104 mongoUrl: 'mongodb://user12345:foobar@localhost/test-app?authSource=admin&w=1',
105 mongoOptions: advancedOptions // See below for details
106 })
107}));
108```
109
110#### Re-use an existing native MongoDB driver client promise
111
112In this case, you just have to give your `MongoClient` instance to `connect-mongo`.
113
114```js
115/*
116** There are many ways to create MongoClient.
117** You should refer to the driver documentation.
118*/
119
120// Database name present in the connection string will be used
121app.use(session({
122 store: MongoStore.create({ clientPromise })
123}));
124
125// Explicitly specifying database name
126app.use(session({
127 store: MongoStore.create({
128 clientPromise,
129 dbName: 'test-app'
130 })
131}));
132```
133
134## Known issues
135
136[Known issues](https://github.com/jdesboeufs/connect-mongo/issues?q=is%3Aopen+is%3Aissue+label%3Abug) in GitHub Issues page.
137
138### Native autoRemove causing error on close
139
140- Calling `close()` immediately after creating the session store may cause error when the async index creation is in process when `autoRemove: 'native'`. You may want to manually manage the autoRemove index. [#413](https://github.com/jdesboeufs/connect-mongo/issues/413)
141
142### MongoError exports circular dependency
143
144The following error can be safely ignore from [official reply](https://developer.mongodb.com/community/forums/t/warning-accessing-non-existent-property-mongoerror-of-module-exports-inside-circular-dependency/15411/5).
145
146```
147(node:16580) Warning: Accessing non-existent property 'MongoError' of module exports inside circular dependency
148(Use `node --trace-warnings ...` to show where the warning was created)
149```
150
151### Existing encrypted v3.2.0 sessions are not decrypted correctly by v4
152
153v4 cannot decrypt the session encrypted from v3.2 due to a bug. Please take a look on this issue for possible workaround. [#420](https://github.com/jdesboeufs/connect-mongo/issues/420)
154
155## Events
156
157A `MongoStore` instance will emit the following events:
158
159| Event name | Description | Payload
160| ----- | ----- | ----- |
161| `create` | A session has been created | `sessionId` |
162| `touch` | A session has been touched (but not modified) | `sessionId` |
163| `update` | A session has been updated | `sessionId` |
164| `set` | A session has been created OR updated _(for compatibility purpose)_ | `sessionId` |
165| `destroy` | A session has been destroyed manually | `sessionId` |
166
167## Session expiration
168
169When the session cookie has an expiration date, `connect-mongo` will use it.
170
171Otherwise, it will create a new one, using `ttl` option.
172
173```js
174app.use(session({
175 store: MongoStore.create({
176 mongoUrl: 'mongodb://localhost/test-app',
177 ttl: 14 * 24 * 60 * 60 // = 14 days. Default
178 })
179}));
180```
181
182__Note:__ Each time an user interacts with the server, its session expiration date is refreshed.
183
184## Remove expired sessions
185
186By default, `connect-mongo` uses MongoDB's TTL collection feature (2.2+) to have mongod automatically remove expired sessions. But you can change this behavior.
187
188### Set MongoDB to clean expired sessions (default mode)
189
190`connect-mongo` will create a TTL index for you at startup. You MUST have MongoDB 2.2+ and administration permissions.
191
192```js
193app.use(session({
194 store: MongoStore.create({
195 mongoUrl: 'mongodb://localhost/test-app',
196 autoRemove: 'native' // Default
197 })
198}));
199```
200
201__Note:__ If you use `connect-mongo` in a very concurrent environment, you should avoid this mode and prefer setting the index yourself, once!
202
203### Set the compatibility mode
204
205In some cases you can't or don't want to create a TTL index, e.g. Azure Cosmos DB.
206
207`connect-mongo` will take care of removing expired sessions, using defined interval.
208
209```js
210app.use(session({
211 store: MongoStore.create({
212 mongoUrl: 'mongodb://localhost/test-app',
213 autoRemove: 'interval',
214 autoRemoveInterval: 10 // In minutes. Default
215 })
216}));
217```
218
219### Disable expired sessions cleaning
220
221You are in production environnement and/or you manage the TTL index elsewhere.
222
223```js
224app.use(session({
225 store: MongoStore.create({
226 mongoUrl: 'mongodb://localhost/test-app',
227 autoRemove: 'disabled'
228 })
229}));
230```
231
232## Lazy session update
233
234If you are using [express-session](https://github.com/expressjs/session) >= [1.10.0](https://github.com/expressjs/session/releases/tag/v1.10.0) and don't want to resave all the session on database every single time that the user refresh the page, you can lazy update the session, by limiting a period of time.
235
236```js
237app.use(express.session({
238 secret: 'keyboard cat',
239 saveUninitialized: false, // don't create session until something stored
240 resave: false, //don't save session if unmodified
241 store: MongoStore.create({
242 mongoUrl: 'mongodb://localhost/test-app',
243 touchAfter: 24 * 3600 // time period in seconds
244 })
245}));
246```
247
248by doing this, setting `touchAfter: 24 * 3600` you are saying to the session be updated only one time in a period of 24 hours, does not matter how many request's are made (with the exception of those that change something on the session data)
249
250
251## Transparent encryption/decryption of session data
252
253When working with sensitive session data it is [recommended](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Session_Management_Cheat_Sheet.md) to use encryption
254
255```js
256const store = MongoStore.create({
257 mongoUrl: 'mongodb://localhost/test-app',
258 crypto: {
259 secret: 'squirrel'
260 }
261})
262```
263
264## Options
265
266### Connection-related options (required)
267
268One of the following options should be provided. If more than one option are provided, each option will take precedence over others according to priority.
269
270|Priority|Option|Description|
271|:------:|------|-----------|
272|1|`mongoUrl`|A [connection string](https://docs.mongodb.com/manual/reference/connection-string/) for creating a new MongoClient connection. If database name is not present in the connection string, database name should be provided using `dbName` option. |
273|2|`clientPromise`|A Promise that is resolved with MongoClient connection. If the connection was established without database name being present in the connection string, database name should be provided using `dbName` option.|
274|3|`client`|An existing MongoClient connection. If the connection was established without database name being present in the connection string, database name should be provided using `dbName` option.|
275
276### More options
277
278|Option|Default|Description|
279|------|:-----:|-----------|
280|`mongoOptions`|`{ useUnifiedTopology: true }`|Options object for [`MongoClient.connect()`](https://mongodb.github.io/node-mongodb-native/3.3/api/MongoClient.html#.connect) method. Can be used with `mongoUrl` option.|
281|`dbName`||A name of database used for storing sessions. Can be used with `mongoUrl`, or `clientPromise` options. Takes precedence over database name present in the connection string.|
282|`collectionName`|`'sessions'`|A name of collection used for storing sessions.|
283|`ttl`|`1209600`|The maximum lifetime (in seconds) of the session which will be used to set `session.cookie.expires` if it is not yet set. Default is 14 days.|
284|`autoRemove`|`'native'`|Behavior for removing expired sessions. Possible values: `'native'`, `'interval'` and `'disabled'`.|
285|`autoRemoveInterval`|`10`|Interval (in minutes) used when `autoRemove` option is set to `interval`.|
286|`touchAfter`|`0`|Interval (in seconds) between session updates.|
287|`stringify`|`true`|If `true`, connect-mongo will serialize sessions using `JSON.stringify` before setting them, and deserialize them with `JSON.parse` when getting them. This is useful if you are using types that MongoDB doesn't support.|
288|`serialize`||Custom hook for serializing sessions to MongoDB. This is helpful if you need to modify the session before writing it out.|
289|`unserialize`||Custom hook for unserializing sessions from MongoDB. This can be used in scenarios where you need to support different types of serializations (e.g., objects and JSON strings) or need to modify the session before using it in your app.|
290|`writeOperationOptions`||Options object to pass to every MongoDB write operation call that supports it (e.g. `update`, `remove`). Useful for adjusting the write concern. Only exception: If `autoRemove` is set to `'interval'`, the write concern from the `writeOperationOptions` object will get overwritten.|
291|`transformId`||Transform original `sessionId` in whatever you want to use as storage key.|
292|`crypto`||Crypto related options. See below.|
293
294### Crypto-related options
295
296|Option|Default|Description|
297|------|:-----:|-----------|
298|`secret`|`false`|Enables transparent crypto in accordance with [OWASP session management recommendations](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Session_Management_Cheat_Sheet.md).|
299|`algorithm`|`'aes-256-gcm'`|Allows for changes to the default symmetric encryption cipher. See [`crypto.getCiphers()`](https://nodejs.org/api/crypto.html#crypto_crypto_getciphers) for supported algorithms.|
300|`hashing`|`'sha512'`|May be used to change the default hashing algorithm. See [`crypto.getHashes()`](https://nodejs.org/api/crypto.html#crypto_crypto_gethashes) for supported hashing algorithms.|
301|`encodeas`|`'hex'`|Specify to change the session data cipher text encoding.|
302|`key_size`|`32`|When using varying algorithms the key size may be used. Default value `32` is based on the `AES` blocksize.|
303|`iv_size`|`16`|This can be used to adjust the default [IV](https://csrc.nist.gov/glossary/term/IV) size if a different algorithm requires a different size.|
304|`at_size`|`16`|When using newer `AES` modes such as the default `GCM` or `CCM` an authentication tag size can be defined.|
305
306## Development
307
308```
309yarn install
310docker-compose up -d
311# Run these 2 lines in 2 shell
312yarn watch:build
313yarn watch:test
314```
315
316### Example application
317
318```
319yarn link
320cd example
321yarn link "connect-mongo"
322yarn install
323yarn start
324```
325
326### Release
327
328Since I cannot access the setting page. I can only do it manually.
329
3301. Bump version, update `CHANGELOG.md` and README. Commit and push.
3312. Run `yarn build && yarn test && npm publish`
3323. `git tag vX.Y.Z && git push --tags`
333
334## License
335
336The MIT License