@fastify/secure-session
Advanced tools
Comparing version 7.1.0 to 7.3.0
'use strict' | ||
const fastify = require('fastify')({ logger: false }) | ||
const fs = require('fs') | ||
const path = require('path') | ||
const assert = require('assert') | ||
const fs = require('node:fs') | ||
const path = require('node:path') | ||
const assert = require('node:assert') | ||
@@ -8,0 +8,0 @@ fastify.register(require('../..'), { |
30
index.js
@@ -53,4 +53,9 @@ 'use strict' | ||
const cookieName = sessionOptions.cookieName || sessionName | ||
const expiry = sessionOptions.expiry || 86401 // 24 hours | ||
const cookieOptions = sessionOptions.cookieOptions || sessionOptions.cookie || {} | ||
if (cookieOptions.httpOnly === undefined) { | ||
cookieOptions.httpOnly = true | ||
} | ||
let key | ||
@@ -124,3 +129,4 @@ if (sessionOptions.secret) { | ||
cookieOptions, | ||
key | ||
key, | ||
expiry | ||
}) | ||
@@ -144,3 +150,3 @@ | ||
const { key } = sessionNames.get(sessionName) | ||
const { key, expiry } = sessionNames.get(sessionName) | ||
@@ -190,4 +196,11 @@ // do not use destructuring or it will deopt | ||
const parsed = JSON.parse(msg) | ||
if ((parsed.__ts + expiry) * 1000 - Date.now() <= 0) { | ||
// maximum validity is reached, resetting | ||
log.debug('@fastify/secure-session: expiry reached') | ||
return null | ||
} | ||
const session = new Proxy(new Session(JSON.parse(msg)), sessionProxyHandler) | ||
session.changed = signingKeyRotated | ||
return session | ||
@@ -235,3 +248,3 @@ }) | ||
request[sessionName] = new Proxy((result || new Session({})), sessionProxyHandler) | ||
request[sessionName] = result || new Proxy(new Session({}), sessionProxyHandler) | ||
} | ||
@@ -283,2 +296,6 @@ | ||
this.deleted = false | ||
if (this[kObj].__ts === undefined) { | ||
this[kObj].__ts = Math.round(Date.now() / 1000) | ||
} | ||
} | ||
@@ -305,3 +322,8 @@ | ||
data () { | ||
return this[kObj] | ||
const copy = { | ||
...this[kObj] | ||
} | ||
delete copy.__ts | ||
return copy | ||
} | ||
@@ -308,0 +330,0 @@ |
{ | ||
"name": "@fastify/secure-session", | ||
"version": "7.1.0", | ||
"version": "7.3.0", | ||
"description": "Create a secure stateless cookie session for Fastify", | ||
"main": "index.js", | ||
"type": "commonjs", | ||
"types": "types/index.d.ts", | ||
@@ -34,8 +35,9 @@ "bin": { | ||
"@fastify/pre-commit": "^2.0.2", | ||
"@sinonjs/fake-timers": "^11.2.2", | ||
"@types/node": "^20.1.0", | ||
"cookie": "^0.5.0", | ||
"cookie": "^0.6.0", | ||
"fastify": "^4.0.0", | ||
"standard": "^17.0.0", | ||
"tap": "^16.1.0", | ||
"tsd": "^0.28.0" | ||
"tsd": "^0.31.0" | ||
}, | ||
@@ -42,0 +44,0 @@ "dependencies": { |
@@ -37,3 +37,3 @@ # @fastify/secure-session | ||
```sh | ||
./node_modules/@fastify/secure-session/genkey.js > secret_key | ||
./node_modules/@fastify/secure-session/genkey.js > secret-key | ||
``` | ||
@@ -47,4 +47,4 @@ | ||
const fastify = require('fastify')({ logger: false }) | ||
const fs = require('fs') | ||
const path = require('path') | ||
const fs = require('node:fs') | ||
const path = require('node:path') | ||
@@ -58,2 +58,5 @@ fastify.register(require('@fastify/secure-session'), { | ||
key: fs.readFileSync(path.join(__dirname, 'secret-key')), | ||
// the amount of time the session is considered valid; this is different from the cookie options | ||
// and based on value wihin the session. | ||
expiry: 24 * 60 * 60, // Default 1 day | ||
cookie: { | ||
@@ -98,3 +101,3 @@ path: '/' | ||
If you enable [`debug` level logging](https://www.fastify.io/docs/latest/Reference/Logging/), | ||
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 | ||
@@ -255,3 +258,3 @@ expect to be there is not present. For extra details, you can also enable `trace` | ||
```js | ||
const fs = require('fs') | ||
const fs = require('node:fs') | ||
const fastify = require('fastify')({ logger: false }) | ||
@@ -339,3 +342,3 @@ | ||
The session data is typed as `{ [key: string]: any }`. This can be extended with [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) to get improved type support. | ||
The session data is defined as an interface called `SessionData`. It can be extended with [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) for improved type support. | ||
@@ -374,5 +377,8 @@ ```ts | ||
## TODO | ||
## Security Notice | ||
- [ ] add an option to just sign, and do not encrypt | ||
`@fastify/secure-session` stores the session within a cookie, and as a result an attacker could impersonate a user | ||
if the cookie is leaked. The maximum expiration time of the session is set by the `expiry` option, which has default | ||
1 day. Adjust this parameter accordingly. | ||
Moreover, to protect users from further attacks, all cookies are created as "http only" if not specified otherwise. | ||
@@ -379,0 +385,0 @@ ## License |
@@ -23,3 +23,3 @@ 'use strict' | ||
maxAge: 60, | ||
domain: 'fastify.io' | ||
domain: 'fastify.dev' | ||
}, | ||
@@ -72,3 +72,3 @@ sessionName: 'shortTermSession' | ||
t.equal(response.cookies[1].maxAge, 60) | ||
t.equal(response.cookies[1].domain, 'fastify.io') | ||
t.equal(response.cookies[1].domain, 'fastify.dev') | ||
@@ -75,0 +75,0 @@ fastify.inject({ |
@@ -18,2 +18,3 @@ /// <reference types="node" /> | ||
type FastifySecureSession = FastifyPluginCallback<fastifySecureSession.SecureSessionPluginOptions | (fastifySecureSession.SecureSessionPluginOptions & Required<Pick<fastifySecureSession.SecureSessionPluginOptions, 'sessionName'>>)[]>; | ||
interface SessionData {} | ||
@@ -33,6 +34,2 @@ declare namespace fastifySecureSession { | ||
export interface SessionData { | ||
[key: string]: any; | ||
} | ||
export type SecureSessionPluginOptions = { | ||
@@ -39,0 +36,0 @@ cookie?: CookieSerializeOptions |
@@ -42,3 +42,2 @@ import SecureSessionPlugin, { Session, SessionData } from ".."; | ||
expectType<string | undefined>(request.session.foo); | ||
expectType<any>(request.session.baz); | ||
expectType<SessionData | undefined>(request.session.data()); | ||
@@ -55,2 +54,9 @@ request.session.delete(); | ||
request.foo.touch(); | ||
// @ts-expect-error: set undefined key | ||
request.session.set("baz", "bar"); | ||
// @ts-expect-error: invoke undefined key | ||
expectType<any>(request.session.baz); | ||
// @ts-expect-error: invoke undefined key | ||
request.baz.touch() | ||
}); | ||
@@ -57,0 +63,0 @@ |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
77589
34
2073
381
0
8