flask-simpleldap icon indicating copy to clipboard operation
flask-simpleldap copied to clipboard

AttributeError: 'list' object has no attribute 'items' when calling ldap.bind_user(user, passwd)

Open zeent opened this issue 5 years ago • 2 comments

Here's my code which I've copy/pasted from your sample:

`import ldap as l from flask import Flask, g, request, session, redirect, url_for from flask_simpleldap import LDAP

app = Flask(name) app.secret_key = 'dev key' app.debug = True

app.config['LDAP_HOST'] = 'MY AD SERVER' app.config['LDAP_PORT'] = '389' app.config['LDAP_BASE_DN'] = 'Base DN' app.config['LDAP_USERNAME'] = 'Username' app.config['LDAP_PASSWORD'] = 'Password' app.config['LDAP_CUSTOM_OPTIONS'] = {l.OPT_REFERRALS: 0} ldap = LDAP(app)

@app.before_request def before_request(): g.user = None if 'user_id' in session: # This is where you'd query your database to get the user info. g.user = {} # Create a global with the LDAP groups the user is a member of. g.ldap_groups = ldap.get_user_groups(user=session['user_id'])

@app.route('/') @ldap.login_required def index(): return 'Successfully logged in!'

@app.route('/login', methods=['GET', 'POST']) def login(): if g.user: return redirect(url_for('index')) if request.method == 'POST': user = request.form['user'] print(user) passwd = request.form['passwd'] print(passwd) test = ldap.bind_user(user, passwd) print(test) if test is None or passwd == '': return 'Invalid credentials' else: session['user_id'] = request.form['user'] return redirect('/') return """

user:
password:
"""

@app.route('/group') @ldap.group_required(groups=['Web Developers', 'QA']) def group(): return 'Group restricted page'

@app.route('/logout') def logout(): session.pop('user_id', None) return redirect(url_for('index'))

if name == 'main': app.run()`

If I change any of :

app.config['LDAP_HOST'] = 'MY AD SERVER' app.config['LDAP_PORT'] = '389' app.config['LDAP_BASE_DN'] = 'Base DN' app.config['LDAP_USERNAME'] = 'Username' app.config['LDAP_PASSWORD'] = 'Password' app.config['LDAP_CUSTOM_OPTIONS'] = {l.OPT_REFERRALS: 0} ldap = LDAP(app)

it fails with connection error and related messages. My AD is registering correct connection from Username from my IP @.

Any tip?

zeent avatar Dec 22 '19 17:12 zeent

Did you find a solution to this yet? I get the same error message

[2020-05-19 14:03:45,891] ERROR in app: Exception on /ldap [GET] Traceback (most recent call last): File "/home///lib64/python3.6/site-packages/flask/app.py", line 2447, in wsgi_app response = self.full_dispatch_request() File "/home///lib64/python3.6/site-packages/flask/app.py", line 1952, in full_dispatch_request rv = self.handle_user_exception(e) File "/home///lib64/python3.6/site-packages/flask_restful/init.py", line 272, in error_router return original_handler(e) File "/home///lib64/python3.6/site-packages/flask/app.py", line 1821, in handle_user_exception reraise(exc_type, exc_value, tb) File "/home///lib64/python3.6/site-packages/flask/_compat.py", line 39, in reraise raise value File "/home///lib64/python3.6/site-packages/flask/app.py", line 1950, in full_dispatch_request rv = self.dispatch_request() File "/home///lib64/python3.6/site-packages/flask/app.py", line 1936, in dispatch_request return self.view_functionsrule.endpoint File "/home///lib64/python3.6/site-packages/flask_simpleldap/init.py", line 372, in wrapped if not self.bind_user(req_username, req_password): File "/home///lib64/python3.6/site-packages/flask_simpleldap/init.py", line 144, in bind_user user_dn = self.get_object_details(user=username, dn_only=True) File "/home///lib64/python3.6/site-packages/flask_simpleldap/init.py", line 198, in get_object_details for k, v in list(records[0][1].items()): AttributeError: 'list' object has no attribute 'items'

ckieser avatar May 19 '20 12:05 ckieser

I encounter this issue as well on the latest version if I attempt to login with a non-existent username. The issue is that a LDAP search will respond with a result and then some references that could be searched if you chased referrals (which is apparently a very broken concept). The search result would be in the format a dn string and then a dictionary containing the proper information about the user, but when the search is empty you just end up with the search references as shown below, and obviously the second item in each tuple is not a dict:

[(None, ['ldap://ForestDnsZones.mycompany.com/DC=ForestDnsZones,DC=mycompany,DC=com']), (None, ['ldap://DomainDnsZones.mycompany.com/DC=DomainDnsZones,DC=mycompany,DC=com']), (None, ['ldap://mycompany.com/CN=Configuration,DC=mycompany,DC=com'])]

A successful search looks like this: [('CN=My Name,OU=Users,OU=Accounts,DC=mycompany,DC=com', {'accountExpires': [b'9223372036854775807'], 'cn': [b'First Last'], 'userPrincipalName': [b'[email protected]'], 'whenChanged': [b'20210119003635.0Z'], 'whenCreated': [b'20201005164610.0Z']}), (None, ['ldap://ForestDnsZones.mycompany.com/DC=ForestDnsZones,DC=mycompany,DC=com']), (None, ['ldap://DomainDnsZones.mycompany.com/DC=DomainDnsZones,DC=mycompany,DC=com']), (None, ['ldap://mycompany.com/CN=Configuration,DC=mycompany,DC=com'])]

fredthomsen avatar Jan 23 '21 06:01 fredthomsen