@@ -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