* @param {object} options options
* @param {string | string[]} options.encryptionSecret encryption secret
* @param {object} options.authenticator authenticator options
- * @param {boolean} options.authenticator.secureAuthOnly disable auth over non-https
- * @param {string[]} options.authenticator.forbiddenPAMIdentifiers reject these identifiers for PAM auth
- * @param {string[]} options.authenticator.authnEnabled in order of preference for storing new credentials
+ * @param {boolean=} options.authenticator.secureAuthOnly disable auth over non-https
+ * @param {string=} options.authenticator.sessionCookieSameSite sameSite setting for session cookie, default Lax
+ * @param {string[]=} options.authenticator.forbiddenPAMIdentifiers reject these identifiers for PAM auth
+ * @param {string[]=} options.authenticator.authnEnabled in order of preference for storing new credentials
* @param {number=} options.authenticator.inactiveSessionLifespanSeconds session timeout
* @param {string[]=} options.authenticator.loginBlurb text for login page
* @param {string[]=} options.authenticator.indieAuthBlurb text for indieauth login section
* @param {string[]=} options.authenticator.userBlurb text for local user login section
* @param {string[]=} options.authenticator.otpBlurb text for otp entry
- * @param {string=} options.dingus dingus options
+ * @param {object=} options.dingus dingus options
* @param {string=} options.dingus.proxyPrefix base url prefix
*/
constructor(logger, db, options) {
this.options = options;
this.basicRealm = options.authenticator.basicRealm || packageName;
this.secureAuthOnly = options.authenticator.secureAuthOnly ?? true;
+ this.sameSite = options.authenticator.sessionCookieSameSite || 'Lax';
this.proxyPrefix = options.dingus?.proxyPrefix ?? '';
+ if (!['None', 'Lax', 'Strict'].includes(this.sameSite)) {
+ throw new RangeError(`invalid sameSite value "${this.sameSite}"`);
+ }
+
// First construct map of all available code-supported auth mechanisms.
this.authn = {
indieAuth: {},
common.addCookie(res, Enum.SessionCookie, ctx.cookie[Enum.SessionCookie], {
httpOnly: true,
maxAge: this.cookieLifespan,
- sameSite: 'Lax',
+ sameSite: this.sameSite,
path: `${this.proxyPrefix}/`,
secure: this.secureAuthOnly,
});
common.addCookie(res, Enum.SessionCookie, '""', {
httpOnly: true,
maxAge: 0,
- sameSite: 'Lax',
+ sameSite: this.sameSite,
path: `${this.proxyPrefix}/`,
secure: this.secureAuthOnly,
});
* @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
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)));
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,
});