Skip to content

Commit

Permalink
refactor(account): security enhancement
Browse files Browse the repository at this point in the history
  • Loading branch information
polonel committed May 16, 2022
1 parent 526cef3 commit 7f4eac1
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 28 deletions.
10 changes: 9 additions & 1 deletion src/controllers/api/v1/users.js
Expand Up @@ -369,6 +369,8 @@ apiUsers.update = function (req, res) {
const data = req.body
// saveGroups - Profile saving where groups are not sent
const saveGroups = !_.isUndefined(data.saveGroups) ? data.saveGroups : true
let passwordUpdated = false

const obj = {
fullname: data.aFullname,
title: data.aTitle,
Expand Down Expand Up @@ -402,6 +404,7 @@ apiUsers.update = function (req, res) {
) {
if (obj.password === obj.passconfirm) {
user.password = obj.password
passwordUpdated = true
}
}

Expand Down Expand Up @@ -476,7 +479,7 @@ apiUsers.update = function (req, res) {
}
}
},
function (err, results) {
async function (err, results) {
if (err) {
winston.debug(err)
return res.status(400).json({ success: false, error: err })
Expand All @@ -487,6 +490,11 @@ apiUsers.update = function (req, res) {
return { _id: g._id, name: g.name }
})

if (passwordUpdated) {
const Session = require('../../../models/session')
await Session.destroy(user._id)
}

return res.json({ success: true, user: user })
}
)
Expand Down
10 changes: 9 additions & 1 deletion src/controllers/api/v2/accounts.js
Expand Up @@ -246,6 +246,8 @@ accountsApi.update = function (req, res) {
var postData = req.body
if (!username || !postData) return apiUtil.sendApiError_InvalidPostData(res)

let passwordUpdated = false

async.series(
{
user: function (next) {
Expand All @@ -263,6 +265,7 @@ accountsApi.update = function (req, res) {
) {
if (postData.password === postData.passwordConfirm) {
user.password = postData.password
passwordUpdated = true
}
}

Expand Down Expand Up @@ -389,7 +392,7 @@ accountsApi.update = function (req, res) {
Department.getUserDepartments(postData._id, next)
}
},
function (err, results) {
async function (err, results) {
if (err) return apiUtil.sendApiError(res, 500, err.message)

var user = results.user.toJSON()
Expand All @@ -407,6 +410,11 @@ accountsApi.update = function (req, res) {
})
}

if (passwordUpdated) {
const Session = require('../../../models/session')
await Session.destroy(user._id)
}

return apiUtil.sendApiSuccess(res, { user: user })
}
)
Expand Down
8 changes: 5 additions & 3 deletions src/controllers/main.js
Expand Up @@ -189,10 +189,12 @@ mainController.l2AuthPost = function (req, res, next) {
}

mainController.logout = function (req, res) {
req.logout()
req.session.l2auth = null
req.session.destroy()
return res.redirect('/')
req.session.destroy(function () {
req.logout()
res.clearCookie('connect.sid')
return res.redirect('/')
})
}

mainController.forgotL2Auth = function (req, res) {
Expand Down
69 changes: 69 additions & 0 deletions src/models/session.js
@@ -0,0 +1,69 @@
/*
* . .o8 oooo
* .o8 "888 `888
* .o888oo oooo d8b oooo oooo .oooo888 .ooooo. .oooo.o 888 oooo
* 888 `888""8P `888 `888 d88' `888 d88' `88b d88( "8 888 .8P'
* 888 888 888 888 888 888 888ooo888 `"Y88b. 888888.
* 888 . 888 888 888 888 888 888 .o o. )88b 888 `88b.
* "888" d888b `V88V"V8P' `Y8bod88P" `Y8bod8P' 8""888P' o888o o888o
* ========================================================================
* Author: Chris Brame
* Updated: 5/16/22 3:01 PM
* Copyright (c) 2014-2022. All rights reserved.
*/
// This is used to connect to MongoStore for express-session to destroy the sessions of users

const mongoose = require('mongoose')
const winston = require('../logger')

const COLLECTION = 'sessions'

const SessionSchema = new mongoose.Schema(
{
_id: String,
expires: Date,
session: String
},
{ strict: false }
)

SessionSchema.statics.getAllSessionUsers = async function () {}

SessionSchema.statics.destroyUserSession = async function (userId) {
return new Promise((resolve, reject) => {
;(async () => {
try {
if (!userId) return reject(new Error('Invalid User Id'))

const userSessions = await this.model(COLLECTION).find({})

if (userSessions) {
for (const s of userSessions) {
const id = s._id
const sessionObject = JSON.parse(s.session)

if (
sessionObject.passport &&
sessionObject.passport.user &&
sessionObject.passport.user === userId.toString()
) {
delete sessionObject.passport
await this.model(COLLECTION).findOneAndUpdate({ _id: id }, { session: JSON.stringify(sessionObject) })
}
}

return resolve()
} else {
return resolve()
}
} catch (e) {
winston.error(e)
return reject(e)
}
})()
})
}

SessionSchema.statics.destroy = SessionSchema.statics.destroyUserSession

module.exports = mongoose.model(COLLECTION, SessionSchema)
32 changes: 9 additions & 23 deletions src/passport/index.js
Expand Up @@ -12,14 +12,14 @@
* Copyright (c) 2014-2019. All rights reserved.
*/

var passport = require('passport')
var Local = require('passport-local').Strategy
var TotpStrategy = require('passport-totp').Strategy
var JwtStrategy = require('passport-jwt').Strategy
var ExtractJwt = require('passport-jwt').ExtractJwt
var base32 = require('thirty-two')
var User = require('../models/user')
var nconf = require('nconf')
const passport = require('passport')
const Local = require('passport-local').Strategy
const TotpStrategy = require('passport-totp').Strategy
const JwtStrategy = require('passport-jwt').Strategy
const ExtractJwt = require('passport-jwt').ExtractJwt
const base32 = require('thirty-two')
const User = require('../models/user')
const nconf = require('nconf')

module.exports = function () {
passport.serializeUser(function (user, done) {
Expand Down Expand Up @@ -48,12 +48,7 @@ module.exports = function () {
return done(err)
}

if (!user || user.deleted) {
req.flash('loginMessage', '')
return done(null, false, req.flash('loginMessage', 'Invalid Username/Password'))
}

if (!User.validate(password, user.password)) {
if (!user || user.deleted || !User.validate(password, user.password)) {
req.flash('loginMessage', '')
return done(null, false, req.flash('loginMessage', 'Invalid Username/Password'))
}
Expand Down Expand Up @@ -100,15 +95,6 @@ module.exports = function () {
if (jwtPayload.exp < Date.now() / 1000) return done({ type: 'exp' })

return done(null, jwtPayload.user)

// User.findOne({ _id: jwtPayload.user._id }, function (err, user) {
// if (err) return done(err)
// if (user) {
// return done(null, jwtPayload.user)
// } else {
// return done(null, false)
// }
// })
}
)
)
Expand Down

0 comments on commit 7f4eac1

Please sign in to comment.