From 780673ed31bb725bae08a088ed46378c84de72f1 Mon Sep 17 00:00:00 2001 From: Jessica Lawshe <5312836+lawshe@users.noreply.github.com> Date: Mon, 6 Nov 2023 09:28:07 -0600 Subject: [PATCH] Merge pull request #15558 from overleaf/jel-log-token-hash-mismatch [web] Log the project ID on link sharing token hash prefix mismatches GitOrigin-RevId: 37d15206f49920f49d61f22479b98dd4d448f6bd --- .../TokenAccess/TokenAccessController.js | 34 +++++++++++-------- .../TokenAccess/TokenAccessHandler.js | 4 +-- .../TokenAccess/TokenAccessControllerTests.js | 23 ++++++++++--- .../TokenAccess/TokenAccessHandlerTests.js | 27 +++++++++++---- 4 files changed, 62 insertions(+), 26 deletions(-) diff --git a/services/web/app/src/Features/TokenAccess/TokenAccessController.js b/services/web/app/src/Features/TokenAccess/TokenAccessController.js index 96bc6b69a8..54d33fbf91 100644 --- a/services/web/app/src/Features/TokenAccess/TokenAccessController.js +++ b/services/web/app/src/Features/TokenAccess/TokenAccessController.js @@ -233,13 +233,6 @@ async function grantTokenAccessReadAndWrite(req, res, next) { } const tokenType = TokenAccessHandler.TOKEN_TYPES.READ_AND_WRITE - TokenAccessHandler.checkTokenHashPrefix( - token, - tokenHashPrefix, - tokenType, - userId - ) - try { const [project, action] = await checkAndGetProjectOrResponseAction( tokenType, @@ -249,12 +242,22 @@ async function grantTokenAccessReadAndWrite(req, res, next) { res, next ) + + TokenAccessHandler.checkTokenHashPrefix( + token, + tokenHashPrefix, + tokenType, + userId, + project?._id + ) + if (action) { return action() } if (!project) { return next(new Errors.NotFoundError()) } + if (!confirmedByUser) { return res.json({ requireAccept: { @@ -303,13 +306,6 @@ async function grantTokenAccessReadOnly(req, res, next) { const tokenType = TokenAccessHandler.TOKEN_TYPES.READ_ONLY - TokenAccessHandler.checkTokenHashPrefix( - token, - tokenHashPrefix, - tokenType, - userId - ) - const docPublishedInfo = await TokenAccessHandler.promises.getV1DocPublishedInfo(token) if (docPublishedInfo.allow === false) { @@ -324,12 +320,22 @@ async function grantTokenAccessReadOnly(req, res, next) { res, next ) + + TokenAccessHandler.checkTokenHashPrefix( + token, + tokenHashPrefix, + tokenType, + userId, + project?._id + ) + if (action) { return action() } if (!project) { return next(new Errors.NotFoundError()) } + if (!confirmedByUser) { return res.json({ requireAccept: { diff --git a/services/web/app/src/Features/TokenAccess/TokenAccessHandler.js b/services/web/app/src/Features/TokenAccess/TokenAccessHandler.js index 2d6e4ad7d4..da8a931b24 100644 --- a/services/web/app/src/Features/TokenAccess/TokenAccessHandler.js +++ b/services/web/app/src/Features/TokenAccess/TokenAccessHandler.js @@ -287,7 +287,7 @@ const TokenAccessHandler = { return hash.digest('hex').slice(0, 6) }, - checkTokenHashPrefix(token, tokenHashPrefix, type, userId) { + checkTokenHashPrefix(token, tokenHashPrefix, type, userId, projectId) { let hashPrefixStatus if (tokenHashPrefix) { @@ -307,7 +307,7 @@ const TokenAccessHandler = { if (hashPrefixStatus === 'mismatch') { logger.info( - { tokenHashPrefix, hashPrefixStatus, userId }, + { tokenHashPrefix, hashPrefixStatus, userId, projectId }, 'mismatched token hash prefix' ) } diff --git a/services/web/test/unit/src/TokenAccess/TokenAccessControllerTests.js b/services/web/test/unit/src/TokenAccess/TokenAccessControllerTests.js index 2da7cb6f4b..05747514cf 100644 --- a/services/web/test/unit/src/TokenAccess/TokenAccessControllerTests.js +++ b/services/web/test/unit/src/TokenAccess/TokenAccessControllerTests.js @@ -113,7 +113,8 @@ describe('TokenAccessController', function () { this.token, 'prefix', 'readAndWrite', - this.user._id + this.user._id, + this.project._id ) }) }) @@ -162,7 +163,8 @@ describe('TokenAccessController', function () { this.token, undefined, 'readAndWrite', - this.user._id + this.user._id, + this.project._id ) }) }) @@ -199,14 +201,15 @@ describe('TokenAccessController', function () { ) }) - it('sends checks if hash prefix matches', function () { + it('checks if hash prefix matches', function () { expect( this.TokenAccessHandler.checkTokenHashPrefix ).to.have.been.calledWith( this.token, 'prefix', 'readOnly', - this.user._id + this.user._id, + this.project._id ) }) }) @@ -228,6 +231,18 @@ describe('TokenAccessController', function () { expect(this.ProjectAuditLogHandler.promises.addEntry).to.not.have.been .called }) + + it('still checks if hash prefix matches', function () { + expect( + this.TokenAccessHandler.checkTokenHashPrefix + ).to.have.been.calledWith( + this.token, + undefined, + 'readOnly', + this.user._id, + this.project._id + ) + }) }) }) }) diff --git a/services/web/test/unit/src/TokenAccess/TokenAccessHandlerTests.js b/services/web/test/unit/src/TokenAccess/TokenAccessHandlerTests.js index 824c000f11..5a516751e5 100644 --- a/services/web/test/unit/src/TokenAccess/TokenAccessHandlerTests.js +++ b/services/web/test/unit/src/TokenAccess/TokenAccessHandlerTests.js @@ -651,6 +651,7 @@ describe('TokenAccessHandler', function () { describe('checkTokenHashPrefix', function () { const userId = 'abc123' + const projectId = 'def456' it('sends "match" to metrics when prefix matches the prefix of the hash of the token', function () { const token = 'zxpxjrwdtsgd' const prefix = this.TokenAccessHandler.createTokenHashPrefix(token) @@ -658,7 +659,9 @@ describe('TokenAccessHandler', function () { this.TokenAccessHandler.checkTokenHashPrefix( token, `#${prefix}`, - 'readOnly' + 'readOnly', + userId, + projectId ) expect(this.Metrics.inc).to.have.been.calledWith( @@ -676,7 +679,8 @@ describe('TokenAccessHandler', function () { 'anothertoken', `#${prefix}`, 'readOnly', - userId + userId, + projectId ) expect(this.Metrics.inc).to.have.been.calledWith( @@ -687,7 +691,12 @@ describe('TokenAccessHandler', function () { } ) expect(this.logger.info).to.have.been.calledWith( - { tokenHashPrefix: prefix, hashPrefixStatus: 'mismatch', userId }, + { + tokenHashPrefix: prefix, + hashPrefixStatus: 'mismatch', + userId, + projectId, + }, 'mismatched token hash prefix' ) }) @@ -695,7 +704,9 @@ describe('TokenAccessHandler', function () { this.TokenAccessHandler.checkTokenHashPrefix( 'anothertoken', undefined, - 'readOnly' + 'readOnly', + userId, + projectId ) expect(this.Metrics.inc).to.have.been.calledWith( @@ -710,7 +721,9 @@ describe('TokenAccessHandler', function () { this.TokenAccessHandler.checkTokenHashPrefix( 'anothertoken', '#', - 'readOnly' + 'readOnly', + userId, + projectId ) expect(this.Metrics.inc).to.have.been.calledWith( @@ -728,7 +741,9 @@ describe('TokenAccessHandler', function () { this.TokenAccessHandler.checkTokenHashPrefix( token, `%23${prefix}`, - 'readOnly' + 'readOnly', + userId, + projectId ) expect(this.Metrics.inc).to.have.been.calledWith(