From e9749a150cfe8c0548cb78380aba9ab2e4730984 Mon Sep 17 00:00:00 2001 From: Michaƫl Ball Date: Sat, 5 Dec 2015 12:26:19 +0000 Subject: Support api key authentication --- app.db | Bin 3072 -> 4096 bytes common/security.py | 7 +++++++ mach2.py | 48 +++++++++++++++++++++++++++++++++++++++++++----- models/user.py | 10 ++++++++-- 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/app.db b/app.db index 8078901..264137d 100644 Binary files a/app.db and b/app.db differ diff --git a/common/security.py b/common/security.py index af1e8b9..91acb2b 100644 --- a/common/security.py +++ b/common/security.py @@ -1,6 +1,13 @@ +import configparser + from passlib.context import CryptContext +config = configparser.ConfigParser() +config.read("mach2.ini") + +secret_key = config["DEFAULT"]["secret_key"] + pwd_context = CryptContext( schemes=["pbkdf2_sha256", "des_crypt"], default="pbkdf2_sha256", diff --git a/mach2.py b/mach2.py index f609534..fdd86c2 100644 --- a/mach2.py +++ b/mach2.py @@ -24,18 +24,21 @@ DATABASE = "app.db" compress = Compress() app = Flask(__name__) -app.secret_key = """\xfc[\x16\x9d\x0f\x86;;\x9e_\x96\x01\xb7\xeay^\x8b\xa0E\x84 - \x91;\x18\xc2""" app.config.from_object(__name__) config = configparser.ConfigParser() config.read("mach2.ini") +app.config["DEBUG"] = config["DEFAULT"]["debug"] +app.config["SECRET_KEY"] = config["DEFAULT"]["secret_key"] + login_manager = LoginManager() login_manager.login_view = "login" +config = configparser.ConfigParser() +config.read("mach2.ini") -login_manager.init_app(app) -compress.init_app(app) +login_manager = LoginManager() +login_manager.login_view = "login" def get_db(): @@ -62,6 +65,42 @@ def query_db(query, args=(), one=False): return (rv[0] if rv else None) if one else rv +@login_manager.request_loader +def load_user(request): + # first, try to login using the api_key url arg + api_key = request.args.get('api_key', None) + + if not api_key: + # next, try to login using Basic Auth + api_key = request.headers.get('Authorization', None) + + if api_key: + api_key = api_key.replace('Basic ', '', 1) + try: + api_key = base64.b64decode(api_key) + except TypeError: + pass + + if api_key: + user = None + result = query_db("SELECT * FROM user WHERE api_key = ?", + [api_key], one=True) + + if result: + user = User(id=result[0], + username=result[1], + password_hash=result[2], + authenticated=0, + active=result[4], + anonymous=result[5]) + + if user: + return user + + # finally, return None if both methods did not login the user + return None + + @app.route("/") @login_required def index(): @@ -348,7 +387,6 @@ def login(): user = None result = query_db("SELECT * FROM user WHERE username = ?", [request.form["username"]], one=True) - if result: user = User(id=result[0], username=result[1], diff --git a/models/user.py b/models/user.py index f912e43..925df5e 100644 --- a/models/user.py +++ b/models/user.py @@ -1,4 +1,8 @@ -from common.security import pwd_context +import os + +from flask.ext.login import make_secure_token + +from common.security import pwd_context, secret_key class User: @@ -46,7 +50,9 @@ class User: else: hash = pwd_context.encrypt(password) - return hash + api_key = make_secure_token(hash, os.urandom(64), key=secret_key) + + return hash, api_key else: raise ValueError("No user") -- cgit v1.2.3