UNPKG

10.6 kBMarkdownView Raw
1# cookie-session
2
3[![NPM Version][npm-version-image]][npm-url]
4[![NPM Downloads][npm-downloads-image]][npm-url]
5[![Build Status][ci-image]][ci-url]
6[![Test Coverage][coveralls-image]][coveralls-url]
7
8Simple cookie-based session middleware.
9
10A user session can be stored in two main ways with cookies: on the server or on
11the client. This module stores the session data on the client within a cookie,
12while a module like [express-session](https://www.npmjs.com/package/express-session)
13stores only a session identifier on the client within a cookie and stores the
14session data on the server, typically in a database.
15
16The following points can help you choose which to use:
17
18 * `cookie-session` does not require any database / resources on the server side,
19 though the total session data cannot exceed the browser's max cookie size.
20 * `cookie-session` can simplify certain load-balanced scenarios.
21 * `cookie-session` can be used to store a "light" session and include an identifier
22 to look up a database-backed secondary store to reduce database lookups.
23
24**NOTE** This module does not encrypt the session contents in the cookie, only provides
25signing to prevent tampering. The client will be able to read the session data by
26examining the cookie's value. Secret data should not be set in `req.session` without
27encrypting it, or use a server-side session instead.
28
29**NOTE** This module does not prevent session replay, as the expiration set is that
30of the cookie only; if that is a concern of your application, you can store an expiration
31date in `req.session` object and validate it on the sever, and implement any other logic
32to extend the session as your application needs.
33
34## Install
35
36This is a [Node.js](https://nodejs.org/en/) module available through the
37[npm registry](https://www.npmjs.com/). Installation is done using the
38[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
39
40```sh
41$ npm install cookie-session
42```
43
44## API
45
46```js
47var cookieSession = require('cookie-session')
48var express = require('express')
49
50var app = express()
51
52app.use(cookieSession({
53 name: 'session',
54 keys: [/* secret keys */],
55
56 // Cookie Options
57 maxAge: 24 * 60 * 60 * 1000 // 24 hours
58}))
59```
60
61### cookieSession(options)
62
63Create a new cookie session middleware with the provided options. This middleware
64will attach the property `session` to `req`, which provides an object representing
65the loaded session. This session is either a new session if no valid session was
66provided in the request, or a loaded session from the request.
67
68The middleware will automatically add a `Set-Cookie` header to the response if the
69contents of `req.session` were altered. _Note_ that no `Set-Cookie` header will be
70in the response (and thus no session created for a specific user) unless there are
71contents in the session, so be sure to add something to `req.session` as soon as
72you have identifying information to store for the session.
73
74#### Options
75
76Cookie session accepts these properties in the options object.
77
78##### name
79
80The name of the cookie to set, defaults to `session`.
81
82##### keys
83
84The list of keys to use to sign & verify cookie values, or a configured
85[`Keygrip`](https://www.npmjs.com/package/keygrip) instance. Set cookies are always
86signed with `keys[0]`, while the other keys are valid for verification, allowing
87for key rotation. If a `Keygrip` instance is provided, it can be used to
88change signature parameters like the algorithm of the signature.
89
90##### secret
91
92A string which will be used as single key if `keys` is not provided.
93
94##### Cookie Options
95
96Other options are passed to `cookies.get()` and `cookies.set()` allowing you
97to control security, domain, path, and signing among other settings.
98
99The options can also contain any of the following (for the full list, see
100[cookies module documentation](https://www.npmjs.org/package/cookies#readme):
101
102 - `maxAge`: a number representing the milliseconds from `Date.now()` for expiry
103 - `expires`: a `Date` object indicating the cookie's expiration date (expires at the end of session by default).
104 - `path`: a string indicating the path of the cookie (`/` by default).
105 - `domain`: a string indicating the domain of the cookie (no default).
106 - `partitioned`: a boolean indicating whether to partition the cookie in Chrome for the [CHIPS Update](https://developers.google.com/privacy-sandbox/3pcd/chips) (`false` by default). If this is true, Cookies from embedded sites will be partitioned and only readable from the same top level site from which it was created.
107 - `priority`: a string indicating the cookie priority. This can be set to `'low'`, `'medium'`, or `'high'`.
108 - `sameSite`: a boolean or string indicating whether the cookie is a "same site" cookie (`false` by default). This can be set to `'strict'`, `'lax'`, `'none'`, or `true` (which maps to `'strict'`).
109 - `secure`: a boolean indicating whether the cookie is only to be sent over HTTPS (`false` by default for HTTP, `true` by default for HTTPS). If this is set to `true` and Node.js is not directly over a TLS connection, be sure to read how to [setup Express behind proxies](https://expressjs.com/en/guide/behind-proxies.html) or the cookie may not ever set correctly.
110 - `httpOnly`: a boolean indicating whether the cookie is only to be sent over HTTP(S), and not made available to client JavaScript (`true` by default).
111 - `signed`: a boolean indicating whether the cookie is to be signed (`true` by default).
112 - `overwrite`: a boolean indicating whether to overwrite previously set cookies of the same name (`true` by default).
113
114### req.session
115
116Represents the session for the given request.
117
118#### .isChanged
119
120Is `true` if the session has been changed during the request.
121
122#### .isNew
123
124Is `true` if the session is new.
125
126#### .isPopulated
127
128Determine if the session has been populated with data or is empty.
129
130### req.sessionOptions
131
132Represents the session options for the current request. These options are a
133shallow clone of what was provided at middleware construction and can be
134altered to change cookie setting behavior on a per-request basis.
135
136### Destroying a session
137
138To destroy a session simply set it to `null`:
139
140```js
141req.session = null
142```
143
144### Saving a session
145
146Since the entire contents of the session is kept in a client-side cookie, the
147session is "saved" by writing a cookie out in a `Set-Cookie` response header.
148This is done automatically if there has been a change made to the session when
149the Node.js response headers are being written to the client and the session
150was not destroyed.
151
152## Examples
153
154### Simple view counter example
155
156```js
157var cookieSession = require('cookie-session')
158var express = require('express')
159
160var app = express()
161
162app.set('trust proxy', 1) // trust first proxy
163
164app.use(cookieSession({
165 name: 'session',
166 keys: ['key1', 'key2']
167}))
168
169app.get('/', function (req, res, next) {
170 // Update views
171 req.session.views = (req.session.views || 0) + 1
172
173 // Write response
174 res.end(req.session.views + ' views')
175})
176
177app.listen(3000)
178```
179
180### Per-user sticky max age
181
182```js
183var cookieSession = require('cookie-session')
184var express = require('express')
185
186var app = express()
187
188app.set('trust proxy', 1) // trust first proxy
189
190app.use(cookieSession({
191 name: 'session',
192 keys: ['key1', 'key2']
193}))
194
195// This allows you to set req.session.maxAge to let certain sessions
196// have a different value than the default.
197app.use(function (req, res, next) {
198 req.sessionOptions.maxAge = req.session.maxAge || req.sessionOptions.maxAge
199 next()
200})
201
202// ... your logic here ...
203```
204
205### Extending the session expiration
206
207This module does not send a `Set-Cookie` header if the contents of the session
208have not changed. This means that to extend the expiration of a session in the
209user's browser (in response to user activity, for example) some kind of
210modification to the session needs be made.
211
212```js
213var cookieSession = require('cookie-session')
214var express = require('express')
215
216var app = express()
217
218app.use(cookieSession({
219 name: 'session',
220 keys: ['key1', 'key2']
221}))
222
223// Update a value in the cookie so that the set-cookie will be sent.
224// Only changes every minute so that it's not sent with every request.
225app.use(function (req, res, next) {
226 req.session.nowInMinutes = Math.floor(Date.now() / 60e3)
227 next()
228})
229
230// ... your logic here ...
231```
232
233### Using a custom signature algorithm
234
235This example shows creating a custom `Keygrip` instance as the `keys` option
236to provide keys and additional signature configuration.
237
238```js
239var cookieSession = require('cookie-session')
240var express = require('express')
241var Keygrip = require('keygrip')
242
243var app = express()
244
245app.use(cookieSession({
246 name: 'session',
247 keys: new Keygrip(['key1', 'key2'], 'SHA384', 'base64')
248}))
249
250// ... your logic here ...
251```
252
253## Usage Limitations
254
255### Max Cookie Size
256
257Because the entire session object is encoded and stored in a cookie, it is
258possible to exceed the maximum cookie size limits on different browsers. The
259[RFC6265 specification](https://tools.ietf.org/html/rfc6265#section-6.1)
260recommends that a browser **SHOULD** allow
261
262> At least 4096 bytes per cookie (as measured by the sum of the length of
263> the cookie's name, value, and attributes)
264
265In practice this limit differs slightly across browsers. See a list of
266[browser limits here](http://browsercookielimits.iain.guru). As a rule
267of thumb **don't exceed 4093 bytes per domain**.
268
269If your session object is large enough to exceed a browser limit when encoded,
270in most cases the browser will refuse to store the cookie. This will cause the
271following requests from the browser to either a) not have any session
272information or b) use old session information that was small enough to not
273exceed the cookie limit.
274
275If you find your session object is hitting these limits, it is best to
276consider if data in your session should be loaded from a database on the
277server instead of transmitted to/from the browser with every request. Or
278move to an [alternative session strategy](https://github.com/expressjs/session#compatible-session-stores)
279
280## License
281
282[MIT](LICENSE)
283
284[ci-image]: https://badgen.net/github/checks/expressjs/cookie-session/master?label=ci
285[ci-url]: https://github.com/expressjs/cookie-session/actions?query=workflow%3Aci
286[coveralls-image]: https://badgen.net/coveralls/c/github/expressjs/cookie-session/master
287[coveralls-url]: https://coveralls.io/r/expressjs/cookie-session?branch=master
288[npm-downloads-image]: https://badgen.net/npm/dm/cookie-session
289[npm-url]: https://npmjs.org/package/cookie-session
290[npm-version-image]: https://badgen.net/npm/v/cookie-session