* @param {Boolean} options.authenticator.secureAuthOnly
* @param {String[]} options.authenticator.forbiddenPAMIdentifiers
* @param {String[]} options.authenticator.authnEnabled
+ * @param {Number=} options.authenticator.inactiveSessionLifespanSeconds
* @param {String[]=} options.authenticator.loginBlurb
* @param {String[]=} options.authenticator.indieAuthBlurb
* @param {String[]=} options.authenticator.userBlurb
}
this.mysteryBox = new MysteryBox(logger, options);
+
+ this.cookieLifespan = options.authenticator.inactiveSessionLifespanSeconds || 60 * 60 * 24 * 32;
}
&& (ctx.session.authenticatedIdentifier
|| (profilesAllowed && ctx.session.authenticatedProfile))) {
this.logger.debug(_scope, 'valid session cookie', { ctx });
+ // Refresh timeout on valid session.
+ const cookieParts = [
+ sessionCookie,
+ 'HttpOnly',
+ `Max-Age=${this.cookieLifespan}`,
+ 'SameSite=Lax',
+ `Path=${this.options.dingus.proxyPrefix}/`,
+ ];
+ if (this.options.authenticator.secureAuthOnly) {
+ cookieParts.push('Secure');
+ }
+ res.setHeader(Enum.Header.SetCookie, cookieParts.join('; '));
return true;
}
`${Enum.SessionCookie}=""`,
'HttpOnly',
'Max-Age=0',
+ 'SameSite=Lax',
`Path=${this.options.dingus.proxyPrefix}/`,
];
if (this.options.authenticator.secureAuthOnly) {
/**
* Require auth for an API endpoint.
- * Check for valid local identifier in session, or Authentication header.
+ * Check for valid local identifier in Authorization header; optionally
+ * fall back to session cookie if no header provided.
* Prompts for Basic auth if not valid.
* @param {http.ClientRequest} req
* @param {http.ServerResponse} res
* @param {Boolean} sessionAlsoValid
*/
async apiRequiredLocal(req, res, ctx, sessionAlsoValid = true) {
- const validSession = sessionAlsoValid && this.sessionCheck(req, res, ctx, undefined, false, false);
+ const _scope = _fileScope('apiRequiredLocal');
+ this.logger.debug(_scope, 'called', { ctx, sessionAlsoValid });
+
+ // If a Authorization header was provided, never consider session as a fallback.
const authorizationHeader = req.getHeader(Enum.Header.Authorization);
- const validAuthorization = authorizationHeader && this.isValidAuthorization(authorizationHeader, ctx);
- if (validSession || validAuthorization) {
- return true;
+ if (authorizationHeader) {
+ if (await this.isValidAuthorization(authorizationHeader, ctx)) {
+ this.logger.debug(_scope, 'valid authorization', { ctx, sessionAlsoValid });
+ return true;
+ }
+ } else {
+ if (sessionAlsoValid
+ && await this.sessionCheck(req, res, ctx, undefined, false, false)) {
+ this.logger.debug(_scope, 'valid session', { ctx, sessionAlsoValid });
+ return true;
+ }
}
+
+ this.logger.debug(_scope, 'invalid authorization', { ctx, sessionAlsoValid });
this.requestBasic(res);
}
}
-module.exports = Authenticator;
\ No newline at end of file
+module.exports = Authenticator;