update devDependencies, clean up lint issues
[squeep-authentication-module] / lib / session-manager.js
index 7b33d8600b986cde34eab5dcf87a7a37b9aae150..4635547b7d42dbbebda728bf02983bf7aefb1bee 100644 (file)
@@ -8,7 +8,7 @@
 const { Communication: IndieAuthCommunication } = require('@squeep/indieauth-helper');
 const { MysteryBox } = require('@squeep/mystery-box');
 const { TOTP } = require('@squeep/totp');
-const { randomUUID } = require('crypto');
+const { randomUUID } = require('node:crypto');
 const common = require('./common');
 const Enum = require('./enum');
 const Template = require('./template');
@@ -35,6 +35,7 @@ class SessionManager {
    * @param {string[]} options.authenticator.authnEnabled authentication methods enabled
    * @param {number=} options.authenticator.inactiveSessionLifespanSeconds session timeout
    * @param {boolean} options.authenticator.secureAuthOnly allow only https
+   * @param {string=} options.authenticator.sessionCookieSameSite sameSite setting for session cookie, default Lax
    * @param {object=} options.dingus dingus options
    * @param {string=} options.dingus.proxyPrefix prefix on route paths
    * @param {string} options.dingus.selfBaseUrl base url
@@ -47,6 +48,8 @@ class SessionManager {
     this.db = authenticator.db; // TODO: take db arg in next major version bump
     this.options = options;
     this.proxyPrefix = options.dingus?.proxyPrefix ?? '';
+    this.secureAuthOnly = options.authenticator.secureAuthOnly ?? true;
+    this.sameSite = options.authenticator.sessionCookieSameSite || 'Lax';
     this.indieAuthCommunication = new IndieAuthCommunication(logger, options);
     this.mysteryBox = new MysteryBox(options);
     this.mysteryBox.on('statistics', common.mysteryBoxLogger(logger, _fileScope(this.constructor.name)));
@@ -67,8 +70,8 @@ class SessionManager {
     const secureSession = session && await this.mysteryBox.pack(session) || '""';
     common.addCookie(res, cookieName, secureSession, {
       httpOnly: true,
-      sameSite: 'Lax',
-      secure: this.options.authenticator.secureAuthOnly,
+      sameSite: this.sameSite,
+      secure: this.secureAuthOnly,
       maxAge: session && maxAge || 0,
       path,
     });
@@ -229,6 +232,7 @@ class SessionManager {
     }
 
     await this._sessionCookieSet(res, session);
+    res.setHeader(Enum.Header.SetLogin, Enum.LoginState.LoggedIn);
     res.setHeader(Enum.Header.Location, authorizationEndpoint.href);
     res.statusCode = 302; // Found
     res.end();
@@ -318,6 +322,7 @@ class SessionManager {
           authenticatedIdentifier: state.authenticatedIdentifier,
         };
         await this._sessionCookieSet(res, ctx.session);
+        res.setHeader(Enum.Header.SetLogin, Enum.LoginState.LoggedIn);
         res.statusCode = 302;
         res.setHeader(Enum.Header.Location, state.redirect);
         res.end();
@@ -397,6 +402,7 @@ class SessionManager {
       authenticatedIdentifier: ctx.authenticationId,
     };
     await this._sessionCookieSet(res, ctx.session);
+    res.setHeader(Enum.Header.SetLogin, Enum.LoginState.LoggedIn);
     res.statusCode = 302;
     res.setHeader(Enum.Header.Location, redirect);
     res.end();
@@ -415,6 +421,7 @@ class SessionManager {
     this.logger.debug(_scope, 'called', { ctx });
 
     await this._sessionCookieClear(res);
+    res.setHeader(Enum.Header.SetLogin, Enum.LoginState.LoggedOut);
 
     const redirect = ctx.queryParams['r'] || './';
 
@@ -536,6 +543,7 @@ class SessionManager {
     };
 
     await this._sessionCookieSet(res, ctx.session);
+    res.setHeader(Enum.Header.SetLogin, Enum.LoginState.LoggedIn);
     res.statusCode = 302;
     res.setHeader(Enum.Header.Location, redirect);
     res.end();
@@ -604,7 +612,7 @@ class SessionManager {
             await this._otpDisable(dbCtx, ctx, authData);
             return;
 
-          case 'confirm': 
+          case 'confirm':
             await this._otpConfirm(dbCtx, ctx);
             return;