From 4e61b08330f25892b76de792728da286c8c3d28a Mon Sep 17 00:00:00 2001 From: dandds Date: Tue, 12 Jun 2018 15:07:45 -0400 Subject: [PATCH] handle auth via redirect with parameter --- atst/app.py | 5 +++-- atst/handler.py | 21 +-------------------- atst/handlers/home.py | 10 ++++++++++ atst/handlers/login.py | 29 ++++++++++++++++++++++++++++- tests/test_auth.py | 34 +++++++--------------------------- 5 files changed, 49 insertions(+), 50 deletions(-) create mode 100644 atst/handlers/home.py diff --git a/atst/app.py b/atst/app.py index 92d188db..0d74ce47 100644 --- a/atst/app.py +++ b/atst/app.py @@ -4,6 +4,7 @@ import tornado.web from tornado.web import url from atst.handlers.main import MainHandler +from atst.handlers.home import Home from atst.handlers.login import Login from atst.handlers.workspace import Workspace from atst.handlers.request import Request @@ -20,7 +21,7 @@ def make_app(config): authnid_client = ApiClient(config["default"]["AUTHNID_BASE_URL"]) routes = [ - url(r"/", Login, {"page": "login"}, name="main"), + url(r"/", Home, {"page": "login"}, name="main"), url(r"/login", Login, {"page": "login"}, name="login"), url(r"/home", MainHandler, {"page": "home"}, name="home"), url( @@ -47,7 +48,7 @@ def make_app(config): app = tornado.web.Application( routes, - login_url="/login", + login_url="/", template_path = home.child('templates'), static_path = home.child('static'), cookie_secret=config["default"]["COOKIE_SECRET"], diff --git a/atst/handler.py b/atst/handler.py index dbd95430..b38be79b 100644 --- a/atst/handler.py +++ b/atst/handler.py @@ -22,17 +22,9 @@ helpers = { def authenticated(method): @functools.wraps(method) - @tornado.gen.coroutine def wrapper(self, *args, **kwargs): if not self.current_user: - if self.get_cookie('bearer-token'): - bearer_token = self.get_cookie('bearer-token') - valid = yield validate_login_token(self.application.authnid_client, bearer_token) - if valid: - self._start_session() - else: - raise NotImplementedError - elif self.request.method in ("GET", "HEAD"): + if self.request.method in ("GET", "HEAD"): url = self.get_login_url() self.redirect(url) return @@ -41,17 +33,6 @@ def authenticated(method): return method(self, *args, **kwargs) return wrapper -@tornado.gen.coroutine -def validate_login_token(client, token): - try: - response = yield client.post('/api/v1/validate', raise_error=False, json={"token": token}) - return response.code == 200 - except tornado.httpclient.HTTPError as error: - if error.response.code == 401: - return False - else: - raise error - class BaseHandler(tornado.web.RequestHandler): def get_template_namespace(self): diff --git a/atst/handlers/home.py b/atst/handlers/home.py new file mode 100644 index 00000000..d600dfaa --- /dev/null +++ b/atst/handlers/home.py @@ -0,0 +1,10 @@ +import tornado +from atst.handler import BaseHandler + +class Home(BaseHandler): + + def initialize(self, page): + self.page = page + + def get(self): + self.render( '%s.html.to' % self.page, page = self.page ) diff --git a/atst/handlers/login.py b/atst/handlers/login.py index b3012288..80c96fdf 100644 --- a/atst/handlers/login.py +++ b/atst/handlers/login.py @@ -1,10 +1,37 @@ import tornado from atst.handler import BaseHandler + class Login(BaseHandler): def initialize(self, page): self.page = page + @tornado.gen.coroutine def get(self): - self.render( '%s.html.to' % self.page, page = self.page ) + token = self.get_query_argument("bearer-token") + if token: + valid = yield self._validate_login_token(token) + if valid: + self._start_session() + self.redirect("/home") + return + + url = self.get_login_url() + self.redirect(url) + return + + @tornado.gen.coroutine + def _validate_login_token(self, token): + try: + response = yield self.application.authnid_client.post( + "/api/v1/validate", json={"token": token} + ) + return response.code == 200 + + except tornado.httpclient.HTTPError as error: + if error.response.code == 401: + return False + + else: + raise error diff --git a/tests/test_auth.py b/tests/test_auth.py index fa636b67..a9c2e5de 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -1,7 +1,6 @@ import pytest import tornado.web from concurrent.futures import ThreadPoolExecutor -from atst.handler import validate_login_token class MockApiResponse(): @@ -11,27 +10,6 @@ class MockApiResponse(): self.json = json -@pytest.mark.gen_test -def test_successful_validate_login_token(monkeypatch, app): - monkeypatch.setattr( - "atst.api_client.ApiClient.get", - lambda x, - y, - json=None: MockApiResponse(200, {"status": "success"}), - ) - assert validate_login_token(app.authnid_client, "abc-123") - - -@pytest.mark.gen_test -def test_unsuccessful_validate_login_token(monkeypatch, app): - monkeypatch.setattr( - "atst.api_client.ApiClient.get", - lambda x,y,json=None: MockApiResponse(401, {"status": "error"}), - ) - valid = yield validate_login_token(app.authnid_client, "abc-123") - assert not valid - - @pytest.mark.gen_test def test_redirects_when_not_logged_in(http_client, base_url): response = yield http_client.fetch( @@ -39,22 +17,24 @@ def test_redirects_when_not_logged_in(http_client, base_url): ) assert response.code == 302 assert response.error - assert response.headers["Location"] == "/login" + assert response.headers["Location"] == "/" @pytest.mark.gen_test def test_login_with_valid_bearer_token(app, monkeypatch, http_client, base_url): with ThreadPoolExecutor(max_workers=1) as executor: monkeypatch.setattr( - "atst.handler.validate_login_token", + "atst.handlers.login.Login._validate_login_token", lambda c,t: executor.submit(lambda: True), ) response = yield http_client.fetch( - base_url + "/home", headers={"Cookie": "bearer-token=anything"} + base_url + "/login?bearer-token=abc-123", + follow_redirects=False, + raise_error=False ) assert response.headers["Set-Cookie"].startswith("atst") - assert response.code == 200 - assert not response.error + assert response.headers['Location'] == '/home' + assert response.code == 302 @pytest.mark.gen_test