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.
		
		
		
		
		
			
		
			
				
					144 lines
				
				4.0 KiB
			
		
		
			
		
	
	
					144 lines
				
				4.0 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								'use strict'
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const fp = require('fastify-plugin')
							 | 
						||
| 
								 | 
							
								const cookie = require('cookie')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const { Signer, sign, unsign } = require('./signer')
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function fastifyCookieSetCookie (reply, name, value, options, signer) {
							 | 
						||
| 
								 | 
							
								  const opts = Object.assign({}, options)
							 | 
						||
| 
								 | 
							
								  if (opts.expires && Number.isInteger(opts.expires)) {
							 | 
						||
| 
								 | 
							
								    opts.expires = new Date(opts.expires)
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (opts.signed) {
							 | 
						||
| 
								 | 
							
								    value = signer.sign(value)
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (opts.secure === 'auto') {
							 | 
						||
| 
								 | 
							
								    if (isConnectionSecure(reply.request)) {
							 | 
						||
| 
								 | 
							
								      opts.secure = true
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      opts.sameSite = 'lax'
							 | 
						||
| 
								 | 
							
								      opts.secure = false
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const serialized = cookie.serialize(name, value, opts)
							 | 
						||
| 
								 | 
							
								  let setCookie = reply.getHeader('Set-Cookie')
							 | 
						||
| 
								 | 
							
								  if (!setCookie) {
							 | 
						||
| 
								 | 
							
								    reply.header('Set-Cookie', serialized)
							 | 
						||
| 
								 | 
							
								    return reply
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (typeof setCookie === 'string') {
							 | 
						||
| 
								 | 
							
								    setCookie = [setCookie]
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  setCookie.push(serialized)
							 | 
						||
| 
								 | 
							
								  reply.removeHeader('Set-Cookie')
							 | 
						||
| 
								 | 
							
								  reply.header('Set-Cookie', setCookie)
							 | 
						||
| 
								 | 
							
								  return reply
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function fastifyCookieClearCookie (reply, name, options) {
							 | 
						||
| 
								 | 
							
								  const opts = Object.assign({ path: '/' }, options || { }, {
							 | 
						||
| 
								 | 
							
								    expires: new Date(1),
							 | 
						||
| 
								 | 
							
								    signed: undefined,
							 | 
						||
| 
								 | 
							
								    maxAge: undefined
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								  return fastifyCookieSetCookie(reply, name, '', opts)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function onReqHandlerWrapper (fastify) {
							 | 
						||
| 
								 | 
							
								  return function fastifyCookieOnReqHandler (fastifyReq, fastifyRes, done) {
							 | 
						||
| 
								 | 
							
								    fastifyReq.cookies = {} // New container per request. Issue #53
							 | 
						||
| 
								 | 
							
								    const cookieHeader = fastifyReq.raw.headers.cookie
							 | 
						||
| 
								 | 
							
								    if (cookieHeader) {
							 | 
						||
| 
								 | 
							
								      fastifyReq.cookies = fastify.parseCookie(cookieHeader)
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    done()
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function plugin (fastify, options, next) {
							 | 
						||
| 
								 | 
							
								  const secret = options.secret || ''
							 | 
						||
| 
								 | 
							
								  const enableRotation = Array.isArray(secret)
							 | 
						||
| 
								 | 
							
								  const algorithm = options.algorithm || 'sha256'
							 | 
						||
| 
								 | 
							
								  const signer = typeof secret === 'string' || enableRotation ? new Signer(secret, algorithm) : secret
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.decorate('parseCookie', parseCookie)
							 | 
						||
| 
								 | 
							
								  fastify.decorate('signCookie', signCookie)
							 | 
						||
| 
								 | 
							
								  fastify.decorate('unsignCookie', unsignCookie)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.decorateRequest('cookies', null)
							 | 
						||
| 
								 | 
							
								  fastify.decorateRequest('unsignCookie', unsignCookie)
							 | 
						||
| 
								 | 
							
								  fastify.decorateReply('setCookie', setCookie)
							 | 
						||
| 
								 | 
							
								  fastify.decorateReply('cookie', setCookie)
							 | 
						||
| 
								 | 
							
								  fastify.decorateReply('clearCookie', clearCookie)
							 | 
						||
| 
								 | 
							
								  fastify.decorateReply('unsignCookie', unsignCookie)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  fastify.addHook('onRequest', onReqHandlerWrapper(fastify))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  next()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // ***************************
							 | 
						||
| 
								 | 
							
								  function parseCookie (cookieHeader) {
							 | 
						||
| 
								 | 
							
								    return cookie.parse(cookieHeader, options.parseOptions)
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function signCookie (value) {
							 | 
						||
| 
								 | 
							
								    return signer.sign(value)
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function unsignCookie (value) {
							 | 
						||
| 
								 | 
							
								    return signer.unsign(value)
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function setCookie (name, value, cookieOptions) {
							 | 
						||
| 
								 | 
							
								    const opts = Object.assign({}, options.parseOptions, cookieOptions)
							 | 
						||
| 
								 | 
							
								    return fastifyCookieSetCookie(this, name, value, opts, signer)
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function clearCookie (name, options) {
							 | 
						||
| 
								 | 
							
								    return fastifyCookieClearCookie(this, name, options)
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function isConnectionSecure (request) {
							 | 
						||
| 
								 | 
							
								  return (
							 | 
						||
| 
								 | 
							
								    request.raw.socket?.encrypted === true ||
							 | 
						||
| 
								 | 
							
								    request.headers['x-forwarded-proto'] === 'https'
							 | 
						||
| 
								 | 
							
								  )
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const fastifyCookie = fp(plugin, {
							 | 
						||
| 
								 | 
							
								  fastify: '4.x',
							 | 
						||
| 
								 | 
							
								  name: '@fastify/cookie'
							 | 
						||
| 
								 | 
							
								})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * These export configurations enable JS and TS developers
							 | 
						||
| 
								 | 
							
								 * to consume fastify-cookie in whatever way best suits their needs.
							 | 
						||
| 
								 | 
							
								 * Some examples of supported import syntax includes:
							 | 
						||
| 
								 | 
							
								 * - `const fastifyCookie = require('fastify-cookie')`
							 | 
						||
| 
								 | 
							
								 * - `const { fastifyCookie } = require('fastify-cookie')`
							 | 
						||
| 
								 | 
							
								 * - `import * as fastifyCookie from 'fastify-cookie'`
							 | 
						||
| 
								 | 
							
								 * - `import { fastifyCookie } from 'fastify-cookie'`
							 | 
						||
| 
								 | 
							
								 * - `import fastifyCookie from 'fastify-cookie'`
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								fastifyCookie.signerFactory = Signer
							 | 
						||
| 
								 | 
							
								fastifyCookie.fastifyCookie = fastifyCookie
							 | 
						||
| 
								 | 
							
								fastifyCookie.default = fastifyCookie
							 | 
						||
| 
								 | 
							
								module.exports = fastifyCookie
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								fastifyCookie.fastifyCookie.signerFactory = Signer
							 | 
						||
| 
								 | 
							
								fastifyCookie.fastifyCookie.Signer = Signer
							 | 
						||
| 
								 | 
							
								fastifyCookie.fastifyCookie.sign = sign
							 | 
						||
| 
								 | 
							
								fastifyCookie.fastifyCookie.unsign = unsign
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.signerFactory = Signer
							 | 
						||
| 
								 | 
							
								module.exports.Signer = Signer
							 | 
						||
| 
								 | 
							
								module.exports.sign = sign
							 | 
						||
| 
								 | 
							
								module.exports.unsign = unsign
							 |