diff --git a/lib/core-generators/new/templates/api/controllers/entrance/login.js.template b/lib/core-generators/new/templates/api/controllers/entrance/login.js.template index a95aabf8..7a0a7dfc 100644 --- a/lib/core-generators/new/templates/api/controllers/entrance/login.js.template +++ b/lib/core-generators/new/templates/api/controllers/entrance/login.js.template @@ -87,26 +87,32 @@ and exposed as \`req.me\`.)` await sails.helpers.passwords.checkPassword(password, userRecord.password) .intercept('incorrect', 'badCombo'); - // If "Remember Me" was enabled, then keep the session alive for - // a longer amount of time. (This causes an updated "Set Cookie" - // response header to be sent as the result of this request -- thus - // we must be dealing with a traditional HTTP request in order for - // this to work.) - if (rememberMe) { - if (this.req.isSocket) { - sails.log.warn( - 'Received `rememberMe: true` from a virtual request, but it was ignored\n'+ - 'because a browser\'s session cookie cannot be reset over sockets.\n'+ - 'Please use a traditional HTTP request instead.' - ); - } else { - this.req.session.cookie.maxAge = sails.config.custom.rememberMeCookieMaxAge; - } - }//fi - - // Modify the active session instance. - // (This will be persisted when the response is sent.) - this.req.session.userId = userRecord.id; + // Regenerate the session upon login: this prevents a class of Session fixation + // attacks, including CSRF token fixation. + await new Promise((resolve, reject) => { + this.req.session.regenerate(function(err) { + this.req.session.userId = userRecord.id; + + // If "Remember Me" was enabled, then keep the session alive for + // a longer amount of time. (This causes an updated "Set Cookie" + // response header to be sent as the result of this request -- thus + // we must be dealing with a traditional HTTP request in order for + // this to work.) + if (rememberMe) { + if (this.req.isSocket) { + sails.log.warn( + 'Received `rememberMe: true` from a virtual request, but it was ignored\n'+ + 'because a browser\'s session cookie cannot be reset over sockets.\n'+ + 'Please use a traditional HTTP request instead.' + ); + } else { + this.req.session.cookie.maxAge = sails.config.custom.rememberMeCookieMaxAge; + } + } + + resolve(); + }.bind(this)); + }); // In case there was an existing session (e.g. if we allow users to go to the login page // when they're already logged in), broadcast a message that we can display in other open tabs. diff --git a/lib/core-generators/new/templates/api/controllers/entrance/signup.js.template b/lib/core-generators/new/templates/api/controllers/entrance/signup.js.template index a5df774f..c3fa44e5 100644 --- a/lib/core-generators/new/templates/api/controllers/entrance/signup.js.template +++ b/lib/core-generators/new/templates/api/controllers/entrance/signup.js.template @@ -98,12 +98,17 @@ the account verification message.)`, }); } - // Store the user's new id in their session.<% if (verbose) {%> + // Regenerate the session and store the user's new id in their session.<% if (verbose) {%> // > We can use this (`req.session.userId`) to authenticate this user's future // > requests-- i.e. to tell that they came from from a "logged in" user, and // > from _this_ user, in particular. (That'll work until their session expires, // > we log them out, or they clear their cookies.)<% }%> - this.req.session.userId = newUserRecord.id; + await new Promise((resolve, reject) => { + this.req.session.regenerate(function(err) { + this.req.session.userId = newUserRecord.id; + resolve(); + }.bind(this)); + }); // In case there was an existing session (e.g. if we allow users to go to the signup page // when they're already logged in), broadcast a message that we can display in other open tabs.