diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2a6f4937ea..b26a4212d9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -65,6 +65,11 @@ Fixed ``GET /v1/rules`` and ``GET /v1/rules/`` API endpoint. (bug fix) #4788 #4807 Contributed by @Nicodemos305 and @jeansfelix +* Fix a bug with authentication API endpoint (``POST /auth/v1/tokens``) returning internal + server error when running under gunicorn and when``auth.api_url`` config option was not set. + (bug fix) #4809 + + Reported by @guzzijones 3.1.0 - June 27, 2019 --------------------- diff --git a/st2auth/st2auth/controllers/v1/auth.py b/st2auth/st2auth/controllers/v1/auth.py index e32266b9d2..3b3073e32b 100644 --- a/st2auth/st2auth/controllers/v1/auth.py +++ b/st2auth/st2auth/controllers/v1/auth.py @@ -22,6 +22,7 @@ from st2common.router import exc from st2common.router import Response from st2common.util import auth as auth_utils +from st2common.util import api as api_utils from st2common import log as logging import st2auth.handlers as handlers @@ -80,7 +81,8 @@ def post(self, request, **kwargs): def process_successful_response(token): resp = Response(json=token, status=http_client.CREATED) - resp.headers['X-API-URL'] = cfg.CONF.auth.api_url + # NOTE: gunicon fails and throws an error if header value is not a string (e.g. if it's None) + resp.headers['X-API-URL'] = api_utils.get_base_public_api_url() return resp diff --git a/st2auth/tests/unit/controllers/v1/test_token.py b/st2auth/tests/unit/controllers/v1/test_token.py index d1a5e46e5e..3a3eb237b1 100644 --- a/st2auth/tests/unit/controllers/v1/test_token.py +++ b/st2auth/tests/unit/controllers/v1/test_token.py @@ -87,6 +87,7 @@ def _test_token_post(self, path=TOKEN_V1_PATH): actual_expiry = isotime.parse(response.json['expiry']) self.assertLess(timestamp, actual_expiry) self.assertLess(actual_expiry, expected_expiry) + return response def test_token_post_unauthorized(self): response = self.app.post_json(TOKEN_V1_PATH, {}, expect_errors=True, extra_environ={ @@ -109,6 +110,22 @@ def test_token_post_new_user(self): def test_token_post_existing_user(self): self._test_token_post() + @mock.patch.object( + User, 'get_by_name', + mock.MagicMock(return_value=UserDB(name=USERNAME))) + def test_token_post_success_x_api_url_header_value(self): + # auth.api_url option is explicitly set + cfg.CONF.set_override('api_url', override='https://example.com', group='auth') + + resp = self._test_token_post() + self.assertEqual(resp.headers['X-API-URL'], 'https://example.com') + + # auth.api_url option is not set, url is inferred from listen host and port + cfg.CONF.set_override('api_url', override=None, group='auth') + + resp = self._test_token_post() + self.assertEqual(resp.headers['X-API-URL'], 'http://127.0.0.1:9101') + @mock.patch.object( User, 'get_by_name', mock.MagicMock(return_value=UserDB(name=USERNAME)))