From 8c506094917fbf135b87eb1fcab9a01c7ad47df8 Mon Sep 17 00:00:00 2001 From: Sebastian Gierlinger Date: Mon, 23 Nov 2015 18:21:19 +0100 Subject: [PATCH] Handling Origin Header closes #6106 - added better error message for client and console - added exclusion of localhost/127.0.0.1 for dev mode --- core/server/middleware/auth.js | 27 +++++++---- .../unit/middleware/authentication_spec.js | 48 +++++++++++++++++++ 2 files changed, 67 insertions(+), 8 deletions(-) diff --git a/core/server/middleware/auth.js b/core/server/middleware/auth.js index 43837f1762..ea746b90c2 100644 --- a/core/server/middleware/auth.js +++ b/core/server/middleware/auth.js @@ -1,9 +1,10 @@ -var _ = require('lodash'), - passport = require('passport'), - url = require('url'), - errors = require('../errors'), - config = require('../config'), - labs = require('../utils/labs'), +var _ = require('lodash'), + passport = require('passport'), + url = require('url'), + errors = require('../errors'), + config = require('../config'), + labs = require('../utils/labs'), + isDevelopment, oauthServer, auth; @@ -36,10 +37,14 @@ function isBearerAutorizationHeader(req) { } function isValidOrigin(origin, client) { + isDevelopment = process.env.NODE_ENV === 'development'; + if (origin && client && client.type === 'ua' && ( _.some(client.trustedDomains, {trusted_domain: origin}) || origin === url.parse(config.url).hostname || origin === url.parse(config.urlSSL ? config.urlSSL : '').hostname + || (origin === '127.0.0.1' && isDevelopment) + || (origin === 'localhost' && isDevelopment) )) { return true; } else { @@ -70,7 +75,8 @@ auth = { return passport.authenticate(['oauth2-client-password'], {session: false, failWithError: false}, function authenticate(err, client) { - var origin = null; + var origin = null, + error; if (err) { return next(err); // will generate a 500 error } @@ -94,7 +100,12 @@ auth = { req.client = client; return next(null, client); } else { - return errors.handleAPIError(new errors.UnauthorizedError('Access denied.'), req, res, next); + error = new errors.UnauthorizedError('Access Denied from url: ' + origin + '. Please use the url configured in config.js.'); + errors.logError(error, + 'You have attempted to access your Ghost admin panel from a url that does not appear in config.js.', + 'For information on how to fix this, please visit http://support.ghost.org/config/#url.' + ); + return errors.handleAPIError(error, req, res, next); } } )(req, res, next); diff --git a/core/test/unit/middleware/authentication_spec.js b/core/test/unit/middleware/authentication_spec.js index 136fbcb7f6..bfaf99856c 100644 --- a/core/test/unit/middleware/authentication_spec.js +++ b/core/test/unit/middleware/authentication_spec.js @@ -406,6 +406,54 @@ describe('Auth', function () { done(); }); + it('should authenticate client with origin `localhost` while in development', function (done) { + var resetEnvironment = auth.__set__('process.env.NODE_ENV', 'development'); + req.body = {}; + req.body.client_id = testClient; + req.body.client_secret = testSecret; + req.headers = {}; + req.headers.origin = 'http://localhost'; + + res.header = {}; + + sandbox.stub(res, 'header', function (key, value) { + key.should.equal('Access-Control-Allow-Origin'); + value.should.equal('http://localhost'); + }); + + registerSuccessfulClientPasswordStrategy(); + auth.authenticateClient(req, res, next); + + next.called.should.be.true; + next.calledWith(null, client).should.be.true; + resetEnvironment(); + done(); + }); + + it('shouldn\'t authenticate client with origin `localhost` by default', function (done) { + req.body = {}; + req.body.client_id = testClient; + req.body.client_secret = testSecret; + req.headers = {}; + req.headers.origin = 'http://localhost'; + + res.status = {}; + + sandbox.stub(res, 'status', function (statusCode) { + statusCode.should.eql(401); + return { + json: function (err) { + err.errors[0].errorType.should.eql('UnauthorizedError'); + } + }; + }); + + registerSuccessfulClientPasswordStrategy(); + auth.authenticateClient(req, res, next); + next.called.should.be.false; + done(); + }); + it('should authenticate client with id in query', function (done) { req.body = {}; req.query = {};