From 09feb01bd97c4b3e372750c0f894cd65ee42d86a Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Mon, 6 Aug 2018 15:27:20 +0300 Subject: Fix: authorization code can only be used once --- qvisqve/authz_attempt.py | 6 ++++++ qvisqve/authz_attempt_tests.py | 6 ++++++ qvisqve/token_router.py | 4 +++- yarns/300-end-user-auth.yarn | 7 +++++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/qvisqve/authz_attempt.py b/qvisqve/authz_attempt.py index 229c802..21d9be5 100644 --- a/qvisqve/authz_attempt.py +++ b/qvisqve/authz_attempt.py @@ -107,6 +107,12 @@ class AuthorizationAttempts: self._attempts.append(aa) return aa + def delete_by_id(self, attempt_id): + self._attempts = [ + aa for aa in self._attempts + if aa.get_attempt_id() != attempt_id + ] + def find_by_id(self, attempt_id): for aa in self._attempts: if aa.get_attempt_id() == attempt_id: diff --git a/qvisqve/authz_attempt_tests.py b/qvisqve/authz_attempt_tests.py index d46660d..a9fadb6 100644 --- a/qvisqve/authz_attempt_tests.py +++ b/qvisqve/authz_attempt_tests.py @@ -90,6 +90,12 @@ class AuthorizationAttemptsTests(unittest.TestCase): self.assertEqual(aa.get_state(), self.urlparams['state']) self.assertEqual(aa.get_redirect_uri(), self.urlparams['redirect_uri']) + def test_deletes_attempt(self): + aa = self.aas.create_attempt(self.urlparams) + attempt_id = aa.get_attempt_id() + self.aas.delete_by_id(attempt_id) + self.assertEqual(self.aas.find_by_id(attempt_id), None) + def test_finds_by_id(self): aa = self.aas.create_attempt(self.urlparams) attempt_id = aa.get_attempt_id() diff --git a/qvisqve/token_router.py b/qvisqve/token_router.py index c510b8b..ea37065 100644 --- a/qvisqve/token_router.py +++ b/qvisqve/token_router.py @@ -137,7 +137,7 @@ class AuthorizationCodeGrant(Grant): aa = self._attempts.find_by_code(code) if aa is None: qvisqve.log.log('error', msg_text='Unknown code given', code=code) - return qvisqve.unauthorized_response('Access denied') + return qvisqve.bad_request_response('Bad request') subject_id = aa.get_subject_id() scope = aa.get_scope() @@ -148,6 +148,8 @@ class AuthorizationCodeGrant(Grant): if s in allowed ) + self._attempts.delete_by_id(aa.get_attempt_id()) + empty_token = self._generator.new_token( '', scope, subject_id=subject_id) return qvisqve.ok_response({ diff --git a/yarns/300-end-user-auth.yarn b/yarns/300-end-user-auth.yarn index e69ccad..da79b03 100644 --- a/yarns/300-end-user-auth.yarn +++ b/yarns/300-end-user-auth.yarn @@ -181,4 +181,11 @@ this. Needs research and thinking. AND access token has a scope field set to read AND access token has a sub field set to tomjon +The authorization code can't be re-used. + + WHEN facade requests POST /token, with + ... form values grant_type=authorization_code and code=${CODE} + ... using Basic Auth with username facade, password happydays + THEN HTTP status code is 400 Bad request + FINALLY Qvisqve is stopped -- cgit v1.2.1