diff --git a/spec/index.spec.js b/spec/index.spec.js index d2c8984d71..31b8c662e2 100644 --- a/spec/index.spec.js +++ b/spec/index.spec.js @@ -12,6 +12,30 @@ describe('server', () => { expect(setServerConfiguration.bind(undefined, { appId: 'myId', masterKey: 'mk' })).toThrow('You must provide a serverURL!'); done(); }); + + it('support http basic authentication with masterkey', done => { + request.get({ + url: 'http://localhost:8378/1/classes/TestObject', + headers: { + 'Authorization': 'Basic ' + new Buffer('test:' + 'test').toString('base64') + } + }, (error, response, body) => { + expect(response.statusCode).toEqual(200); + done(); + }); + }); + + it('support http basic authentication with javascriptKey', done => { + request.get({ + url: 'http://localhost:8378/1/classes/TestObject', + headers: { + 'Authorization': 'Basic ' + new Buffer('test:javascript-key=' + 'test').toString('base64') + } + }, (error, response, body) => { + expect(response.statusCode).toEqual(200); + done(); + }); + }); it('fails if database is unreachable', done => { setServerConfiguration({ diff --git a/src/middlewares.js b/src/middlewares.js index 10115d6853..cce677299d 100644 --- a/src/middlewares.js +++ b/src/middlewares.js @@ -27,6 +27,14 @@ function handleParseHeaders(req, res, next) { dotNetKey: req.get('X-Parse-Windows-Key'), restAPIKey: req.get('X-Parse-REST-API-Key') }; + + var basicAuth = httpAuth(req); + + if (basicAuth) { + info.appId = basicAuth.appId + info.masterKey = basicAuth.masterKey || info.masterKey; + info.javascriptKey = basicAuth.javascriptKey || info.javascriptKey; + } if (req.body) { // Unity SDK sends a _noBody key which needs to be removed. @@ -144,6 +152,45 @@ function handleParseHeaders(req, res, next) { }); } +function httpAuth(req) { + if (!(req.req || req).headers.authorization) + return ; + + var header = (req.req || req).headers.authorization; + var appId, masterKey, javascriptKey; + + // parse header + var authPrefix = 'basic '; + + var match = header.toLowerCase().indexOf(authPrefix); + + if (match == 0) { + var encodedAuth = header.substring(authPrefix.length, header.length); + var credentials = decodeBase64(encodedAuth).split(':'); + + if (credentials.length == 2) { + appId = credentials[0]; + var key = credentials[1]; + + var jsKeyPrefix = 'javascript-key='; + + var matchKey = key.indexOf(jsKeyPrefix) + if (matchKey == 0) { + javascriptKey = key.substring(jsKeyPrefix.length, key.length); + } + else { + masterKey = key; + } + } + } + + return {appId: appId, masterKey: masterKey, javascriptKey: javascriptKey}; +} + +function decodeBase64(str) { + return new Buffer(str, 'base64').toString() +} + var allowCrossDomain = function(req, res, next) { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');