handle auth via redirect with parameter
This commit is contained in:
parent
234bbcea0f
commit
4e61b08330
@ -4,6 +4,7 @@ import tornado.web
|
|||||||
from tornado.web import url
|
from tornado.web import url
|
||||||
|
|
||||||
from atst.handlers.main import MainHandler
|
from atst.handlers.main import MainHandler
|
||||||
|
from atst.handlers.home import Home
|
||||||
from atst.handlers.login import Login
|
from atst.handlers.login import Login
|
||||||
from atst.handlers.workspace import Workspace
|
from atst.handlers.workspace import Workspace
|
||||||
from atst.handlers.request import Request
|
from atst.handlers.request import Request
|
||||||
@ -20,7 +21,7 @@ def make_app(config):
|
|||||||
authnid_client = ApiClient(config["default"]["AUTHNID_BASE_URL"])
|
authnid_client = ApiClient(config["default"]["AUTHNID_BASE_URL"])
|
||||||
|
|
||||||
routes = [
|
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"/login", Login, {"page": "login"}, name="login"),
|
||||||
url(r"/home", MainHandler, {"page": "home"}, name="home"),
|
url(r"/home", MainHandler, {"page": "home"}, name="home"),
|
||||||
url(
|
url(
|
||||||
@ -47,7 +48,7 @@ def make_app(config):
|
|||||||
|
|
||||||
app = tornado.web.Application(
|
app = tornado.web.Application(
|
||||||
routes,
|
routes,
|
||||||
login_url="/login",
|
login_url="/",
|
||||||
template_path = home.child('templates'),
|
template_path = home.child('templates'),
|
||||||
static_path = home.child('static'),
|
static_path = home.child('static'),
|
||||||
cookie_secret=config["default"]["COOKIE_SECRET"],
|
cookie_secret=config["default"]["COOKIE_SECRET"],
|
||||||
|
@ -22,17 +22,9 @@ helpers = {
|
|||||||
|
|
||||||
def authenticated(method):
|
def authenticated(method):
|
||||||
@functools.wraps(method)
|
@functools.wraps(method)
|
||||||
@tornado.gen.coroutine
|
|
||||||
def wrapper(self, *args, **kwargs):
|
def wrapper(self, *args, **kwargs):
|
||||||
if not self.current_user:
|
if not self.current_user:
|
||||||
if self.get_cookie('bearer-token'):
|
if self.request.method in ("GET", "HEAD"):
|
||||||
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"):
|
|
||||||
url = self.get_login_url()
|
url = self.get_login_url()
|
||||||
self.redirect(url)
|
self.redirect(url)
|
||||||
return
|
return
|
||||||
@ -41,17 +33,6 @@ def authenticated(method):
|
|||||||
return method(self, *args, **kwargs)
|
return method(self, *args, **kwargs)
|
||||||
return wrapper
|
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):
|
class BaseHandler(tornado.web.RequestHandler):
|
||||||
|
|
||||||
def get_template_namespace(self):
|
def get_template_namespace(self):
|
||||||
|
10
atst/handlers/home.py
Normal file
10
atst/handlers/home.py
Normal file
@ -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 )
|
@ -1,10 +1,37 @@
|
|||||||
import tornado
|
import tornado
|
||||||
from atst.handler import BaseHandler
|
from atst.handler import BaseHandler
|
||||||
|
|
||||||
|
|
||||||
class Login(BaseHandler):
|
class Login(BaseHandler):
|
||||||
|
|
||||||
def initialize(self, page):
|
def initialize(self, page):
|
||||||
self.page = page
|
self.page = page
|
||||||
|
|
||||||
|
@tornado.gen.coroutine
|
||||||
def get(self):
|
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
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
import tornado.web
|
import tornado.web
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from atst.handler import validate_login_token
|
|
||||||
|
|
||||||
|
|
||||||
class MockApiResponse():
|
class MockApiResponse():
|
||||||
@ -11,27 +10,6 @@ class MockApiResponse():
|
|||||||
self.json = json
|
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
|
@pytest.mark.gen_test
|
||||||
def test_redirects_when_not_logged_in(http_client, base_url):
|
def test_redirects_when_not_logged_in(http_client, base_url):
|
||||||
response = yield http_client.fetch(
|
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.code == 302
|
||||||
assert response.error
|
assert response.error
|
||||||
assert response.headers["Location"] == "/login"
|
assert response.headers["Location"] == "/"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.gen_test
|
@pytest.mark.gen_test
|
||||||
def test_login_with_valid_bearer_token(app, monkeypatch, http_client, base_url):
|
def test_login_with_valid_bearer_token(app, monkeypatch, http_client, base_url):
|
||||||
with ThreadPoolExecutor(max_workers=1) as executor:
|
with ThreadPoolExecutor(max_workers=1) as executor:
|
||||||
monkeypatch.setattr(
|
monkeypatch.setattr(
|
||||||
"atst.handler.validate_login_token",
|
"atst.handlers.login.Login._validate_login_token",
|
||||||
lambda c,t: executor.submit(lambda: True),
|
lambda c,t: executor.submit(lambda: True),
|
||||||
)
|
)
|
||||||
response = yield http_client.fetch(
|
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.headers["Set-Cookie"].startswith("atst")
|
||||||
assert response.code == 200
|
assert response.headers['Location'] == '/home'
|
||||||
assert not response.error
|
assert response.code == 302
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.gen_test
|
@pytest.mark.gen_test
|
||||||
|
Loading…
x
Reference in New Issue
Block a user