Merge pull request #2249 from overleaf/bg-create-session-validation-token-for-all-sessions

move session validation into SessionStoreManager

GitOrigin-RevId: 438ec738f0ccaf9f072629d6203a334cb8439b83
This commit is contained in:
Brian Gough
2019-10-18 08:42:35 +00:00
committed by sharelatex
parent 5d3c125ffb
commit bc8ccf26c7
5 changed files with 141 additions and 80 deletions
@@ -48,6 +48,9 @@ describe('AuthenticationController', function() {
untrackSession: sinon.stub(),
revokeAllUserSessions: sinon.stub().callsArgWith(1, null)
}),
'../../infrastructure/SessionStoreManager': (this.SessionStoreManager = {
checkValidationToken: sinon.stub().returns(true)
}),
'../../infrastructure/Modules': (this.Modules = {
hooks: { fire: sinon.stub().callsArgWith(2, null, []) }
}),
@@ -296,16 +299,6 @@ describe('AuthenticationController', function() {
})
})
it('should set a vaildation token on the session', function(done) {
this.call(err => {
if (err) {
return done(err)
}
expect(this.req.session).to.have.property('validationToken', 'v1:omid')
done()
})
})
describe('when req.session.save produces an error', function() {
beforeEach(function() {
this.req.session.save = sinon.stub().callsArgWith(0, new Error('woops'))
@@ -330,45 +323,29 @@ describe('AuthenticationController', function() {
})
describe('getSessionUser', function() {
it('should accept a session without a validation token', function() {
it('should accept a valid session', function() {
this.req.session = {
passport: {
user: { _id: 'one' }
}
}
this.SessionStoreManager.checkValidationToken = sinon.stub().returns(true)
const user = this.AuthenticationController.getSessionUser(this.req)
expect(user).to.deep.equal({ _id: 'one' })
})
it('should reject an invalid validation token', function() {
this.req.sessionID = 'nabuchodonosorroidebabylone'
it('should reject an invalid session', function() {
this.req.session = {
validationToken: 'v1:gasp', // does not match last 4 characters of session id
passport: {
user: { _id: 'two' }
}
}
this.SessionStoreManager.checkValidationToken = sinon
.stub()
.returns(false)
const user = this.AuthenticationController.getSessionUser(this.req)
expect(user).to.be.null
})
it('should accept a valid validation token', function() {
this.req.sessionID = 'nabuchodonosorroidebabylone'
this.req.session = {
validationToken: 'v1:lone', // matches last 4 characters of session id
passport: {
user: { _id: 'three' }
}
}
const user = this.AuthenticationController.getSessionUser(this.req)
expect(user).to.deep.equal({ _id: 'three' })
})
it('should work with legacy sessions', function() {
this.req.session = { user: { _id: 'one' } }
const user = this.AuthenticationController.getSessionUser(this.req)
expect(user).to.deep.equal({ _id: 'one' })
})
})
describe('doPassportLogin', function() {
@@ -0,0 +1,70 @@
const sinon = require('sinon')
const chai = require('chai')
const { expect } = chai
const modulePath = '../../../../app/src/infrastructure/SessionStoreManager.js'
const SandboxedModule = require('sandboxed-module')
describe('SessionStoreManager', function() {
beforeEach(function() {
this.SessionStoreManager = SandboxedModule.require(modulePath, {
globals: {
console: console
},
requires: {
'metrics-sharelatex': (this.Metrics = { inc: sinon.stub() }),
'logger-sharelatex': (this.logger = {
log: sinon.stub(),
warn: sinon.stub(),
error: sinon.stub(),
err: sinon.stub()
})
}
})
this.sessionStore = {
generate: sinon.spy(req => {
req.session = {}
})
}
})
describe('enableValidationToken', function() {
beforeEach(function() {
this.originalGenerate = this.sessionStore.generate
this.SessionStoreManager.enableValidationToken(this.sessionStore)
})
it('should set up a wrapper around the generate function', function() {
expect(this.sessionStore.generate).to.not.equal(this.originalGenerate)
})
it('should add a validationToken when the generate function is called', function() {
this.req = { sessionID: '123456789' }
this.sessionStore.generate(this.req)
expect(this.req.session.validationToken).to.equal('v1:6789')
})
it('should not allow the token to be overwritten', function() {
this.req = { sessionID: '123456789' }
this.sessionStore.generate(this.req)
this.req.session.validationToken = 'try-to-overwrite-token'
expect(this.req.session.validationToken).to.equal('v1:6789')
})
})
describe('checkValidationToken', function() {
this.beforeEach(function() {
this.SessionStoreManager.enableValidationToken(this.sessionStore)
this.req = { sessionID: '123456789' }
this.sessionStore.generate(this.req)
})
it('should return true when the session id matches the validation token', function() {
const result = this.SessionStoreManager.checkValidationToken(this.req)
expect(result).to.equal(true)
})
it('should return false when the session id has changed', function() {
this.req.sessionID = 'abcdefghijklmnopqrstuvwxyz'
const result = this.SessionStoreManager.checkValidationToken(this.req)
expect(result).to.equal(false)
})
it('should return true when the session does not have a validation token', function() {
this.req = { sessionID: '123456789', session: {} }
const result = this.SessionStoreManager.checkValidationToken(this.req)
expect(result).to.equal(true)
})
})
})