Merge pull request #1859 from minrk/auth-token

Allow Authenticators to authenticate requests for API tokens
This commit is contained in:
Carol Willing
2018-05-05 01:53:37 +02:00
committed by GitHub
2 changed files with 50 additions and 4 deletions

View File

@@ -214,18 +214,39 @@ class UserTokenListAPIHandler(APIHandler):
'oauth_tokens': oauth_tokens,
}))
@admin_or_self
def post(self, name):
async def post(self, name):
body = self.get_json_body() or {}
if not isinstance(body, dict):
raise web.HTTPError(400, "Body must be a JSON dict or empty")
requester = self.get_current_user()
if requester is None:
# defer to Authenticator for identifying the user
# can be username+password or an upstream auth token
try:
name = await self.authenticator.authenticate(self, body.get('auth'))
except web.HTTPError as e:
# turn any authentication error into 403
raise web.HTTPError(403)
except Exception as e:
# suppress and log error here in case Authenticator
# isn't prepared to handle auth via this data
self.log.error("Error authenticating request for %s: %s",
self.request.uri, e)
raise web.HTTPError(403)
requester = self.find_user(name)
if requester is None:
# couldn't identify requester
raise web.HTTPError(403)
user = self.find_user(name)
if requester is not user and not requester.admin:
raise web.HTTPError(403, "Only admins can request tokens for other users")
if not user:
raise web.HTTPError(404, "No such user: %s" % name)
body = self.get_json_body()
if requester is not user:
kind = 'user' if isinstance(requester, User) else 'service'
note = (body or {}).get('note')
note = body.get('note')
if not note:
note = "Requested via api"
if requester is not user:

View File

@@ -1289,6 +1289,31 @@ def test_token_for_user(app, as_user, for_user, status):
)
assert r.status_code == 404
@mark.gen_test
def test_token_authenticator_noauth(app):
"""Create a token for a user relying on Authenticator.authenticate and no auth header"""
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),