@@ -5,17 +5,20 @@ import fastifySession from '@fastify/session';
55import crypto from "node:crypto"
66
77
8-
9- export const COOKIE_NAME_ENCRYPTION_KEY = "session_encryption_key" ;
10- export const COOKIE_NAME_SESSION = "session-cookie" ;
11-
12- export const SECURE_SESSION_NAME = "encryptedSessionInternal" ;
13- export const UNDERLYING_SESSION_NAME = "underlyingSessionNotPerUserEncrypted" ;
14-
15- // This is the key used to store the encryption key in the secure session cookie
16- export const SECURE_COOKIE_KEY_ENCRYPTION_KEY = "encryptionKey" ;
17-
8+ // name of the request decorator this plugin exposes. Using request.encryptedSession can be used with set, get, clear delete
9+ // functions and the encryption will then be handled in this plugin.
1810export const REQUEST_DECORATOR = "encryptedSession" ;
11+ // name of the request decorator of the secure-session library that stores its session data in an encrypted cookie on user side.
12+ export const ENCRYPTED_COOKIE_REQUEST_DECORATOR = "encryptedSessionInternal" ;
13+ // name of the request decorator of the session library that is used as underlying store for this library.
14+ export const UNDERLYING_SESSION_NAME_REQUEST_DECORATOR = "underlyingSessionNotPerUserEncrypted" ;
15+
16+ // name of the secure-session cookie that stores the encryption key on user side.
17+ export const ENCRYPTION_KEY_COOKIE_NAME = "session_encryption_key" ;
18+ // the key used to store the encryption key in the secure-session cookie on user side.
19+ export const ENCRYPTED_COOKIE_KEY_ENCRYPTION_KEY = "encryptionKey" ;
20+ // name of the cookie that stores the session identifier on user side.
21+ export const SESSION_COOKIE_NAME = "session-cookie" ;
1922
2023async function encryptedSession ( fastify ) {
2124 const { COOKIE_SECRET , SESSION_SECRET , NODE_ENV } = fastify . config ;
@@ -24,8 +27,8 @@ async function encryptedSession(fastify) {
2427
2528 fastify . register ( secureSession , {
2629 secret : Buffer . from ( COOKIE_SECRET , "hex" ) ,
27- cookieName : COOKIE_NAME_ENCRYPTION_KEY ,
28- sessionName : SECURE_SESSION_NAME ,
30+ cookieName : ENCRYPTION_KEY_COOKIE_NAME ,
31+ sessionName : ENCRYPTED_COOKIE_REQUEST_DECORATOR ,
2932 cookie : {
3033 path : "/" ,
3134 httpOnly : true ,
@@ -34,11 +37,9 @@ async function encryptedSession(fastify) {
3437 maxAge : 60 * 60 * 24 * 7 , // 7 days
3538 } ,
3639 } ) ;
37-
38-
3940 fastify . register ( fastifySession , {
4041 secret : SESSION_SECRET ,
41- cookieName : COOKIE_NAME_SESSION ,
42+ cookieName : SESSION_COOKIE_NAME ,
4243 // sessionName: UNDERLYING_SESSION_NAME, //NOT POSSIBLE to change the name it is decorated on the request object
4344 cookie : {
4445 path : "/" ,
@@ -50,18 +51,18 @@ async function encryptedSession(fastify) {
5051 } ) ;
5152
5253 fastify . addHook ( 'onRequest' , ( request , _reply , next ) => {
53- //we use secure-session cookie to get the encryption key and decrypt the store
54- if ( ! request [ SECURE_SESSION_NAME ] . get ( SECURE_COOKIE_KEY_ENCRYPTION_KEY ) ) {
54+ const userEncryptionKey = getUserEncryptionKeyFromUserCookie ( request ) ;
55+ if ( ! userEncryptionKey ) {
5556 request . log . info ( { "plugin" : "encrypted-session" } , "user-side encryption key not found, creating new one" ) ;
5657
5758 let newEncryptionKey = generateSecureEncryptionKey ( ) ;
58- request [ SECURE_SESSION_NAME ] . set ( SECURE_COOKIE_KEY_ENCRYPTION_KEY , newEncryptionKey . toString ( 'base64' ) ) ;
59+ setUserEncryptionKeyIntoUserCookie ( request , newEncryptionKey ) ;
5960 request [ REQUEST_DECORATOR ] = createStore ( )
6061 newEncryptionKey = undefined
6162 } else {
6263 request . log . info ( { "plugin" : "encrypted-session" } , "user-side encryption key found, using existing one" ) ;
6364
64- const loadedEncryptionKey = Buffer . from ( request [ SECURE_SESSION_NAME ] . get ( SECURE_COOKIE_KEY_ENCRYPTION_KEY ) , "base64" ) ;
65+ const loadedEncryptionKey = Buffer . from ( userEncryptionKey , "base64" ) ;
6566
6667 const encryptedStore = request . session . get ( "encryptedStore" ) ;
6768 if ( encryptedStore ) {
@@ -89,7 +90,7 @@ async function encryptedSession(fastify) {
8990 // onSend is called before the response is send. Here we take encrypt the Session object and store it in the fastify-session.
9091 // Then we also want to make sure the unencrypted object is removed from memory
9192 fastify . addHook ( 'onSend' , async ( request , reply , _payload ) => {
92- const encryptionKey = Buffer . from ( request [ SECURE_SESSION_NAME ] . get ( SECURE_COOKIE_KEY_ENCRYPTION_KEY ) , "base64" ) ;
93+ const encryptionKey = Buffer . from ( getUserEncryptionKeyFromUserCookie ( request ) , "base64" ) ;
9394 if ( ! encryptionKey ) {
9495 // if no encryption key is found in the secure session, we cannot encrypt the store. This should not happen since an encrption key is generated when the request arrived
9596 request . log . error ( { "plugin" : "encrypted-session" } , "No encryption key found in secure session, cannot encrypt store" ) ;
@@ -112,6 +113,14 @@ async function encryptedSession(fastify) {
112113 await request . session . save ( )
113114 request . log . info ( "store encrypted and set into request.session.encryptedStore" ) ;
114115 } )
116+
117+ function getUserEncryptionKeyFromUserCookie ( request ) {
118+ return request [ ENCRYPTED_COOKIE_REQUEST_DECORATOR ] . get ( ENCRYPTED_COOKIE_KEY_ENCRYPTION_KEY )
119+ }
120+
121+ function setUserEncryptionKeyIntoUserCookie ( request , key ) {
122+ request [ ENCRYPTED_COOKIE_REQUEST_DECORATOR ] . set ( ENCRYPTED_COOKIE_KEY_ENCRYPTION_KEY , key . toString ( 'base64' ) ) ;
123+ }
115124}
116125
117126export default fp ( encryptedSession ) ;
0 commit comments