diff --git a/jupyterhub/apihandlers/users.py b/jupyterhub/apihandlers/users.py index b12320c1..7ec20e57 100644 --- a/jupyterhub/apihandlers/users.py +++ b/jupyterhub/apihandlers/users.py @@ -243,6 +243,9 @@ class UserTokenListAPIHandler(APIHandler): # can be username+password or an upstream auth token try: name = await self.authenticator.authenticate(self, body.get('auth')) + if isinstance(name, dict): + # not a simple string so it has to be a dict + name = name.get('name') except web.HTTPError as e: # turn any authentication error into 403 raise web.HTTPError(403) diff --git a/jupyterhub/tests/test_api.py b/jupyterhub/tests/test_api.py index d4e91cd0..fac3e83f 100644 --- a/jupyterhub/tests/test_api.py +++ b/jupyterhub/tests/test_api.py @@ -1370,6 +1370,33 @@ def test_token_authenticator_noauth(app): assert reply['name'] == name +@mark.gen_test +def test_token_authenticator_dict_noauth(app): + """Create a token for a user relying on Authenticator.authenticate and no auth header""" + app.authenticator.auth_state = { + 'who': 'cares', + } + name = 'user' + data = { + 'auth': { + 'username': name, + 'password': name, + }, + } + r = yield api_request(app, 'users', name, 'tokens', + method='post', + data=json.dumps(data) if data else None, + noauth=True, + ) + assert r.status_code == 200 + reply = r.json() + assert 'token' in reply + r = yield api_request(app, 'authorizations', 'token', reply['token']) + r.raise_for_status() + reply = r.json() + assert reply['name'] == name + + @mark.gen_test @mark.parametrize("as_user, for_user, status", [ ('admin', 'other', 200),