moved security to buckler

This commit is contained in:
iou1name 2019-09-25 19:57:54 -04:00
parent 921163f454
commit 10aa341bff
3 changed files with 119 additions and 8 deletions

107
buckler_flask.py Normal file
View File

@ -0,0 +1,107 @@
#!/usr/bin/env python3
"""
Session interface middlewares to integrate the flask app with Buckler.
"""
import json
import urllib.parse
import urllib.request
from datetime import datetime
from flask.sessions import SessionInterface, SessionMixin
from flask import session, redirect, request
import config
class BucklerSessionInterface(SessionInterface):
"""
Queries the Buckler server for session data to the current user and
application.
"""
def __init__(self):
self.url = config.buckler['url']
self.app_id = config.buckler['app_id']
self.app_key = config.buckler['app_key']
def open_session(self, app, request):
"""Called when a request is initiated."""
user_id = request.cookies.get('userid')
user_sid = request.cookies.get('session')
params = {
'app_id': self.app_id,
'app_key': self.app_key,
'userid': user_id,
'session': user_sid
}
params = urllib.parse.urlencode(params)
req = urllib.request.Request(self.url + f"/get_session?{params}")
res = urllib.request.urlopen(req)
data = json.loads(res.read())
if data.get('error'):
return None
session = BucklerSession()
session.update(data['session_data'])
session.meta = data['meta']
session.cookies = request.cookies
return session
def save_session(self, app, session, response):
"""Called at the end of a request."""
if not session.modified:
return
user_id = session.meta.get('user_id')
user_sid = session.meta.get('user_sid')
params = {
'app_id': self.app_id,
'app_key': self.app_key,
'userid': user_id,
'session': user_sid
}
params = urllib.parse.urlencode(params)
data = json.dumps(session)
req = urllib.request.Request(
self.url + f"/set_session?{params}",
data=data.encode('utf8'),
method='POST')
res = urllib.request.urlopen(req)
last_used = datetime.fromisoformat(session.meta['last_used'])
now = datetime.now(last_used.tzinfo)
delta = now - last_used
if delta.seconds > 600:
response.set_cookie(
'userid',
session.cookies['userid'],
max_age=30*24*60*60,
secure=True,
httponly=True)
response.set_cookie(
'session',
session.cookies['session'],
max_age=30*24*60*60,
secure=True,
httponly=True)
class BucklerSession(dict, SessionMixin):
"""A server side session class based on the Buckler security shield."""
def __init__(self):
super().__init__()
self.modified = False
def __setitem__(self, key, value):
super().__setitem__(key, value)
self.modified = True
def require_auth():
"""
Requires the user to be properly authenticated with Buckler before
accessing any views on the application.
"""
if not hasattr(session, 'meta'):
resp = redirect(config.buckler['login_url'])
resp.set_cookie('redirect', request.url)
return resp

View File

@ -4,6 +4,13 @@ Configuration settings for the Juice IOT hub server.
`url_prefix` is the root path you wish app to reside at
eg. https://example.com/juice.
`registration_open` whether or not new accounts may be registered.
`buckler` specifies settings pertaining to the Buckler server.
"""
url_prefix = '/juice'
registration_open = True
buckler = {
'url': "http://127.0.0.1:5400/buckler",
'app_id': 2,
'app_key': """lol""",
'login_url': "/buckler/login",
}

View File

@ -15,11 +15,11 @@ import config
import models
from auth import auth_required
from tools import make_error
import buckler_flask
app_views = Blueprint('app_views', __name__)
@app_views.route('/')
@auth_required
def index():
"""
The index page.
@ -35,7 +35,6 @@ def index():
@app_views.route('/toggle')
@auth_required
def toggle():
"""
Toggles the state of a RelayDevice.
@ -56,7 +55,6 @@ def toggle():
return res
@app_views.route('/edit')
@auth_required
def edit():
"""
Edits the text of a particular field.
@ -102,7 +100,6 @@ def edit():
@app_views.route('/new_device')
@auth_required
def new_device():
"""
Allows adding a new device. Accepts device_type parameter, returns
@ -112,7 +109,7 @@ def new_device():
device_type = request.args.get('device_type')
if device_type == 'RelayDevice':
device = RelayDevice()
device = models.RelayDevice()
else:
return make_error(400, "Unknown device type")
@ -134,7 +131,6 @@ def new_device():
@app_views.route('/lock_device')
@auth_required
def lock_device():
"""
Locks or unlocks a device to prevent or allow editing it's fields.
@ -159,7 +155,6 @@ def lock_device():
@app_views.route('/delete')
@auth_required
def delete():
"""
Deletes a device.
@ -180,8 +175,10 @@ def delete():
app = Flask(__name__)
app.session_interface = buckler_flask.BucklerSessionInterface()
app.before_request(buckler_flask.require_auth)
app.register_blueprint(app_views, url_prefix=config.url_prefix)
app.register_blueprint(auth.auth_views, url_prefix=config.url_prefix)
#app.register_blueprint(auth.auth_views, url_prefix=config.url_prefix)
app.jinja_env.undefined = "StrictUndefined"
if os.path.isfile('secret_key'):
with open('secret_key', 'rb') as file: