diff options
author | B. Stack <bgstack15@gmail.com> | 2021-06-22 22:45:17 -0400 |
---|---|---|
committer | B. Stack <bgstack15@gmail.com> | 2021-06-22 22:45:17 -0400 |
commit | de829904162705b8f782ec9b93632a8e20b6b811 (patch) | |
tree | 5f1e82c67ffc508ba718e1cd028c4a750f34a590 /session_app.py.publish | |
parent | add ldap support (diff) | |
download | session_app-de829904162705b8f782ec9b93632a8e20b6b811.tar.gz session_app-de829904162705b8f782ec9b93632a8e20b6b811.tar.bz2 session_app-de829904162705b8f782ec9b93632a8e20b6b811.zip |
add basic auth, but lacks request for auth
Endpoint /login/basic/ works now with a POST, but a GET
does not make it prompt a browser for username/password
yet.
Diffstat (limited to 'session_app.py.publish')
-rwxr-xr-x | session_app.py.publish | 92 |
1 files changed, 66 insertions, 26 deletions
diff --git a/session_app.py.publish b/session_app.py.publish index 4a806ed..31df674 100755 --- a/session_app.py.publish +++ b/session_app.py.publish @@ -9,11 +9,14 @@ # 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 +# store "formdata" in session for changing the basic auth to form data for the ldap login https://stackoverflow.com/a/56904875/3569534 # Improve: # move all configs to config file # move all references to references section -# accept a /login/basic endpoint with Authorization: header, use ldap +# make /login/basic actually request http auth if user/pw not provided, or is a GET +# try inspecting flask-httpauth auth.login_required section? # accept a bind credential so we can perform lookups of users who match "uid=%s" under a basedn. +# accept a ldap dns domain name, and a SRV lookup for _tcp._ldap # Run: # FLASK_APP=session_app.py FLASK_DEBUG=1 flask run --host 0.0.0.0 # Dependencies: @@ -109,8 +112,22 @@ def requires_authn_ldap(function): ''' @wraps(function) def decorated(*args, **kwargs): - username = request.form['username'] - pw = request.form['password'] + # formdata is in session if we are coming from login_basic() + form = session.get('formdata', None) + if form: + print(f"DEBUG: requires_authn_ldap form={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_ldap() + username = request.form['username'] + pw = request.form['password'] + #print(f"DEBUG: requires_authn_ldap with username={username} and pw={pw}") ll = ldap_login(username,pw) if ll: return function(ll.user,*args, **kwargs) @@ -162,20 +179,12 @@ def login(user="None"): # default, show login form return redirect(url_for("login_form")) elif request.method == "POST": - # redirect to whichever option was chosen in the drop-down - if 'logintype' in request.form: - logintype = request.form['logintype'] - else: - # choose default logintype for user - logintype = "ldap" - if "ldap" == logintype: - # preserve POST with code 307 https://stackoverflow.com/a/15480983/3569534 - return redirect(url_for("login_ldap"), code=307) - else: - return f"Authentication method {logintype} not supported yet.",400 + if request.authorization: + return redirect(url_for("login_basic"),code=307) + return handle_login_ldap_from_non_ldap(request) def ldap_login(username,password): - print(f"Trying user {username} with pw '{password}'") + #print(f"DEBUG: Trying user {username} with pw '{password}'") user = session_ldap.authenticated_user( app.config['LDAP_URI'], app.config['LDAP_USER_FORMAT'], @@ -217,18 +226,34 @@ def login_ldap(user,groups=[]): resp = login_generic(session,resp,user,groups) return resp -@app.route("/login/form", methods=['GET']) -@app.route("/login/form/", methods=['GET']) +@app.route("/login/form", methods=['POST','GET']) +@app.route("/login/form/", methods=['POST','GET']) def login_form(): - options = { - "ldap": "ldap", - "other": "other" - } - return render_template("login_form.html", - login_url = url_for("login"), - options=options, - kerberos_url = url_for("login_kerberos") - ) + if request.method == "GET": + options = { + "ldap": "ldap", + "other": "other" + } + return render_template("login_form.html", + login_url = url_for("login"), + options=options, + kerberos_url = url_for("login_kerberos") + ) + else: + # assume it is a POST + return redirect(url_for("login_ldap"), code=307) + +def handle_login_ldap_from_non_ldap(request): + # set default logintype for user + logintype = "ldap" + # redirect to whichever option was chosen in the drop-down + if 'logintype' in request.form: + logintype = request.form['logintype'] + if "ldap" == logintype: + # preserve POST with code 307 https://stackoverflow.com/a/15480983/3569534 + return redirect(url_for("login_ldap"), code=307) + else: + return f"Authentication method {logintype} not supported yet.",400 @app.route("/logout") @app.route("/logout/") @@ -242,6 +267,21 @@ def logout(): resp.set_cookie('timestamp','',expires=0) return resp +@app.route("/login/basic",methods=['POST']) +@app.route("/login/basic/",methods=['POST']) +def login_basic(): + if not request.authorization: + return Response(f"No username and password provided.",401) + 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("login_ldap"),code=307) + ## This bumps the session lifetime to two minutes farther out from each web request with this session. #@app.before_request #def make_session_permanent(): |