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:
@@ -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)
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user