You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					197 lines
				
				7.9 KiB
			
		
		
			
		
	
	
					197 lines
				
				7.9 KiB
			| 
											3 years ago
										 | # @fastify/session
 | ||
|  | 
 | ||
|  |  | ||
|  | [](https://www.npmjs.com/package/@fastify/session) | ||
|  | [](https://snyk.io/test/github/fastify/session) | ||
|  | [](https://standardjs.com/) | ||
|  | 
 | ||
|  | A session plugin for [fastify](http://fastify.io/). | ||
|  | Requires the [fastify-cookie](https://github.com/fastify/fastify-cookie) plugin. | ||
|  | 
 | ||
|  | **NOTE:** This is the continuation of [fastify-session](https://github.com/SerayaEryn/fastify-session) which is unmaintained by now. All work credit till [`e201f7`](https://github.com/fastify/session/commit/e201f78fc9d7bd33c6f2e84988be7c8af4b5a8a3) commit goes to [SerayaEryn](https://github.com/SerayaEryn) and contributors. | ||
|  | 
 | ||
|  | ## Install
 | ||
|  | 
 | ||
|  | ``` | ||
|  | npm install @fastify/session | ||
|  | ``` | ||
|  | 
 | ||
|  | ## Usage
 | ||
|  | 
 | ||
|  | ```js | ||
|  | const fastify = require('fastify'); | ||
|  | const fastifySession = require('@fastify/session'); | ||
|  | const fastifyCookie = require('fastify-cookie'); | ||
|  | 
 | ||
|  | const app = fastify(); | ||
|  | app.register(fastifyCookie); | ||
|  | app.register(fastifySession, {secret: 'a secret with minimum length of 32 characters'}); | ||
|  | ``` | ||
|  | Store data in the session by adding it to the `session` decorator at the `request`: | ||
|  | ```js | ||
|  | app.register(fastifySession, {secret: 'a secret with minimum length of 32 characters'}); | ||
|  | app.addHook('preHandler', (request, reply, next) => { | ||
|  |   request.session.user = {name: 'max'}; | ||
|  |   next(); | ||
|  | }) | ||
|  | ``` | ||
|  | **NOTE**: For all unencrypted (HTTP) connections, you need to set the `secure` cookie option to `false`. See below for all cookie options and their details. | ||
|  | The `session` object has methods that allow you to get, save, reload and delete sessions. | ||
|  | ```js | ||
|  | app.register(fastifySession, {secret: 'a secret with minimum length of 32 characters'}); | ||
|  | app.addHook('preHandler', (request, reply, next) => { | ||
|  |   request.session.destroy(next); | ||
|  | }) | ||
|  | ``` | ||
|  | 
 | ||
|  | ## Examples
 | ||
|  | 
 | ||
|  | * [Authentication](https://github.com/fastify/example/tree/master/fastify-session-authentication) | ||
|  | 
 | ||
|  | ## API
 | ||
|  | ### session(fastify, options, next)
 | ||
|  | The session plugin accepts the following options. It decorates the request with the `sessionStore` and a `session` object. The session data is stored server-side using the configured session store. | ||
|  | #### options
 | ||
|  | ##### secret (required)
 | ||
|  | The secret used to sign the cookie. Must be an array of strings or a string with a length of 32 or greater. | ||
|  | 
 | ||
|  | If an array, the first secret is used to sign new cookies and is the first to be checked for incoming cookies. | ||
|  | Further secrets in the array are used to check incoming cookies in the order specified. | ||
|  | 
 | ||
|  | Note that the rest of the application may manipulate the array during its life cycle. This can be done by storing the array in a separate variable that is later used with mutating methods like unshift(), pop(), splice(), etc. | ||
|  | This can be used to rotate the signing secret at regular intervals. A secret should remain somewhere in the array as long as there are active sessions with cookies signed by it. Secrets management is left up to the rest of the application. | ||
|  | ##### cookieName (optional)
 | ||
|  | The name of the session cookie. Defaults to `sessionId`. | ||
|  | ##### cookie
 | ||
|  | The options object is used to generate the `Set-Cookie` header of the session cookie. May have the following properties: | ||
|  | * `path` - The `Path` attribute. Defaults to `/` (the root path). | ||
|  | * `maxAge` - A `number` in milliseconds that specifies the `Expires` attribute by adding the specified milliseconds to the current date. If both `expires` and `maxAge` are set, then `maxAge` is used. | ||
|  | * `httpOnly` - The `boolean` value of the `HttpOnly` attribute. Defaults to true. | ||
|  | * `secure` - The `boolean` value of the `Secure` attribute. Set this option to false when communicating over an unencrypted (HTTP) connection. Value can be set to `auto`; in this case, the `Secure` attribute will be set to false for an HTTP request. In the case of HTTPS, it will be set to true.  Defaults to true. | ||
|  | * `expires` - The expiration `date` used for the `Expires` attribute. If both `expires` and `maxAge` are set, then `maxAge` is used. | ||
|  | * `sameSite`- The `boolean` or `string` of the `SameSite` attribute. Using `Secure` mode with `auto` attribute will change the behavior of the `SameSite` attribute in `http` mode. The `SameSite` attribute will automatically be set to `Lax` with an `http` request. See this [link](https://www.chromium.org/updates/same-site). | ||
|  | * `domain` - The `Domain` attribute. | ||
|  | 
 | ||
|  | ##### store
 | ||
|  | A session store. Needs the following methods: | ||
|  | * set(sessionId, session, callback) | ||
|  | * get(sessionId, callback) | ||
|  | * destroy(sessionId, callback) | ||
|  | 
 | ||
|  | Compatible to stores from [express-session](https://github.com/expressjs/session). | ||
|  | 
 | ||
|  | Defaults to a simple in-memory store.</br> | ||
|  | **Note**: The default store should not be used in a production environment because it will leak memory. | ||
|  | 
 | ||
|  | ##### saveUninitialized (optional)
 | ||
|  | Save sessions to the store, even when they are new and not modified— defaults to `true`. | ||
|  | Setting this to `false` can save storage space and comply with the EU cookie law. | ||
|  | 
 | ||
|  | ##### idGenerator(request) (optional)
 | ||
|  | 
 | ||
|  | Function used to generate new session IDs. Defaults to [`uid(24)`](https://github.com/crypto-utils/uid-safe). | ||
|  | Custom implementation example: | ||
|  | ```js | ||
|  | idGenerator: (request) => { | ||
|  |      if (request.session.returningVisitor) return `returningVisitor-${uid(24)}` | ||
|  |      else return uid(24) | ||
|  | } | ||
|  | ``` | ||
|  | 
 | ||
|  | #### request.session
 | ||
|  | 
 | ||
|  | Allows to access or modify the session data. | ||
|  | 
 | ||
|  | #### Session#destroy(callback)
 | ||
|  | 
 | ||
|  | Allows to destroy the session in the store. If you do not pass a callback, a Promise will be returned. | ||
|  | 
 | ||
|  | #### Session#touch()
 | ||
|  | 
 | ||
|  | Updates the `expires` property of the session. | ||
|  | 
 | ||
|  | #### Session#regenerate(callback)
 | ||
|  | 
 | ||
|  | Regenerates the session by generating a new `sessionId` and persist it to the store. If you do not pass a callback, a Promise will be returned. | ||
|  | ```js | ||
|  | fastify.get('/regenerate', (request, reply, done) => { | ||
|  |   request.session.regenerate(error => { | ||
|  |     if (error) { | ||
|  |       done(error); | ||
|  |       return; | ||
|  |     } | ||
|  |     reply.send(request.session.sessionId); | ||
|  |   }); | ||
|  | }); | ||
|  | ``` | ||
|  | 
 | ||
|  | #### Session#reload(callback)
 | ||
|  | 
 | ||
|  | Reloads the session data from the store and re-populates the `request.session` object. If you do not pass a callback, a Promise will be returned. | ||
|  | 
 | ||
|  | #### Session#save(callback)
 | ||
|  | 
 | ||
|  | Save the session back to the store, replacing the contents on the store with the contents in memory. If you do not pass a callback, a Promise will be returned. | ||
|  | 
 | ||
|  | #### Session#get(key)
 | ||
|  | 
 | ||
|  | Gets a value from the session | ||
|  | 
 | ||
|  | #### Session#set(key, value)
 | ||
|  | 
 | ||
|  | Sets a value in the session | ||
|  | 
 | ||
|  | ### fastify.decryptSession(sessionId, request, cookieOptions, next)
 | ||
|  | This plugin also decorates the fastify instance with `decryptSession` in case you want to decrypt the session manually. | ||
|  | 
 | ||
|  | ```js | ||
|  | const { sessionId } = fastify.parseCookie(cookieHeader); | ||
|  | const request = {} | ||
|  | fastify.decryptSession(sessionId, request, () => { | ||
|  |   // request.session should be available here | ||
|  | }) | ||
|  | 
 | ||
|  | // or decrypt with custom cookie options: | ||
|  | fastify.decryptSession(sessionId, request, { maxAge: 86400 }, () => { | ||
|  |   // ... | ||
|  | }) | ||
|  | ``` | ||
|  | 
 | ||
|  | ### Typescript support:
 | ||
|  | This plugin supports typescript, and you can extend fastify module to add your custom session type. | ||
|  | 
 | ||
|  | ```ts | ||
|  | declare module "fastify" { | ||
|  |     interface Session { | ||
|  |         user_id: string | ||
|  |         other_key: your_prefer_type | ||
|  |         id?: number | ||
|  |     } | ||
|  | } | ||
|  | ``` | ||
|  | 
 | ||
|  | While this plugin can be used with express-session compatible stores, the type definitions of some stores might be tied to express-session, which means that casting to `any` might be required. For example: | ||
|  | 
 | ||
|  | ```ts | ||
|  | import fastifySession from '@fastify/session' | ||
|  | import fastify from 'fastify' | ||
|  | import Redis from 'ioredis' | ||
|  | import connectRedis from 'connect-redis' | ||
|  | 
 | ||
|  | const RedisStore = connectRedis(fastifySession as any) | ||
|  | const redisClient = new Redis(redisConfig) | ||
|  | 
 | ||
|  | const server = fastify() | ||
|  | server.register(fastifySession, { | ||
|  |   store: new RedisStore({ | ||
|  |     client: redisClient, | ||
|  |     // ... other options | ||
|  |   }) as any, | ||
|  |   // ... other options | ||
|  | }) | ||
|  | ``` | ||
|  | 
 | ||
|  | ## License
 | ||
|  | 
 | ||
|  | [MIT](./LICENSE) |