Ldap-module fails when intregrating with Flask
Ldap-module fails when intregrating with Flask
I'm very new to Flask and coding in general so hopefully someone of you guys & girls can give me some more clarification on what's actually going wrong here.
I'm trying to do a very simple (and unsecure) LDAP-authentication towards an internal server, but for some reason I can't for the life of me figure out why it works when running as a standalone script but breaks when integrated in Flask.
My code looks like this:
main.py
from flask import Flask, render_template, request, redirect, session
app = Flask(__name__)
app.config.from_object('config.BaseConfig')
import auth
@app.route('/login', methods=['GET', 'POST'])
def login_page():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
results = auth.authenticate(username,password)
if results == 'OK':
session['username'] = username
session['logged_in'] = True
return redirect(url_for('home_page'))
else:
error = 'Invalid Credentials. Please try again.'
return render_template('login.html', error=error)
return render_template('login.html')
And my LDAP-Authentication is handeld in auth.py:
auth.py
import ldap
def authenticate(username, password):
LDAP_SERVER = 'ldap://ldap.server'
LDAP_USERNAME = 'LDAP%s' % username
LDAP_PASSWORD = password
try:
ldap_client = ldap.initialize(LDAP_SERVER)
ldap_client.set_option(ldap.OPT_REFERRALS,0)
ldap_client.simple_bind_s(LDAP_USERNAME, LDAP_PASSWORD)
except:
ldap_client.unbind()
return 'PASSWORD_ERROR'
ldap_client.unbind()
return 'OK'
The error I get when trying to run this program is:
[Mon Jul 02 19:49:35.018001 2018] [wsgi:error] [pid 20574] [client 10.79.0.38:63620] File "/var/www/html/website/auth.py", line 11, in authenticate, referer: http://.../login
[Mon Jul 02 19:49:35.018010 2018] [wsgi:error] [pid 20574] [client 10.79.0.38:63620] ldap_client = ldap.initialize(LDAP_SERVER), referer: http://.../login
[Mon Jul 02 19:49:35.018029 2018] [wsgi:error] [pid 20574] [client 10.79.0.38:63620] AttributeError: 'module' object has no attribute 'initialize', referer: http://.../login
[Mon Jul 02 19:49:35.019141 2018] [wsgi:error] [pid 20574] [client 10.79.0.38:63620] ldap_client.unbind(), referer: http://.../login
[Mon Jul 02 19:49:35.019155 2018] [wsgi:error] [pid 20574] [client 10.79.0.38:63620] UnboundLocalError: local variable 'ldap_client' referenced before assignment, referer: http://.../login
But it does however work just fine when running it as a standalone script in the virtual enviroment.
import auth
results = auth.authenticate('someuser','somepassword')
if results == 'OK':
print("Success!")
else:
print(results)
Running the above script works everytime.
(flaskenv) [webserver website]$ python test.py
Success!
I'm completely lost on what is causing this and hope I can get some guidance. I've spent the entire day googling for a possible solution but it feels like ive hit a brick wall here. Thanks for taking the time reading.
Edit:
A possible solution was that the production server was running another version of python-ldap than the venv, but this seems not to be the case.
My testing enviroment and production is on the same server and is set up to use the virtual enviroment.
(flaskenv) [webserver website]$ pip freeze | grep ldap
python-ldap==3.1.0
WSGIPythonHome "/var/www/html/website/flaskenv/"
WSGIPythonPath "/var/www/html/website/flaskenv/lib/python3.4/site-packages"
I did however try to install the latest version outside my virtual enviroment but the problem remains the same.
[webserver ~]$ pip3 freeze
python-ldap==3.1.0
Some more searching confirms that the issue must be with the integrating the ldap module, using dir(ldap) in the virtualenviroment gives the correct output with "initialize" etc. This is however the input I get when doing the same in the flask-app:
@app.route('/form')
def form_page():
debug = dir(ldap)
return str(debug)
['__doc__', '__loader__', '__name__', '__package__', '__path__', '__spec__']
2 Answers
2
The problem is in the version of the python-ldap
package. The initialize
function was added in the latest versions, before version 3.0 you had to use a combination of the open
and init
functions.
python-ldap
initialize
open
init
Your testing environment has the latest version, and the code works correct. But your production web environment has the old version that can't find the initialize
function, and that is why you get the error.
initialize
I finally found what was causing the issue, nosklo was close. The Flask-app and the virtualenviroment differed, but not due to installed version - but due to access rights!
As the flask-app is handled by the user apache and the python-ldap package was installed with my own user in the virtual enviroment apache didn't have access to reading the package correctly. After adjusting accessrights it finally works.
sudo chown -R apache:apache dir/
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Thank you! It dosen't however seem to be the case from what I can tell, I updated my post showing a bit more in detail. The production web is/should be running in the same enviroment that i'm testing in.
– smoegendev
Jul 3 at 2:10