@fastify/secure-session
Advanced tools
Comparing version 8.1.0 to 8.1.1
14
index.js
@@ -14,3 +14,3 @@ 'use strict' | ||
return new Proxy(target[prop], { | ||
apply (applyTarget, thisArg, args) { | ||
apply (applyTarget, _thisArg, args) { | ||
return Reflect.apply(applyTarget, target, args) | ||
@@ -22,3 +22,3 @@ } | ||
// accessing own properties, eg request[sessionName].changed | ||
if (Object.prototype.hasOwnProperty.call(target, prop)) { | ||
if (Object.hasOwn(target, prop)) { | ||
return target[prop] | ||
@@ -32,3 +32,3 @@ } | ||
// modifying own properties, eg request[sessionName].changed | ||
if (Object.prototype.hasOwnProperty.call(target, prop)) { | ||
if (Object.hasOwn(target, prop)) { | ||
target[prop] = value | ||
@@ -248,6 +248,6 @@ return true | ||
function addHooks (fastify, options, next) { | ||
function addHooks (fastify, _options, next) { | ||
// the hooks must be registered after @fastify/cookie hooks | ||
fastify.addHook('onRequest', (request, reply, next) => { | ||
fastify.addHook('onRequest', (request, _reply, next) => { | ||
for (const [sessionName, { cookieName, cookieOptions }] of sessionNames.entries()) { | ||
@@ -272,3 +272,3 @@ let cookie = request.cookies[cookieName] | ||
fastify.addHook('onSend', (request, reply, payload, next) => { | ||
fastify.addHook('onSend', (request, reply, _payload, next) => { | ||
for (const [sessionName, { cookieName, cookieOptions }] of sessionNames.entries()) { | ||
@@ -374,3 +374,3 @@ const session = request[sessionName] | ||
if (typeof k !== 'string') { | ||
throw new Error('Key must be string or buffer') | ||
throw new TypeError('Key must be string or buffer') | ||
} | ||
@@ -377,0 +377,0 @@ |
{ | ||
"name": "@fastify/secure-session", | ||
"version": "8.1.0", | ||
"version": "8.1.1", | ||
"description": "Create a secure stateless cookie session for Fastify", | ||
@@ -12,3 +12,4 @@ "main": "index.js", | ||
"scripts": { | ||
"lint": "standard", | ||
"lint": "eslint", | ||
"lint:fix": "eslint --fix", | ||
"test": "npm run test:unit && npm run test:typescript", | ||
@@ -29,2 +30,21 @@ "test:unit": "c8 --100 node --test", | ||
"author": "Matteo Collina <hello@matteocollina.com>", | ||
"contributors": [ | ||
{ | ||
"name": "Tomas Della Vedova", | ||
"url": "http://delved.org" | ||
}, | ||
{ | ||
"name": "James Sumners", | ||
"url": "https://james.sumners.info" | ||
}, | ||
{ | ||
"name": "Aras Abbasi", | ||
"email": "aras.abbasi@gmail.com" | ||
}, | ||
{ | ||
"name": "Frazer Smith", | ||
"email": "frazer.dev@icloud.com", | ||
"url": "https://github.com/fdawgs" | ||
} | ||
], | ||
"license": "MIT", | ||
@@ -35,14 +55,25 @@ "bugs": { | ||
"homepage": "https://github.com/fastify/fastify-secure-session#readme", | ||
"funding": [ | ||
{ | ||
"type": "github", | ||
"url": "https://github.com/sponsors/fastify" | ||
}, | ||
{ | ||
"type": "opencollective", | ||
"url": "https://opencollective.com/fastify" | ||
} | ||
], | ||
"devDependencies": { | ||
"@fastify/pre-commit": "^2.0.2", | ||
"@sinonjs/fake-timers": "^13.0.2", | ||
"@sinonjs/fake-timers": "^14.0.0", | ||
"@types/node": "^22.0.0", | ||
"c8": "^10.1.2", | ||
"cookie": "^0.6.0", | ||
"cookie": "^1.0.1", | ||
"eslint": "^9.17.0", | ||
"fastify": "^5.0.0", | ||
"standard": "^17.1.0", | ||
"neostandard": "^0.12.0", | ||
"tsd": "^0.31.0" | ||
}, | ||
"dependencies": { | ||
"@fastify/cookie": "^10.0.0", | ||
"@fastify/cookie": "^11.0.1", | ||
"fastify-plugin": "^5.0.0", | ||
@@ -49,0 +80,0 @@ "sodium-native": "^4.0.10" |
# @fastify/secure-session | ||
![CI](https://github.com/fastify/fastify-secure-session/workflows/CI/badge.svg) | ||
[![CI](https://github.com/fastify/fastify-secure-session/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/fastify/fastify-secure-session/actions/workflows/ci.yml) | ||
[![NPM version](https://img.shields.io/npm/v/@fastify/secure-session.svg?style=flat)](https://www.npmjs.com/package/@fastify/secure-session) | ||
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/) | ||
[![neostandard javascript style](https://img.shields.io/badge/code_style-neostandard-brightgreen?style=flat)](https://github.com/neostandard/neostandard) | ||
@@ -57,3 +57,3 @@ Create a secure stateless cookie session for Fastify, based on libsodium's | ||
// the amount of time the session is considered valid; this is different from the cookie options | ||
// and based on value wihin the session. | ||
// and based on value within the session. | ||
expiry: 24 * 60 * 60, // Default 1 day | ||
@@ -69,3 +69,3 @@ cookie: { | ||
// or when using a custom sessionName: | ||
// or when using a custom sessionName: | ||
request.customSessionName.set('data', request.body) | ||
@@ -87,3 +87,3 @@ | ||
request.session.options({maxAge: 3600}) | ||
// Send the session cookie to the client even if the session data didn't change | ||
@@ -102,3 +102,3 @@ // can be used to update cookie expiration | ||
If you enable [`debug` level logging](https://fastify.dev/docs/latest/Reference/Logging/), | ||
you will see what steps the library is doing and understand why a session you | ||
you will see what steps the library is taking and understand why a session you | ||
expect to be there is not present. For extra details, you can also enable `trace` | ||
@@ -150,3 +150,3 @@ level logging. | ||
To use your hexadecimal string with this plugin you would need convert it back into a Buffer: | ||
To use your hexadecimal string with this plugin you would need to convert it back into a Buffer: | ||
@@ -175,3 +175,3 @@ ```js | ||
- Although the example reads the key from a file on disk, it is poor practice when it comes to security. Ideally, you should store secret/keys into a key management service like Vault, KMS or something similar and read them at run-time. | ||
- Although the example reads the key from a file on disk, it is poor practice when it comes to security. Ideally, you should store secret/keys in a key management service like Vault, KMS, or something similar and read them at run-time. | ||
- Use `httpOnly` session cookie for all production purposes to reduce the risk of session highjacking or XSS. | ||
@@ -227,3 +227,3 @@ | ||
It is possible to use an non-empty array for the key field to support key rotation as an additional security measure. | ||
It is possible to use a non-empty array for the key field to support key rotation as an additional security measure. | ||
Cookies will always be signed with the first key in the array to try to "err on the side of performance" however | ||
@@ -309,6 +309,6 @@ if decoding the key fails, it will attempt to decode using every subsequent value in the key array. | ||
WARNING: The more keys you have in the key array can make the decode operation get expensive if too many keys are used. | ||
WARNING: The more keys you have in the key array can make the decode operation get expensive if too many keys are used | ||
at once. It is recommended to only use 2 keys at a given time so that the most decode attempts will ever be is 2. | ||
This should allow ample support time for supporting sessions with an old key while rotating to the new one. If you have | ||
really long lived sessions it could be possible to need to support 3 or even 4 keys. Since old sessions are re-signed | ||
long-lived sessions it could be possible to need to support 3 or even 4 keys. Since old sessions are re-signed | ||
with the key at the first index the next time they are seen by the application, you can get away with this. That first | ||
@@ -334,3 +334,3 @@ time the older session is decoded will be a little more expensive though. | ||
If you need to encode or decode a session in related systems (like say `@fastify/websocket`, which does not use normal Fastify `Request` objects), you can use `@fastify/secure-session`'s decorators to encode and decode sessions yourself. This is less than ideal as this library's cookie setting code is battle tested by the community, but the option is there if you need it. | ||
If you need to encode or decode a session in related systems (like say `@fastify/websocket`, which does not use normal Fastify `Request` objects), you can use `@fastify/secure-session`'s decorators to encode and decode sessions yourself. This is less than ideal as this library's cookie setting code is battle-tested by the community, but the option is there if you need it. | ||
@@ -401,2 +401,2 @@ ```js | ||
MIT | ||
Licensed under [MIT](./LICENSE). |
/// <reference types="node" /> | ||
import { CookieSerializeOptions } from "@fastify/cookie"; | ||
import { FastifyPluginCallback, FastifyBaseLogger } from "fastify"; | ||
import { CookieSerializeOptions } from '@fastify/cookie' | ||
import { FastifyPluginCallback, FastifyBaseLogger } from 'fastify' | ||
declare module "fastify" { | ||
declare module 'fastify' { | ||
interface FastifyInstance { | ||
@@ -17,3 +17,3 @@ createSecureSession(data?: Record<string, any>): fastifySecureSession.Session | ||
type FastifySecureSession = FastifyPluginCallback<fastifySecureSession.SecureSessionPluginOptions | (fastifySecureSession.SecureSessionPluginOptions & Required<Pick<fastifySecureSession.SecureSessionPluginOptions, 'sessionName'>>)[]>; | ||
type FastifySecureSession = FastifyPluginCallback<fastifySecureSession.SecureSessionPluginOptions | (fastifySecureSession.SecureSessionPluginOptions & Required<Pick<fastifySecureSession.SecureSessionPluginOptions, 'sessionName'>>)[]> | ||
interface SessionData {} | ||
@@ -35,3 +35,3 @@ | ||
* | ||
* ignoreFields specifies which fields should be kept in the new session object. | ||
* ignoreFields specifies which fields should be kept in the new session object. | ||
*/ | ||
@@ -55,3 +55,3 @@ regenerate(ignoreFields?: string[]): void; | ||
declare function fastifySecureSession(...params: Parameters<FastifySecureSession>): ReturnType<FastifySecureSession> | ||
declare function fastifySecureSession (...params: Parameters<FastifySecureSession>): ReturnType<FastifySecureSession> | ||
export = fastifySecureSession |
@@ -1,2 +0,2 @@ | ||
import SecureSessionPlugin, { Session, SessionData } from ".."; | ||
import SecureSessionPlugin, { Session, SessionData } from '..' | ||
import fastify, { | ||
@@ -6,16 +6,15 @@ FastifyRequest, | ||
FastifyReply, | ||
} from "fastify"; | ||
import { expectType } from "tsd"; | ||
} from 'fastify' | ||
import { expectType } from 'tsd' | ||
const app: FastifyInstance = fastify(); | ||
app.register(SecureSessionPlugin); | ||
app.register(SecureSessionPlugin, { key: "foobar" }); | ||
app.register(SecureSessionPlugin, { key: Buffer.from("foo") }); | ||
app.register(SecureSessionPlugin, { key: ["foo", "bar"] }); | ||
app.register(SecureSessionPlugin, { secret: "foo", salt: "bar" }); | ||
app.register(SecureSessionPlugin, { sessionName: "foo", key: "bar" }); | ||
app.register(SecureSessionPlugin, { expiry: 24 * 60 * 60, key: "bar" }); | ||
app.register(SecureSessionPlugin, [{ sessionName: "foo", key: "bar" }, { sessionName: "bar", key: "bar" }]); | ||
const app: FastifyInstance = fastify() | ||
app.register(SecureSessionPlugin, { key: 'foobar' }) | ||
app.register(SecureSessionPlugin, { key: Buffer.from('foo') }) | ||
app.register(SecureSessionPlugin, { key: ['foo', 'bar'] }) | ||
app.register(SecureSessionPlugin, { secret: 'foo', salt: 'bar' }) | ||
app.register(SecureSessionPlugin, { sessionName: 'foo', key: 'bar' }) | ||
app.register(SecureSessionPlugin, { expiry: 24 * 60 * 60, key: 'bar' }) | ||
app.register(SecureSessionPlugin, [{ sessionName: 'foo', key: 'bar' }, { sessionName: 'bar', key: 'bar' }]) | ||
declare module ".." { | ||
declare module '..' { | ||
interface SessionData { | ||
@@ -30,3 +29,3 @@ foo: string; | ||
declare module "fastify" { | ||
declare module 'fastify' { | ||
interface FastifyRequest { | ||
@@ -37,35 +36,35 @@ foo: Session<FooSessionData>; | ||
app.get("/not-websockets", async (request, reply) => { | ||
expectType<FastifyRequest>(request); | ||
expectType<FastifyReply>(reply); | ||
expectType<Session>(request.session); | ||
request.session.set("foo", "bar"); | ||
expectType<string | undefined>(request.session.get("foo")); | ||
expectType<any>(request.session.get("baz")); | ||
expectType<string | undefined>(request.session.foo); | ||
expectType<SessionData | undefined>(request.session.data()); | ||
request.session.delete(); | ||
app.get('/not-websockets', async (request, reply) => { | ||
expectType<FastifyRequest>(request) | ||
expectType<FastifyReply>(reply) | ||
expectType<Session>(request.session) | ||
request.session.set('foo', 'bar') | ||
expectType<string | undefined>(request.session.get('foo')) | ||
expectType<any>(request.session.get('baz')) | ||
expectType<string | undefined>(request.session.foo) | ||
expectType<SessionData | undefined>(request.session.data()) | ||
request.session.delete() | ||
request.session.options({ maxAge: 42 }) | ||
request.session.touch(); | ||
request.session.touch() | ||
request.foo.set("foo", "bar"); | ||
expectType<string | undefined>(request.foo.get("foo")); | ||
expectType<any>(request.foo.get("baz")); | ||
request.foo.delete(); | ||
request.foo.options({ maxAge: 42 }); | ||
request.foo.touch(); | ||
request.foo.set('foo', 'bar') | ||
expectType<string | undefined>(request.foo.get('foo')) | ||
expectType<any>(request.foo.get('baz')) | ||
request.foo.delete() | ||
request.foo.options({ maxAge: 42 }) | ||
request.foo.touch() | ||
// @ts-expect-error: set undefined key | ||
request.session.set("baz", "bar"); | ||
request.session.set('baz', 'bar') | ||
// @ts-expect-error: invoke undefined key | ||
expectType<any>(request.session.baz); | ||
expectType<any>(request.session.baz) | ||
// @ts-expect-error: invoke undefined key | ||
request.baz.touch() | ||
}); | ||
}) | ||
expectType<Session | null>(app.decodeSecureSession("some cookie")) | ||
let session = app.createSecureSession({foo: 'bar'}); | ||
expectType<Session>(session); | ||
session = app.createSecureSession(); | ||
expectType<Session>(session); | ||
expectType<Session | null>(app.decodeSecureSession('some cookie')) | ||
let session = app.createSecureSession({ foo: 'bar' }) | ||
expectType<Session>(session) | ||
session = app.createSecureSession() | ||
expectType<Session>(session) | ||
expectType<string>(app.encodeSecureSession(session)) |
Sorry, the diff of this file is not supported yet
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
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
92552
35
2382
9
+ Added@fastify/cookie@11.0.2(transitive)
+ Addedcookie@1.0.2(transitive)
- Removed@fastify/cookie@10.0.1(transitive)
- Removedcookie-signature@1.2.2(transitive)
Updated@fastify/cookie@^11.0.1