pythonflaskldapldap3

Search for givenName and surname attribute for the id we provide during login for ldap3 in python and flask


I was able to set up the authentication for my flask app using ldap3. We use active directory and hence I used ldap3 to connect to our active directory and verify the users against input credentials. The problem I am having is with the way it has been set up. Below is the code as you can see:

def global_ldap_authentication(user_id, user_pwd):
    ldap_user_id = user_id.strip()
    ldap_user_pwd = user_pwd.strip()
    ldsp_server = f'our_internal_server'

    root_dn = "OU=Users,OU=AUS - Austin,OU=Americas,OU=JCJJ,DC=jcjj,DC=com"

    user = f'CN=Dave Simmon - {ldap_user_id},{root_dn}'

    server = Server(ldsp_server, get_info=ALL)
    connection = Connection(server, user=user, password=ldap_user_pwd)
    connection.start_tls()



    if not conn.bind():
       print(f" *** cannot bind to ldap server: {conn.last_error}")
       l_success_msg = f' *** Failed Authentication: {conn.last_error}'
    else:
       print(f" *** Successful bind to ldap server")
       l_success_msg = 'Happy'

    return l_success_msg

As you can see this connects to my ldap server and lets me log in. My login route is simple as it takes userID and password and calls this global_ldap_authentication function with these attributes and logs in the user if it authenticates against the active directory that we have. The problem is with the variable 'user' where I have specified a name Dave Simmon in order to connect to ldap which means only user Dave simmon can log in to my app using his user ID (A5564, this is the number for user id) and his password.

I tried other ways of connecting to our ldap directory but I was not successful and it only worked this way. I finally found a technique to make that name variable instead of Dave Simmon. We have a service account and my plan is to log in to ldap using that service account and its password everytime this function gets called and since I will be getting userID and password from the form in login page, I want to search the ldap active directory for the givenName and surname(sn) that belongs to the userid anyone inputs in login form and then replace that Dave simmon with that givenName and sn from active directory.

This will let anyone that is present in that directory log in to my app. The problem is I am having hard time figuring out how to do it. How do I search for givenName and Surname(sn) based on the userID I receive. The userID is unique and each userID is mapped to their users respective first name and last name. SO when A5564 is input in my login form then I should be able to query the Dave Simmon from my active directory so that I can make a successful connection and login.

I tried to make this as detailed as possible. Any help will be highly appreciated!!

My login route is super simple:

@app.route('/', methods=['GET', 'POST'])
def login():
  form = LoginForm()
  if request.method in ('POST'):
    login_id = form.userid.data
    login_password = form.password.data
    
    #used to pass argument to main_page
    print(login_id)
    session['login_id'] = login_id

    login_msg = global_ldap_authentication(login_id, login_password)

    #validate the connection
    print(login_msg)
    if login_msg == "Success":
        return redirect(url_for('main_page'))
        #return render_template('index.html')

    else:
        return render_template('login.html', form=form)

  return render_template('login.html', form=form)

Solution

  • I ultimately figured it out just in case someone needs it. I was able to use this for that.

    conn.search('OU=AUS - Austin,OU=Americas,OU=JCJJ,DC=jcjj,DC=com', '(&(objectclass=person)(sAMAccountName={id}))'.format(id=ldap_user_name), attributes=['CN'])
    entry = conn.entries[0]
    name = entry.CN
    

    So, as I stated before, I was able to connect to ldap active directory using a service account and password at first. And then, I ran the above search based on what 'id' user inputed in my login form. I then mentioned that I want 'CN' attribute which returns the name in this format: Dave Simmon - A5564. This is exactly what I needed to make a variable instead of hard coding it.

    So, I stored this Dave Simmon - A5564 in a variable called name and used this variable to connect to my ldap again and let users see the main page of my app. Now, any users who input their ID would have their name stored in variable called 'name' and will be able to log in to the web page.

    Thanks!