From 507f0d060da30a8f65bec8b2ac1f08837d536b4c Mon Sep 17 00:00:00 2001 From: cbdev Date: Mon, 4 Jul 2022 19:21:34 +0200 Subject: Implement authentication modules for admin panel --- backend/RemoteCookieAuth.py | 68 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 backend/RemoteCookieAuth.py (limited to 'backend/RemoteCookieAuth.py') diff --git a/backend/RemoteCookieAuth.py b/backend/RemoteCookieAuth.py new file mode 100644 index 0000000..4f3ef32 --- /dev/null +++ b/backend/RemoteCookieAuth.py @@ -0,0 +1,68 @@ +import requests +import sqlite3 +import http.cookies as ck +import time + +import config +import utils + +# This authentication provider assumes that a cookie containing a session ID +# has been set by some unspecified means (e.g. a login panel). This session ID +# is verified for authorization by calling a centralized verification endpoint +# which returns any entitlements in JSON. +# Authorized sessions are cached in a table in the local cargohold database +# for a limited time. + +cookie_name = "session" +validator = "https://stumpf.es/auth/cargohold" +session_cache_interval = 60*15 + +db = sqlite3.connect(config.database, check_same_thread = False) + +def login(env, post): + # Check if already using a known session + user = get(env) + if user: + return utils.redirect("/admin") + + # Check if session cookie present + cookies = ck.SimpleCookie(env.get('HTTP_COOKIE', '')) + if cookie_name not in cookies: + return utils.redirect(config.homepage) + + # Check if session ID valid + req = requests.get(validator, headers = {"Cookie": cookie_name + "=" + cookies[cookie_name].value}) + auth = req.json() + + if "entitlement" in auth and auth["entitlement"]["service"] == "cargohold": + # Create the user if not known + utils.ensure_user(auth["user"]) + + # Add to session cache + db.cursor().execute("INSERT INTO sessions (id, user, expire) VALUES (:id, :user, :expire)", {"id": cookies[cookie_name].value, "user": auth["user"], "expire": int(time.time() + min(auth["expire_in"], session_cache_interval))}) + db.commit() + return utils.redirect("/admin") + + return utils.redirect(config.homepage) + +def get(env): + # Check if session cookie present + cookies = ck.SimpleCookie(env.get('HTTP_COOKIE', '')) + if cookie_name not in cookies: + return None + + # Check if session ID is in local cache + data = db.cursor().execute("SELECT user, expire FROM sessions WHERE id = :id", {"id": cookies[cookie_name].value}) + sess = data.fetchone() + if sess and sess[1] > time.time(): + return {"user": sess[0], "expire": sess[1]} + + if sess: + # Prune expired sessions + db.cursor().execute("DELETE FROM sessions WHERE expire < :time", {"time": time.time()}) + db.commit() + return None + +def logout(): + # TODO + return None -- cgit v1.2.3