aboutsummaryrefslogtreecommitdiff
path: root/stackbin_auth.py
diff options
context:
space:
mode:
Diffstat (limited to 'stackbin_auth.py')
-rw-r--r--stackbin_auth.py136
1 files changed, 136 insertions, 0 deletions
diff --git a/stackbin_auth.py b/stackbin_auth.py
new file mode 100644
index 0000000..5c12311
--- /dev/null
+++ b/stackbin_auth.py
@@ -0,0 +1,136 @@
+from functools import wraps
+from flask import Blueprint, Flask, Response, request, url_for, redirect, g, render_template, session, abort, current_app
+auth = Blueprint('auth', __name__)
+
+def requires_session(function):
+ '''
+ Requires a valid session, provided by cookie!
+ '''
+ @wraps(function)
+ def decorated(*args, **kwargs):
+ if not session:
+ #return Response("requires session",401)
+ return redirect(url_for('auth.login'))
+ else:
+ if 'user' not in session:
+ return Response("User is not in this session.",401)
+ s_user = session['user']
+ c_user = request.cookies.get('user')
+ print(f"session user: {s_user}")
+ print(f"cookie user: {c_user}")
+ if session['user'] != c_user:
+ return Response("Wrong user for this session!.",401)
+ # otherwise, everything is good!
+ return function(s_user, [], *args,**kwargs)
+ # catch-all
+ #return Response("requires session",401)
+ return redirect(url_for('auth.login'))
+ return decorated
+
+def _requires_admin_credential(function):
+ """
+ Requires the user pass the correct admin credential configured
+ in the conf file.
+ """
+ @wraps(function)
+ def decorated(*args, **kwargs):
+ # formdata is in session if we are coming from login_basic()
+ form = session.get('formdata', None)
+ if form:
+ session.pop('formdata')
+ if 'username' in form:
+ username = form['username']
+ if 'password' in form:
+ pw = form['password']
+ else:
+ # then we are coming from the form with POST data
+ if 'username' not in request.form or 'password' not in request.form:
+ return _unauthorized_admin()
+ username = request.form['username']
+ pw = request.form['password']
+ if 'ADMIN_USERNAME' in current_app.config and \
+ 'ADMIN_PASSWORD' in current_app.config and \
+ username == current_app.config['ADMIN_USERNAME'] and pw == current_app.config['ADMIN_PASSWORD']:
+ return function(username, [], *args, **kwargs)
+ else:
+ return _unauthorized_admin()
+ return decorated
+
+def _unauthorized_admin():
+ return Response(f'<meta http-equiv="Refresh" content="4; url={url_for("auth.login")}">Unauthorized! Invalid admin credential... returning to login form', 401)
+
+@auth.route("/logout")
+@auth.route("/logout/")
+def logout():
+ resp = Response(f'<meta http-equiv="Refresh" content="1; url={url_for("new_paste")}">logged out')
+ # not documented but is found on the Internet in a few random places:
+ session.clear()
+ #resp.set_cookie('user','',expires=0)
+ return resp
+
+@auth.route("/login/new")
+@auth.route("/login/new/")
+def login_new():
+ return redirect(url_for("auth.login", new=""))
+@auth.route("/login/", methods=['POST','GET'])
+def login(user="None"):
+ if request.method == "GET":
+ if 'user' in session and request.cookies.get('user') == session['user'] and (not 'new' in request.args):
+ return redirect(url_for("admin"))
+ auth_header = request.headers.get("Authorization")
+ # default, show login form
+ return redirect(url_for("auth.login_form"))
+ elif request.method == "POST":
+ if request.authorization:
+ return redirect(url_for("auth.login_basic"),code=307)
+ return redirect(url_for("auth.login_generic"))
+ #return f"Authentication method not supported yet.",400
+
+@auth.route("/login/basic",methods=['POST','GET'])
+@auth.route("/login/basic/",methods=['POST','GET'])
+def login_basic():
+ if not request.authorization:
+ return Response(f"Please provide username and password.",401,{'WWW-Authenticate': 'Basic'})
+ if 'username' not in request.authorization:
+ return Response(f"No username provided.",401)
+ if 'password' not in request.authorization:
+ return Response(f"No password provided.",401)
+ username = request.authorization.username
+ pw = request.authorization.password
+ form={'username':username,'password':pw}
+ session['formdata'] = form
+ return redirect(url_for("auth.login_generic"),code=307)
+
+@auth.route("/login/form", methods=['POST','GET'])
+@auth.route("/login/form/", methods=['POST','GET'])
+def login_form():
+ if request.method == "GET":
+ return render_template("login_form.html",
+ login_url = url_for("auth.login_form")
+ )
+ else:
+ # assume it is a POST
+ username=""
+ if 'username' in request.form:
+ username = request.form['username']
+ password=""
+ if 'password' in request.form:
+ password = request.form['password']
+ form={'username':username,'password':password}
+ session['formdata'] = form
+ return redirect(url_for("auth.login_generic"), code=307)
+
+@auth.route("/login/generic", methods=['POST','GET'])
+@auth.route("/login/generic/", methods=['POST','GET'])
+@_requires_admin_credential
+def login_generic(user,groups=[]):
+ resp = Response(f'<meta http-equiv="Refresh" content="1; url={url_for("admin")}">success')
+ session['user_id'] = "admin"
+ resp = login_success(session,resp,user,groups)
+ return resp
+
+def login_success(session,resp,user,groups=[]):
+ resp.set_cookie('user',user)
+ session.permanent = True
+ session['user']=user
+ return resp
bgstack15