aboutsummaryrefslogtreecommitdiff
path: root/backend/RemoteCookieAuth.py
diff options
context:
space:
mode:
Diffstat (limited to 'backend/RemoteCookieAuth.py')
-rw-r--r--backend/RemoteCookieAuth.py68
1 files changed, 68 insertions, 0 deletions
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