summaryrefslogtreecommitdiff
path: root/session_app.py.publish
diff options
context:
space:
mode:
Diffstat (limited to 'session_app.py.publish')
-rwxr-xr-xsession_app.py.publish190
1 files changed, 190 insertions, 0 deletions
diff --git a/session_app.py.publish b/session_app.py.publish
new file mode 100755
index 0000000..915693a
--- /dev/null
+++ b/session_app.py.publish
@@ -0,0 +1,190 @@
+#!/usr/bin/env python
+# Startdate: 2021-06-17
+# goals:
+# accept kerberos or ldap "authorization: basic gowinablz;nuiowekj==" auth, to create a cookie for a session that lasts for 15 minutes. use the cookie to get to protected URLs
+# References:
+# https://code.tutsplus.com/tutorials/flask-authentication-with-ldap--cms-23101
+# https://www.techlifediary.com/python-web-development-tutorial-using-flask-session-cookies/
+# delete cookie https://stackoverflow.com/a/14386413/3569534
+# timeout sessions https://stackoverflow.com/a/11785722/3569534
+# future: https://code.tutsplus.com/tutorials/flask-authentication-with-ldap--cms-23101
+# better timeout session: https://stackoverflow.com/a/49891626/3569534
+# Improve:
+# purge sessions after 15 minutes?
+# Run:
+# FLASK_APP=session_app.py FLASK_DEBUG=1 flask run --host 0.0.0.0
+# Dependencies:
+# apt-get install python3-flask
+# pip3 install Flask-kerberos kerberos
+
+from flask import Flask, Response, redirect, url_for, render_template, request
+
+from flask_kerberos import init_kerberos, requires_authentication, _unauthorized, _forbidden, _gssapi_authenticate
+from flask import _request_ctx_stack as stack, make_response, session
+#from flask.ext.login import LoginManager
+import kerberos
+from functools import wraps
+from socket import gethostname
+import binascii, datetime
+
+from functools import wraps
+import os
+
+DEBUG=True
+app = Flask(__name__)
+app.config.from_object(__name__)
+app.debug=True
+secret_key_value = os.urandom(24)
+secret_key_value_hex_encoded = binascii.hexlify(secret_key_value)
+app.config['SECRET_KEY'] = secret_key_value_hex_encoded
+#app.config['PERMANENT_SESSION_LIFETIME'] = datetime.timedelta(days=7)
+#session.permanent = True
+minutes = 2
+app.permanent_session_lifetime=datetime.timedelta(minutes=minutes)
+
+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)
+ 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 Response(f"session user: {s_user}<br/>cookie user: {c_user}", 200)
+ # return to the passed function, from https://github.com/ArtemAngelchev/flask-basicauth-ldap/blob/master/flask_basicauth_ldap.py
+ return function(*args,**kwargs)
+ # catch-all
+ return Response("requires session",401)
+ return decorated
+
+# imported from flask_kerberos and modified, because I want custom 401 message
+def requires_authn_kerberos(function):
+ '''
+ Require that the wrapped view function only be called by users
+ authenticated with Kerberos. The view function will have the authenticated
+ users principal passed to it as its first argument.
+
+ :param function: flask view function
+ :type function: function
+ :returns: decorated function
+ :rtype: function
+ '''
+ @wraps(function)
+ def decorated(*args, **kwargs):
+ header = request.headers.get("Authorization")
+ if header:
+ ctx = stack.top
+ token = ''.join(header.split()[1:])
+ rc = _gssapi_authenticate(token)
+ if rc == kerberos.AUTH_GSS_COMPLETE:
+ response = function(ctx.kerberos_user, *args, **kwargs)
+ response = make_response(response)
+ if ctx.kerberos_token is not None:
+ response.headers['WWW-Authenticate'] = ' '.join(['negotiate', ctx.kerberos_token])
+ return response
+ elif rc != kerberos.AUTH_GSS_CONTINUE:
+ return _forbidden()
+ return _unauthorized_kerberos()
+ return decorated
+
+def _unauthorized_kerberos():
+ '''
+ Indicate that authentication is required
+ '''
+ # from https://billstclair.com/html-redirect2.html
+ return Response(f'<meta http-equiv="Refresh" content="4; url={url_for("login_ldap")}">Unauthorized! No kerberos auth provided. Trying <a href="{url_for("login_ldap")}">ldap</a> automatically in a moment.', 401, {'WWW-Authenticate': 'Negotiate'})
+
+@app.route("/")
+def index():
+ return render_template('index.html')
+
+@app.route("/open/")
+def open():
+ header = request.headers.get("Authorization")
+ if header:
+ print("Header!")
+ token = ''.join(header.split()[1:])
+ print("token",token)
+ print("something")
+ return "<html><body>here</body></html>", 200
+
+@app.route("/protected/")
+@requires_session
+def protected_page():
+ return protected_page_real()
+
+def protected_page_real():
+ s_user = session['user']
+ c_user = request.cookies.get('user')
+ cookie=request.cookies
+ print(cookie)
+ return render_template('view.html', c_user = c_user, s_user=s_user, cookie=cookie)
+
+@app.route("/login/")
+#@requires_authn_kerberos
+def login(user="None"):
+ # prefer kerberos
+ return redirect(url_for("login_kerberos"))
+
+@app.route("/login/kerberos")
+@requires_authn_kerberos
+def login_kerberos(user):
+ resp = Response(f'<meta http-equiv="Refresh" content="1; url={url_for("protected_page")}">success with kerberos')
+ #resp.headers['login'] = "from-kerberos"
+ resp.set_cookie('user',user)
+ resp.set_cookie('type',"kerberos")
+ end_time = datetime.datetime.now(datetime.timezone.utc) + app.permanent_session_lifetime
+ end_time_str = datetime.datetime.strftime(end_time,"%FT%TZ")
+ resp.set_cookie('timestamp',end_time_str)
+ session.permanent = True
+ session['user']=user
+ session['end_time'] = end_time_str
+ return resp
+
+# WORKHERE: ldap auth
+# WIP 2021-06-18 17:42; make this unauthenticated GET send to a form.
+@app.route("/login/ldap", methods=['POST','GET'])
+#@app.route("/login/ldap/<user>")
+def login_ldap(user = "none"):
+ resp = Response(f"success, from user {user}")
+ resp.headers['login'] = "from-ldap"
+ resp.set_cookie('user',user)
+ resp.set_cookie('type',"ldap")
+ session['user']=user
+ resp.set_cookie('timestamp',app.permanent_session_lifetime)
+ return resp
+
+@app.route("/logout")
+def logout():
+ resp = Response(f"logged out")
+ # Doing anything with session here leaves a cookie.
+ #session['user']=""
+ resp.set_cookie('user','',expires=0)
+ resp.set_cookie('type','',expires=0)
+ resp.set_cookie('session','',expires=0)
+ resp.set_cookie('timestamp','',expires=0)
+ return resp
+
+## This bumps the session lifetime to two minutes farther out from each web request with this session.
+#@app.before_request
+#def make_session_permanent():
+# session.permanent = True
+# session['end_time'] = datetime.datetime.now()+app.permanent_session_lifetime
+
+# keytab from `/usr/sbin/ipa-getkeytab -p HTTP/d2-03a.ipa.example.com -k session.keytab`
+os.environ['KRB5_KTNAME'] = "./session.keytab"
+os.environ['KRB5_TRACE'] = "./kerberos.log"
+init_kerberos(app, hostname="d2-03a.ipa.internal.com", service="HTTP")
+if __name__ == '__main__':
+ init_kerberos(app, hostname="d2-03a.ipa.internal.com", service="HTTP")
+ app.run(host='0.0.0.0',debug=True)
bgstack15