add buckler protection

This commit is contained in:
iou1name 2019-09-25 19:48:19 -04:00
parent 09823d4ebe
commit 265617ee6f
4 changed files with 121 additions and 0 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ __pycache__/
*.swo
*.json
*.db
config.py

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

10
config.py.template Executable file
View File

@ -0,0 +1,10 @@
#!/usr/bin/env python3
"""
Configuration settings for Musik.
`buckler` specifies settings pertaining to the Buckler server.
"""
buckler = {
'url': "http://127.0.0.1:5400/buckler",
'app_id': 1,
'app_key': """password""",
}

View File

@ -11,6 +11,7 @@ from urllib import parse
from flask import Flask, Response, render_template, send_file, url_for, request, abort
import database
import buckler_flask
FFMPEG_CMD = [
'ffmpeg', '-y',
@ -23,6 +24,8 @@ FFMPEG_CMD = [
app = Flask(__name__)
app.session_interface = buckler_flask.BucklerSessionInterface()
app.before_request(buckler_flask.require_auth)
database.init_database()
@app.route('/')