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
This commit is contained in:
Steven Shipton
2016-10-26 21:44:39 +01:00
committed by Florent Vilmart
parent 278027a955
commit e788d49af0
2 changed files with 62 additions and 13 deletions

View File

@@ -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',

View File

@@ -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);
}