X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=lib%2Fsession-manager.js;h=43990cc376e4ee8b16a35092c2bf81620b3a1b9a;hb=29aaaee5ec2834fa363a8b9ea57bdc1362da4edc;hp=a97a0e0fd3f0edf2ed897e89c9f565e41843525c;hpb=a44a8c411be1831e7b2418212ee0b295206ca27a;p=squeep-authentication-module diff --git a/lib/session-manager.js b/lib/session-manager.js index a97a0e0..43990cc 100644 --- a/lib/session-manager.js +++ b/lib/session-manager.js @@ -6,6 +6,7 @@ const { Communication: IndieAuthCommunication } = require('@squeep/indieauth-helper'); const { MysteryBox } = require('@squeep/mystery-box'); +const { randomUUID } = require('crypto'); const common = require('./common'); const Enum = require('./enum'); const Template = require('./template'); @@ -22,15 +23,16 @@ class SessionManager { * @param {Number=} options.authenticator.inactiveSessionLifespanSeconds * @param {Boolean} options.authenticator.secureAuthOnly * @param {Object} options.dingus - * @param {Object} options.dingus.proxyPrefix - * @param {Object} options.dingus.selfBaseUrl + * @param {String} options.dingus.proxyPrefix + * @param {String} options.dingus.selfBaseUrl */ constructor(logger, authenticator, options) { this.logger = logger; this.authenticator = authenticator; this.options = options; this.indieAuthCommunication = new IndieAuthCommunication(logger, options); - this.mysteryBox = new MysteryBox(logger, options); + this.mysteryBox = new MysteryBox(options); + this.mysteryBox.on('statistics', common.mysteryBoxLogger(logger, _fileScope(this.constructor.name))); this.cookieLifespan = options.authenticator.inactiveSessionLifespanSeconds || 60 * 60 * 24 * 32; } @@ -51,6 +53,7 @@ class SessionManager { const cookieParts = [ `${cookieName}=${secureSession}`, 'HttpOnly', + 'SameSite=Lax', ]; if (this.options.authenticator.secureAuthOnly) { cookieParts.push('Secure'); @@ -123,9 +126,11 @@ class SessionManager { } // Otherwise, carry on with IndieAuth handshake. - let me, session, authorizationEndpoint; + let me, meAutoScheme, session, authorizationEndpoint; try { me = new URL(ctx.parsedBody['me']); + meAutoScheme = !!ctx.parsedBody['me_auto_scheme']; + } catch (e) { this.logger.debug(_scope, 'failed to parse supplied profile url', { ctx }); ctx.errors.push(`Unable to understand '${ctx.parsedBody['me']}' as a profile URL.`); @@ -133,8 +138,15 @@ class SessionManager { if (this.options.authenticator.authnEnabled.includes('indieAuth') && me) { - const profile = await this.indieAuthCommunication.fetchProfile(me); - if (!profile || !profile.metadata) { + let profile; + profile = await this.indieAuthCommunication.fetchProfile(me); + if ((!profile?.metadata) + && meAutoScheme) { + this.logger.debug(_scope, 'trying http fallback', { ctx }); + me.protocol = 'http'; + profile = await this.indieAuthCommunication.fetchProfile(me); + } + if (!profile?.metadata) { this.logger.debug(_scope, 'failed to find any profile information at url', { ctx }); ctx.errors.push(`No profile information was found at '${me}'.`); } else { @@ -169,9 +181,10 @@ class SessionManager { if (authorizationEndpoint) { const pkce = await IndieAuthCommunication.generatePKCE(); + const state = randomUUID(); session = { authorizationEndpoint: authorizationEndpoint.href, - state: ctx.requestId, + state, codeVerifier: pkce.codeVerifier, me, redirect, @@ -214,7 +227,7 @@ class SessionManager { const _scope = _fileScope('getAdminLogout'); this.logger.debug(_scope, 'called', { ctx }); - this._sessionCookieSet(res, '', 0); + await this._sessionCookieSet(res, '', 0); const redirect = ctx.queryParams['r'] || './'; @@ -345,4 +358,4 @@ class SessionManager { } -module.exports = SessionManager; \ No newline at end of file +module.exports = SessionManager;