0

I am trying to find a way to retrieve information such as 'mail', 'displayName', 'telephoneNumber' from an LDAP authenticated/logged in user in Flask.

My user can successfully authenticate and log in using LDAP. However how would I be able to get additional information about the user?

I am using standard python-ldap and flask-login modules and I'm trying to create a string variable for these attributes so I can call on them later in the session. When trying to run the query I am getting ldap.FILTER_ERROR: {'desc': u'Bad search filter'} . Any ideas on how to get this working?

class UserInfo():
    def whoami(username, password):
        conn = get_ldap_connection()
        conn.simple_bind_s(username,password)
        basedn = 'OU=...,OU=...,DC=...,DC=...'
        userfilter = "(|(SamAccountName=\*" + username + "\*)"
        userattribute = ['displayName']
        userresults = conn.search_s(basedn,ldap.SCOPE_SUBTREE,userfilter, userattribute)

userinfos = UserInfo()

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(100))

    def __init__(self, username, password):
        self.username = username

    @staticmethod
    def try_login(username, password):
        conn = get_ldap_connection()
        conn.simple_bind_s(domain+username, password)

    def is_authenticated(self):
        return True

    def is_active(self):
        return True

    def is_anonymous(self):
        return False

    def get_id(self):
        return unicode(self.id)

@login_manager.user_loader
def load_user(id):
    return User.query.get(int(id))

@app.before_request
def get_current_user():
    g.user = current_user
Infinity8
  • 615
  • 2
  • 9
  • 24
  • Once the LDAP login is complete you need use the Flask Login [`login_user`](https://github.com/maxcountryman/flask-login/blob/master/flask_login/utils.py#L116-L150) util to pass a `User` object with the details of the user. Checkout the [login example](http://flask-login.readthedocs.io/en/latest/#login-example) to learn how to do it. –  Nov 03 '16 at 17:35
  • Thanks, I do have login_user setup though. It passes the username right now, I'm trying to find a way to pass other attributes from LDAP. – Infinity8 Nov 03 '16 at 17:47
  • So you are trying to say you are facing an error near `conn.search_s` ? –  Nov 03 '16 at 17:52
  • yes essentially the search needs to search for the currently logged in user and get information from there. Right now no search works except if I use userfilter = '(objectclass=person)' but this gives me the results of the entire LDAP. – Infinity8 Nov 03 '16 at 18:18
  • Can you refer us to the LDAP package that you are using? –  Nov 03 '16 at 18:19
  • import ldap, aka python-ldap – Infinity8 Nov 03 '16 at 18:21
  • So, this one? https://github.com/pyldap/pyldap –  Nov 03 '16 at 18:23
  • From [this article](https://confluence.atlassian.com/kb/how-to-write-ldap-search-filters-792496933.html) on LDAP search filters, it suggests that you need not escape `*` in your `userfilter`. Did you try that? –  Nov 03 '16 at 18:30
  • Also it looks like there is a missing closing bracket `)` in `userfilter`. –  Nov 03 '16 at 18:32
  • userfilter = ("SamAccountName="+username) returns nothing [] but userfilter = ("SamAccountName=bobsmith") returns a few attributes. – Infinity8 Nov 03 '16 at 18:46
  • What if you used `'(SamAccountName=%s)'% name'` - no spaces or quotes? –  Nov 03 '16 at 18:54
  • that returns the same ldap.FILTER_ERROR: {'desc': u'Bad search filter'} :( – Infinity8 Nov 03 '16 at 19:02
  • Oh okay. Nvm then. Do it the way you described it before which worked for you. –  Nov 03 '16 at 19:06
  • userfilter = "(&(objectClass=user)(sAMAccountName=actualusername))" works while introducing the variable username with userfilter1 = "(&(objectClass=user)" + "(sAMAccountName=" + username +"))" returns a bad search filter. – Infinity8 Nov 03 '16 at 19:09
  • What about `'(&(objectClass=user)(sAMAccountName=%s))' % name`? –  Nov 03 '16 at 19:11
  • No dice. Pretty stumped as these string joins seem to be fine but for whatever reason it just won't take the variable. – Infinity8 Nov 03 '16 at 19:33
  • What version of python are you using? –  Nov 03 '16 at 19:52
  • 2.7.8...Looking at this example http://stackoverflow.com/questions/140439/authenticating-against-active-directory-using-python-ldap the OP uses a variable...Yet when I try the same format with "username" as per my code, it gives me FILTER_ERROR! i tried userfilter = "(&(objectClass=user)(sAMAccountName="+username+"))" but when typing in the actual username as a string it works. – Infinity8 Nov 03 '16 at 19:57
  • I think it might be an issue with the string concatentation in python. Could you print `userfilter` and tell me what you get? –  Nov 03 '16 at 20:02
  • (&(objectClass=user)(sAMAccountName=serviceaccount)) – Infinity8 Nov 03 '16 at 20:05
  • Did you figure out how to solve this issue? Was there an answer that worked? –  Nov 08 '16 at 21:59
  • Nothing has worked so far. Very frustrating and strange issue. I opened a new question that is more specific to that string here http://stackoverflow.com/questions/40476182/ldap-search-with-username-as-variable/40480957#40480957 – Infinity8 Nov 08 '16 at 22:13

1 Answers1

0

I needed to use ldap.filter.filter_format for proper character escaping.

import ldap.filter

criteria= ldap.filter.filter_format('(&(objectClass=user)(sAMAccountName=%s))', [username])
Infinity8
  • 615
  • 2
  • 9
  • 24