mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #15519 from overleaf/em-upgrade-passport
Upgrade passport GitOrigin-RevId: b93bfcab39ba3d2ab4efb4814371defec8ca95c4
This commit is contained in:
parent
96c11e8755
commit
d96283e593
6 changed files with 85 additions and 95 deletions
26
package-lock.json
generated
26
package-lock.json
generated
|
@ -30573,15 +30573,20 @@
|
|||
}
|
||||
},
|
||||
"node_modules/passport": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz",
|
||||
"integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==",
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz",
|
||||
"integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==",
|
||||
"dependencies": {
|
||||
"passport-strategy": "1.x.x",
|
||||
"pause": "0.0.1"
|
||||
"pause": "0.0.1",
|
||||
"utils-merge": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/jaredhanson"
|
||||
}
|
||||
},
|
||||
"node_modules/passport-google-oauth20": {
|
||||
|
@ -43525,7 +43530,7 @@
|
|||
"otplib": "^12.0.1",
|
||||
"p-limit": "^2.3.0",
|
||||
"parse-data-url": "^2.0.0",
|
||||
"passport": "^0.4.1",
|
||||
"passport": "^0.6.0",
|
||||
"passport-google-oauth20": "^2.0.0",
|
||||
"passport-ldapauth": "^2.1.4",
|
||||
"passport-local": "^1.0.0",
|
||||
|
@ -52267,7 +52272,7 @@
|
|||
"otplib": "^12.0.1",
|
||||
"p-limit": "^2.3.0",
|
||||
"parse-data-url": "^2.0.0",
|
||||
"passport": "^0.4.1",
|
||||
"passport": "^0.6.0",
|
||||
"passport-google-oauth20": "^2.0.0",
|
||||
"passport-ldapauth": "^2.1.4",
|
||||
"passport-local": "^1.0.0",
|
||||
|
@ -70997,12 +71002,13 @@
|
|||
}
|
||||
},
|
||||
"passport": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz",
|
||||
"integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==",
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz",
|
||||
"integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==",
|
||||
"requires": {
|
||||
"passport-strategy": "1.x.x",
|
||||
"pause": "0.0.1"
|
||||
"pause": "0.0.1",
|
||||
"utils-merge": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"passport-google-oauth20": {
|
||||
|
|
|
@ -80,30 +80,36 @@ const AuthenticationController = {
|
|||
// This function is middleware which wraps the passport.authenticate middleware,
|
||||
// so we can send back our custom `{message: {text: "", type: ""}}` responses on failure,
|
||||
// and send a `{redir: ""}` response on success
|
||||
passport.authenticate('local', function (err, user, info) {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
if (user) {
|
||||
// `user` is either a user object or false
|
||||
AuthenticationController.setAuditInfo(req, { method: 'Password login' })
|
||||
return AuthenticationController.finishLogin(user, req, res, next)
|
||||
} else {
|
||||
if (info.redir != null) {
|
||||
return res.json({ redir: info.redir })
|
||||
passport.authenticate(
|
||||
'local',
|
||||
{ keepSessionInfo: true },
|
||||
function (err, user, info) {
|
||||
if (err) {
|
||||
return next(err)
|
||||
}
|
||||
if (user) {
|
||||
// `user` is either a user object or false
|
||||
AuthenticationController.setAuditInfo(req, {
|
||||
method: 'Password login',
|
||||
})
|
||||
return AuthenticationController.finishLogin(user, req, res, next)
|
||||
} else {
|
||||
res.status(info.status || 200)
|
||||
delete info.status
|
||||
const body = { message: info }
|
||||
const { errorReason } = info
|
||||
if (errorReason) {
|
||||
body.errorReason = errorReason
|
||||
delete info.errorReason
|
||||
if (info.redir != null) {
|
||||
return res.json({ redir: info.redir })
|
||||
} else {
|
||||
res.status(info.status || 200)
|
||||
delete info.status
|
||||
const body = { message: info }
|
||||
const { errorReason } = info
|
||||
if (errorReason) {
|
||||
body.errorReason = errorReason
|
||||
delete info.errorReason
|
||||
}
|
||||
return res.json(body)
|
||||
}
|
||||
return res.json(body)
|
||||
}
|
||||
}
|
||||
})(req, res, next)
|
||||
)(req, res, next)
|
||||
},
|
||||
|
||||
finishLogin(user, req, res, next) {
|
||||
|
@ -557,55 +563,34 @@ const AuthenticationController = {
|
|||
}
|
||||
|
||||
function _afterLoginSessionSetup(req, user, callback) {
|
||||
if (callback == null) {
|
||||
callback = function () {}
|
||||
}
|
||||
req.login(user, function (err) {
|
||||
req.login(user, { keepSessionInfo: true }, function (err) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error from req.login', {
|
||||
user_id: user._id,
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
// Regenerate the session to get a new sessionID (cookie value) to
|
||||
// protect against session fixation attacks
|
||||
const oldSession = req.session
|
||||
req.session.destroy(function (err) {
|
||||
delete req.session.__tmp
|
||||
delete req.session.csrfSecret
|
||||
req.session.save(function (err) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error when trying to destroy old session', {
|
||||
OError.tag(err, 'error saving regenerated session after login', {
|
||||
user_id: user._id,
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
req.sessionStore.generate(req)
|
||||
// Note: the validation token is not writable, so it does not get
|
||||
// transferred to the new session below.
|
||||
for (const key in oldSession) {
|
||||
const value = oldSession[key]
|
||||
if (key !== '__tmp' && key !== 'csrfSecret') {
|
||||
req.session[key] = value
|
||||
}
|
||||
UserSessionsManager.trackSession(user, req.sessionID, function () {})
|
||||
if (!req.deviceHistory) {
|
||||
// Captcha disabled or SSO-based login.
|
||||
return callback()
|
||||
}
|
||||
req.session.save(function (err) {
|
||||
if (err) {
|
||||
OError.tag(err, 'error saving regenerated session after login', {
|
||||
user_id: user._id,
|
||||
})
|
||||
return callback(err)
|
||||
}
|
||||
UserSessionsManager.trackSession(user, req.sessionID, function () {})
|
||||
if (!req.deviceHistory) {
|
||||
// Captcha disabled or SSO-based login.
|
||||
return callback()
|
||||
}
|
||||
req.deviceHistory.add(user.email)
|
||||
req.deviceHistory
|
||||
.serialize(req.res)
|
||||
.catch(err => {
|
||||
logger.err({ err }, 'cannot serialize deviceHistory')
|
||||
})
|
||||
.finally(() => callback())
|
||||
})
|
||||
req.deviceHistory.add(user.email)
|
||||
req.deviceHistory
|
||||
.serialize(req.res)
|
||||
.catch(err => {
|
||||
logger.err({ err }, 'cannot serialize deviceHistory')
|
||||
})
|
||||
.finally(() => callback())
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -266,7 +266,8 @@ async function tryDeleteUser(req, res, next) {
|
|||
const sessionId = req.sessionID
|
||||
|
||||
if (typeof req.logout === 'function') {
|
||||
req.logout()
|
||||
const logout = promisify(req.logout)
|
||||
await logout()
|
||||
}
|
||||
|
||||
const destroySession = promisify(req.session.destroy.bind(req.session))
|
||||
|
@ -431,9 +432,10 @@ async function doLogout(req) {
|
|||
logger.debug({ user }, 'logging out')
|
||||
const sessionId = req.sessionID
|
||||
|
||||
// passport logout
|
||||
if (typeof req.logout === 'function') {
|
||||
req.logout()
|
||||
// passport logout
|
||||
const logout = promisify(req.logout.bind(req))
|
||||
await logout()
|
||||
}
|
||||
|
||||
const destroySession = promisify(req.session.destroy.bind(req.session))
|
||||
|
|
|
@ -137,7 +137,7 @@
|
|||
"otplib": "^12.0.1",
|
||||
"p-limit": "^2.3.0",
|
||||
"parse-data-url": "^2.0.0",
|
||||
"passport": "^0.4.1",
|
||||
"passport": "^0.6.0",
|
||||
"passport-google-oauth20": "^2.0.0",
|
||||
"passport-ldapauth": "^2.1.4",
|
||||
"passport-local": "^1.0.0",
|
||||
|
|
|
@ -77,7 +77,7 @@ describe('AuthenticationController', function () {
|
|||
'../User/UserSessionsManager': (this.UserSessionsManager = {
|
||||
trackSession: sinon.stub(),
|
||||
untrackSession: sinon.stub(),
|
||||
revokeAllUserSessions: sinon.stub().callsArgWith(1, null),
|
||||
revokeAllUserSessions: sinon.stub().yields(null),
|
||||
}),
|
||||
'../../infrastructure/Modules': (this.Modules = {
|
||||
hooks: { fire: sinon.stub().yields(null, []) },
|
||||
|
@ -184,17 +184,17 @@ describe('AuthenticationController', function () {
|
|||
describe('passportLogin', function () {
|
||||
beforeEach(function () {
|
||||
this.info = null
|
||||
this.req.login = sinon.stub().callsArgWith(1, null)
|
||||
this.req.login = sinon.stub().yields(null)
|
||||
this.res.json = sinon.stub()
|
||||
this.req.session = {
|
||||
passport: { user: this.user },
|
||||
postLoginRedirect: '/path/to/redir/to',
|
||||
}
|
||||
this.req.session.destroy = sinon.stub().callsArgWith(0, null)
|
||||
this.req.session.save = sinon.stub().callsArgWith(0, null)
|
||||
this.req.session.destroy = sinon.stub().yields(null)
|
||||
this.req.session.save = sinon.stub().yields(null)
|
||||
this.req.sessionStore = { generate: sinon.stub() }
|
||||
this.AuthenticationController.finishLogin = sinon.stub()
|
||||
this.passport.authenticate.callsArgWith(1, null, this.user, this.info)
|
||||
this.passport.authenticate.yields(null, this.user, this.info)
|
||||
this.err = new Error('woops')
|
||||
})
|
||||
|
||||
|
@ -205,7 +205,7 @@ describe('AuthenticationController', function () {
|
|||
|
||||
describe('when authenticate produces an error', function () {
|
||||
beforeEach(function () {
|
||||
this.passport.authenticate.callsArgWith(1, this.err)
|
||||
this.passport.authenticate.yields(this.err)
|
||||
})
|
||||
|
||||
it('should return next with an error', function () {
|
||||
|
@ -221,7 +221,7 @@ describe('AuthenticationController', function () {
|
|||
describe('when authenticate produces a user', function () {
|
||||
beforeEach(function () {
|
||||
this.req.session.postLoginRedirect = 'some_redirect'
|
||||
this.passport.authenticate.callsArgWith(1, null, this.user, this.info)
|
||||
this.passport.authenticate.yields(null, this.user, this.info)
|
||||
})
|
||||
|
||||
afterEach(function () {
|
||||
|
@ -244,7 +244,7 @@ describe('AuthenticationController', function () {
|
|||
describe('when authenticate does not produce a user', function () {
|
||||
beforeEach(function () {
|
||||
this.info = { text: 'a', type: 'b' }
|
||||
this.passport.authenticate.callsArgWith(1, null, false, this.info)
|
||||
this.passport.authenticate.yields(null, false, this.info)
|
||||
})
|
||||
|
||||
it('should not call finishLogin', function () {
|
||||
|
@ -273,8 +273,7 @@ describe('AuthenticationController', function () {
|
|||
beforeEach(function () {
|
||||
this.AuthenticationController._recordFailedLogin = sinon.stub()
|
||||
this.AuthenticationController._recordSuccessfulLogin = sinon.stub()
|
||||
this.Modules.hooks.fire = sinon.stub().callsArgWith(3, null, [])
|
||||
// @AuthenticationController.establishUserSession = sinon.stub().callsArg(2)
|
||||
this.Modules.hooks.fire = sinon.stub().yields(null, [])
|
||||
this.req.body = {
|
||||
email: this.email,
|
||||
password: this.password,
|
||||
|
@ -290,7 +289,7 @@ describe('AuthenticationController', function () {
|
|||
beforeEach(function () {
|
||||
this.Modules.hooks.fire = sinon
|
||||
.stub()
|
||||
.callsArgWith(3, null, [null, { redir: '/somewhere' }, null])
|
||||
.yields(null, [null, { redir: '/somewhere' }, null])
|
||||
})
|
||||
|
||||
it('should stop early and call done with this info object', function (done) {
|
||||
|
@ -311,7 +310,7 @@ describe('AuthenticationController', function () {
|
|||
|
||||
describe('when the users rate limit', function () {
|
||||
beforeEach(function () {
|
||||
this.LoginRateLimiter.processLoginRequest.callsArgWith(1, null, false)
|
||||
this.LoginRateLimiter.processLoginRequest.yields(null, false)
|
||||
})
|
||||
|
||||
it('should block the request if the limit has been exceeded', function (done) {
|
||||
|
@ -330,10 +329,10 @@ describe('AuthenticationController', function () {
|
|||
describe('when the user is authenticated', function () {
|
||||
beforeEach(function () {
|
||||
this.cb = sinon.stub()
|
||||
this.LoginRateLimiter.processLoginRequest.callsArgWith(1, null, true)
|
||||
this.LoginRateLimiter.processLoginRequest.yields(null, true)
|
||||
this.AuthenticationManager.authenticate = sinon
|
||||
.stub()
|
||||
.callsArgWith(3, null, this.user)
|
||||
.yields(null, this.user)
|
||||
this.req.sessionID = Math.random()
|
||||
})
|
||||
|
||||
|
@ -361,7 +360,7 @@ describe('AuthenticationController', function () {
|
|||
beforeEach(function () {
|
||||
this.AuthenticationManager.authenticate = sinon
|
||||
.stub()
|
||||
.callsArgWith(3, new AuthenticationErrors.ParallelLoginError())
|
||||
.yields(new AuthenticationErrors.ParallelLoginError())
|
||||
this.AuthenticationController.doPassportLogin(
|
||||
this.req,
|
||||
this.req.body.email,
|
||||
|
@ -437,10 +436,10 @@ describe('AuthenticationController', function () {
|
|||
|
||||
describe('when the user is not authenticated', function () {
|
||||
beforeEach(function () {
|
||||
this.LoginRateLimiter.processLoginRequest.callsArgWith(1, null, true)
|
||||
this.LoginRateLimiter.processLoginRequest.yields(null, true)
|
||||
this.AuthenticationManager.authenticate = sinon
|
||||
.stub()
|
||||
.callsArgWith(3, null, null)
|
||||
.yields(null, null)
|
||||
this.cb = sinon.stub()
|
||||
this.AuthenticationController.doPassportLogin(
|
||||
this.req,
|
||||
|
@ -937,7 +936,7 @@ describe('AuthenticationController', function () {
|
|||
|
||||
describe('_recordSuccessfulLogin', function () {
|
||||
beforeEach(function () {
|
||||
this.UserUpdater.updateUser = sinon.stub().callsArg(2)
|
||||
this.UserUpdater.updateUser = sinon.stub().yields()
|
||||
this.AuthenticationController._recordSuccessfulLogin(
|
||||
this.user._id,
|
||||
this.callback
|
||||
|
@ -1078,8 +1077,8 @@ describe('AuthenticationController', function () {
|
|||
this.req.session = {
|
||||
passport: { user: { _id: 'one' } },
|
||||
}
|
||||
this.req.session.destroy = sinon.stub().callsArgWith(0, null)
|
||||
this.req.session.save = sinon.stub().callsArgWith(0, null)
|
||||
this.req.session.destroy = sinon.stub().yields(null)
|
||||
this.req.session.save = sinon.stub().yields(null)
|
||||
this.req.sessionStore = { generate: sinon.stub() }
|
||||
this.req.login = sinon.stub().yields(null)
|
||||
|
||||
|
@ -1345,9 +1344,7 @@ describe('AuthenticationController', function () {
|
|||
|
||||
describe('when req.session.save produces an error', function () {
|
||||
beforeEach(function () {
|
||||
this.req.session.save = sinon
|
||||
.stub()
|
||||
.callsArgWith(0, new Error('woops'))
|
||||
this.req.session.save = sinon.stub().yields(new Error('woops'))
|
||||
})
|
||||
|
||||
it('should produce an error', function (done) {
|
||||
|
|
|
@ -173,7 +173,7 @@ describe('UserController', function () {
|
|||
describe('tryDeleteUser', function () {
|
||||
beforeEach(function () {
|
||||
this.req.body.password = 'wat'
|
||||
this.req.logout = sinon.stub()
|
||||
this.req.logout = sinon.stub().yields()
|
||||
this.req.session.destroy = sinon.stub().yields()
|
||||
this.SessionManager.getLoggedInUserId = sinon
|
||||
.stub()
|
||||
|
|
Loading…
Reference in a new issue