From e788d49af01b2e1ee09d29ce805300e0875a6322 Mon Sep 17 00:00:00 2001 From: Steven Shipton Date: Wed, 26 Oct 2016 21:44:39 +0100 Subject: [PATCH] Don't require all keys to be configured to enable key checks (#2816) (#2941) * Add tests. Fail request if any of the 4 optional keys does not match * Only require one key to be supplied in the request, except when no keys are configured * Use const over let, var --- spec/Middlewares.spec.js | 54 ++++++++++++++++++++++++++++++++++++++++ src/middlewares.js | 21 ++++++---------- 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/spec/Middlewares.spec.js b/spec/Middlewares.spec.js index 45efc2fd..a17b40e7 100644 --- a/spec/Middlewares.spec.js +++ b/spec/Middlewares.spec.js @@ -17,6 +17,7 @@ describe('middlewares', () => { return fakeReq.headers[key.toLowerCase()] } }; + fakeRes = jasmine.createSpyObj('fakeRes', ['end', 'status']); AppCache.put(fakeReq.body._ApplicationId, {}); }); @@ -35,6 +36,59 @@ describe('middlewares', () => { }); }); + it('should give invalid response when keys are configured but no key supplied', () => { + AppCache.put(fakeReq.body._ApplicationId, { + masterKey: 'masterKey', + restAPIKey: 'restAPIKey' + }); + middlewares.handleParseHeaders(fakeReq, fakeRes); + expect(fakeRes.status).toHaveBeenCalledWith(403); + }); + + it('should give invalid response when keys are configured but supplied key is incorrect', () => { + AppCache.put(fakeReq.body._ApplicationId, { + masterKey: 'masterKey', + restAPIKey: 'restAPIKey' + }); + fakeReq.headers['x-parse-rest-api-key'] = 'wrongKey'; + middlewares.handleParseHeaders(fakeReq, fakeRes); + expect(fakeRes.status).toHaveBeenCalledWith(403); + }); + + it('should give invalid response when keys are configured but different key is supplied', () => { + AppCache.put(fakeReq.body._ApplicationId, { + masterKey: 'masterKey', + restAPIKey: 'restAPIKey' + }); + fakeReq.headers['x-parse-client-key'] = 'clientKey'; + middlewares.handleParseHeaders(fakeReq, fakeRes); + expect(fakeRes.status).toHaveBeenCalledWith(403); + }); + + + it('should succeed when any one of the configured keys supplied', (done) => { + AppCache.put(fakeReq.body._ApplicationId, { + clientKey: 'clientKey', + masterKey: 'masterKey', + restAPIKey: 'restAPIKey' + }); + fakeReq.headers['x-parse-rest-api-key'] = 'restAPIKey'; + middlewares.handleParseHeaders(fakeReq, fakeRes, () => { + expect(fakeRes.status).not.toHaveBeenCalled(); + done(); + }); + }); + + it('should succeed when no keys are configured and none supplied', (done) => { + AppCache.put(fakeReq.body._ApplicationId, { + masterKey: 'masterKey' + }); + middlewares.handleParseHeaders(fakeReq, fakeRes, () => { + expect(fakeRes.status).not.toHaveBeenCalled(); + done(); + }); + }); + const BodyParams = { clientVersion: '_ClientVersion', installationId: '_InstallationId', diff --git a/src/middlewares.js b/src/middlewares.js index ca054c0a..650b20d9 100644 --- a/src/middlewares.js +++ b/src/middlewares.js @@ -120,20 +120,15 @@ export function handleParseHeaders(req, res, next) { // Client keys are not required in parse-server, but if any have been configured in the server, validate them // to preserve original behavior. - let keys = ["clientKey", "javascriptKey", "dotNetKey", "restAPIKey"]; + const keys = ["clientKey", "javascriptKey", "dotNetKey", "restAPIKey"]; + const oneKeyConfigured = keys.some(function(key) { + return req.config[key]; + }); + const oneKeyMatches = keys.some(function(key){ + return req.config[key] && info[key] == req.config[key]; + }); - // We do it with mismatching keys to support no-keys config - var keyMismatch = keys.reduce(function(mismatch, key){ - - // check if set in the config and compare - if (req.config[key] && info[key] !== req.config[key]) { - mismatch++; - } - return mismatch; - }, 0); - - // All keys mismatch - if (keyMismatch == keys.length) { + if (oneKeyConfigured && !oneKeyMatches) { return invalidRequest(req, res); }