From 527d2855f37bed4fe8ab82a0d0c340258a19adc7 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Tue, 31 Jul 2018 15:46:45 +0300 Subject: Add: actually check user credentials --- qvisqve/api.py | 7 ++++++- qvisqve/auth_router.py | 19 ++++++++++++++++++- yarns/300-end-user-auth.yarn | 4 ++++ yarns/lib.py | 13 ++++++++++++- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/qvisqve/api.py b/qvisqve/api.py index 6c3fe34..dfe69d0 100644 --- a/qvisqve/api.py +++ b/qvisqve/api.py @@ -31,7 +31,7 @@ class API: qvisqve.TokenRouter( self._create_token_generator(), self._get_clients()), qvisqve.LoginRouter(), - qvisqve.AuthRouter(self._get_applications()), + qvisqve.AuthRouter(self._get_applications(), self._get_users()), ] routes = [] @@ -65,3 +65,8 @@ class API: rs = self._create_resource_store() am = qvisqve.ApplicationManager(rs) return am + + def _get_users(self): + rs = self._create_resource_store() + um = qvisqve.UserManager(rs) + return um diff --git a/qvisqve/auth_router.py b/qvisqve/auth_router.py index 717e46f..378a995 100644 --- a/qvisqve/auth_router.py +++ b/qvisqve/auth_router.py @@ -17,14 +17,18 @@ import urllib.parse +import bottle + + import qvisqve class AuthRouter(qvisqve.Router): - def __init__(self, apps): + def __init__(self, apps, users): super().__init__() self._apps = apps + self._users = users def get_routes(self): return [ @@ -44,6 +48,12 @@ class AuthRouter(qvisqve.Router): if content_type != 'application/x-www-form-urlencoded': return qvisqve.bad_request_response('Wrong content type') + params = self._get_form_params(body) + username = self._get_param(params, 'username') + password = self._get_param(params, 'password') + if not self._users.is_valid_secret(username, password): + return qvisqve.unauthorized_response('Access denied') + # TODO: # - perform actual auth # - create and store auth code @@ -59,3 +69,10 @@ class AuthRouter(qvisqve.Router): qvisqve.log.log('xxx', msg_text='Returning redirect', url=url) return qvisqve.found_response('Redirect to callback url', url) + + def _get_param(self, params, name): + return params[name][0] + + def _get_form_params(self, body): + body = body.decode('UTF-8') + return urllib.parse.parse_qs(body) diff --git a/yarns/300-end-user-auth.yarn b/yarns/300-end-user-auth.yarn index f2a74f2..46d6236 100644 --- a/yarns/300-end-user-auth.yarn +++ b/yarns/300-end-user-auth.yarn @@ -25,6 +25,10 @@ User goes to the login URL and gets a login page. AND body has an HTML form with field username AND body has an HTML form with field password + WHEN browser requests POST /auth, with form values + ... username=tomjon and password=wrong + THEN HTTP status code is 401 Unauthorized + WHEN browser requests POST /auth, with form values ... username=tomjon and password=hunter2 THEN HTTP status code is 302 Found diff --git a/yarns/lib.py b/yarns/lib.py index 56707ba..7d83c08 100644 --- a/yarns/lib.py +++ b/yarns/lib.py @@ -181,9 +181,11 @@ def start_qvisqve(): os.mkdir(store) os.mkdir(os.path.join(store, 'client')) os.mkdir(os.path.join(store, 'application')) + os.mkdir(os.path.join(store, 'user')) + + sh = qvisqve_secrets.SecretHasher() if V['client_id'] and V['client_secret']: - sh = qvisqve_secrets.SecretHasher() client = { 'hashed_secret': sh.hash(V['client_secret']), 'allowed_scopes': V['allowed_scopes'], @@ -202,6 +204,15 @@ def start_qvisqve(): with open(filename, 'w') as f: yaml.safe_dump(spec, stream=f) + users = V['users'] + for name in users or []: + filename = os.path.join(store, 'user', name) + spec = { + 'hashed_secret': sh.hash(users[name]), + } + with open(filename, 'w') as f: + yaml.safe_dump(spec, stream=f) + config = { 'gunicorn': 'background', 'gunicorn-log': 'gunicorn.log', -- cgit v1.2.1