diff --git a/jupyterhub/handlers/login.py b/jupyterhub/handlers/login.py index ec174527..b8e7b558 100644 --- a/jupyterhub/handlers/login.py +++ b/jupyterhub/handlers/login.py @@ -78,7 +78,7 @@ class LoginHandler(BaseHandler): # parse the arguments dict data = {} for arg in self.request.arguments: - data[arg] = self.get_argument(arg) + data[arg] = self.get_argument(arg, strip=False) auth_timer = self.statsd.timer('login.authenticate').start() username = yield self.authenticate(data) diff --git a/jupyterhub/tests/test_pages.py b/jupyterhub/tests/test_pages.py index f273e5d9..0f0d3b3c 100644 --- a/jupyterhub/tests/test_pages.py +++ b/jupyterhub/tests/test_pages.py @@ -3,6 +3,7 @@ from urllib.parse import urlencode, urlparse import requests +from tornado import gen from ..handlers import BaseHandler from ..utils import url_path_join as ujoin @@ -231,6 +232,27 @@ def test_login_fail(app): assert not r.cookies +def test_login_strip(app): + """Test that login form doesn't strip whitespace from passwords""" + form_data = { + 'username': 'spiff', + 'password': ' space man ', + } + base_url = public_url(app) + called_with = [] + @gen.coroutine + def mock_authenticate(handler, data): + called_with.append(data) + + with mock.patch.object(app.authenticator, 'authenticate', mock_authenticate): + r = requests.post(base_url + 'hub/login', + data=form_data, + allow_redirects=False, + ) + + assert called_with == [form_data] + + def test_login_redirect(app, io_loop): cookies = app.login_user('river') user = app.users['river']