Active Directory LDAP requires a login - DaDaBiK's config doesn't have one!

Transistor

New member
I'm trying to use LDAP to authenticate against the company Active Directory. A username and password is required to make an LDAP request but DaDaBiK doesn't provide any settings in config.php to facilitate this.

This test script from GitHub works OK (once the variables are set).

[pre]
//domain name(or URL),account,password should replace with actual string
<?php
//For testing the AD server is work or not
$ldaphost="domain name";
$ldapconn=ldap_connect($ldaphost);
if($ldapconn)
echo "Connect success<br>";
else
echo "Connect Failure";
//For simplification,you can wirte $ldapconn = ldap_connect($ldaphost)or die("Could not connect to ".$ldaphost);
//rdn:relative distinguished name
$User="account";
$ldaprdn=$User."@".$ldaphost;
$ldappass="password";
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
//Reference:http://php.net/manual/en/function.ldap-bind.php
if ($ldapconn) {
// binding to ldap server
$ldapbind = ldap_bind($ldapconn, $ldaprdn, $ldappass);
// verify binding
if ($ldapbind) {
echo "LDAP bind successful...";
} else {
echo "LDAP bind failed...";
}
}
ldap_close($ldapconn);
?>
[/pre]

How do we do this with DaDaBiK?






DaDaBIK version 9.4-Monterosso pro, installed on 11-22-2019 (installation code: 150615dd851a6018d8),
PHP Version: 5.5.9
mysql version: 5.6.11
Web server: Microsoft-IIS/7.0
Client: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36
 

Transistor

New member
I though some more about this. In previous applications I had to provide a service account username and password to browses Active Directory. I realise now that DaDaBiK is using the username and password entered which, if valid, will gain access to Active Directory and allow authentication. Very clever!

I have used Microsoft's AD Explorer to find the following information from my company's system:

[pre]
OU=Users,OU=Users & Computers,OU=MyTown,OU=DE,OU=MyCompany Locations,DC=MyCompany,DC=com
[/pre]

So, my best guess is that I should set up the LDAP options in config.php as follows:

[pre]
$ldap_base_dn_ar[0]['attribute_name'] = 'ou';
$ldap_base_dn_ar[0]['attribute_value'] = 'Users';
$ldap_base_dn_ar[1]['attribute_name'] = 'ou';
$ldap_base_dn_ar[1]['attribute_value'] = 'Users & Computers';
$ldap_base_dn_ar[2]['attribute_name'] = 'ou';
$ldap_base_dn_ar[2]['attribute_value'] = 'MyTown';
$ldap_base_dn_ar[3]['attribute_name'] = 'ou';
$ldap_base_dn_ar[3]['attribute_value'] = 'DE';
$ldap_base_dn_ar[4]['attribute_name'] = 'ou';
$ldap_base_dn_ar[4]['attribute_value'] = 'MyCompany Locations';
$ldap_base_dn_ar[5]['attribute_name'] = 'dc';
$ldap_base_dn_ar[5]['attribute_value'] = 'MyCompany';
$ldap_base_dn_ar[6]['attribute_name'] = 'dc';
$ldap_base_dn_ar[6]['attribute_value'] = 'com';
[/pre]

I have tried my username and password in the login screen and receive the "Username or password incorrect" error.

I feel that I am very close to success. Any ideas?
 

eugenio

Administrator
Staff member
Hello,
yes, DaDaBIK check the user and pass entered against an LDAP server; everything you wrote seems fine to me, except the fact the "ou" and the other attribute names are lowercase, I would try using the same case you get from Microsoft's AD Explorer.

Have you also checked if $ldap_username_field is correct?

Best,
 

Transistor

New member
Yes, I got it to work by setting
[pre]
$ldap_username_field = 'CN';
[/pre]
and using my "Firstname Lastname" as my login rather than my username (xxxxxxyy, where xxxxxx is the first six letters of family name and yy are initials) which is what I would normally use for Single Sign-On (SSO).

I have one other question on this (for now!). In my attribute_name/attribute_value pairs above I have to give the full AD path to the CN field. I think this means that someone in another office cannot login. Is there a way to specify an LDAP 'sub:' search so that I can make the application Intranet global? I would then just use:

[pre]
$ldap_base_dn_ar[0]['attribute_name'] = 'ou';
$ldap_base_dn_ar[0]['attribute_value'] = 'MyCompany Locations';

$ldap_base_dn_ar[1]['attribute_name'] = 'dc';
$ldap_base_dn_ar[1]['attribute_value'] = 'MyCompany';

$ldap_base_dn_ar[2]['attribute_name'] = 'dc';
$ldap_base_dn_ar[2]['attribute_value'] = 'com';
[/pre]

Many thanks again.
 

eugenio

Administrator
Staff member
Hello,
I am glad it works now; about your question: no I don't think the LDAP search can work specifying a "sub" search; a possible workaround: if you can get, via php, the current office, you can in your config_custom.php override your ldap config parameters according to the office.


Best,
 

abraun

Member
Is there a chance that this non-OU specific search method can be added to a requested features list? I believe if we were to specify a bind DN as a service account or something, then you could pass the login page user and password into the search function of the already bound connection to reach past the OU.
 

abraun

Member
Where does the code that actually executes the ldap login live? I wonder if I can add another variable to specifcally define a bind DN and insert it there while leaving the search query to the base dn.
 

Transistor

New member
eugenio Wrote:
-------------------------------------------------------
> No, I don't think the LDAP search can work specifying a "sub" search; a possible workaround:

LDAP.com seems to suggest that it is possible. I don't know enough to understand it all.

>if you can get, via php, the current office, you can in your config_custom.php override your ldap config parameters according to the office.

I wouldn't know from their login what office the user belongs to.

I like @abraun's suggestion. I have a service account specially for LDAP. If I could use that would DaDaBiK be able to retrieve the information to add into the dadabik_users table?
 

eugenio

Administrator
Staff member
Hi all,
at the moment it is not possible to do what you need in DaDaBIK without modification to the code but you can override your ldap config parameters according to some custom code ... if you can, using custom code, find the correct ldap parameters to use and then override them, this can be a solution (you can do everything in your config_custom.php file).

Of course you can add your proposal to the feature requests forum, if there is enough interest I will look into that for a future release.

Best,
 

Transistor

New member
Caio, Eugenio.

I am working on a config_custom.php code to use my Active Directory service account to login and get the AD path for the user.

What is the php variable name for the username entered in the login form?

Grazie.
 
Transistor,

Were you able to make any progress with this approach? I would be interested in the logic you added to the custom PHP file if it does work for you as it may apply to our situation as well. Obviously, remove any of your server specific names details, etc.

Thanks in advance!
 
Transistor Wrote:
-------------------------------------------------------
> Yes, I got it to work by setting
> [pre]
> $ldap_username_field = 'CN';
> [/pre]
> and using my "Firstname Lastname" as my login rath
> er than my username (xxxxxxyy, where xxxxxx is the
> first six letters of family name and yy are initia
> ls) which is what I would normally use for Single
> Sign-On (SSO).
>
> I have one other question on this (for now!). In m
> y attribute_name/attribute_value pairs above I hav
> e to give the full AD path to the CN field. I thin
> k this means that someone in another office cannot
> login. Is there a way to specify an LDAP 'sub:' se
> arch so that I can make the application Intranet g
> lobal? I would then just use:
>
> [pre]
> $ldap_base_dn_ar[0]['attribute_name'] = 'ou';
> $ldap_base_dn_ar[0]['attribute_value'] = 'MyCompan
> y Locations';
>
> $ldap_base_dn_ar[1]['attribute_name'] = 'dc';
> $ldap_base_dn_ar[1]['attribute_value'] = 'MyCompan
> y';
>
> $ldap_base_dn_ar[2]['attribute_name'] = 'dc';
> $ldap_base_dn_ar[2]['attribute_value'] = 'com';
> [/pre]
>
> Many thanks again.

Hello, thought I'd contribute as well.

My details:
[pre]
PHP Version: 7.2.5

mysql version: 5.5.5-10.2.31-MariaDB

Web server: Apache

Client: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36
[/pre]

I too have observed similar issues getting the LDAP authentication to work. Only the "Firstname Lastname" combination works. Our single sign on format is xyyyyyyyy where x is the first initial of the firstname and yyyyyyyy is the last name. The whole string is in lowercase even though LDAP seems to capitalize the first 2 characters. I have tried augmenting the dn array to add the mailNickname or sAMAccountName fields that the LDAP server tree maintains as that value format but this makes no difference. Only using $ldap_username_field = 'CN'; in the config_custom.php with the "Firstname Lastname" combination at login works at all. While somewhat viable this is not ideal (read further).

We also have the problem of this solution not working for some locations as we have 2 separate OU's setup for North America and Italy (EU) so our users in Milan will not be able to use this approach as the OU=EU they fall under would be left out of the dn array and they would never be found on the server. There would have to be some kind of logic in the custom PHP script to determine where the user is logging in from and alter the dn array accordingly. I currently do not know how to write this, although I'm sure there are PHP API's for querying LDAP servers. Having multiple dn arrays and DaDaBik and checking all of them upon authentication is one possible solution though it will require code changes to the software so this is not an immediate fix and that approach seems hackish at best but it what occurred to me off the top of my head.

So, I will attempt to add special instructions to the login page header for the users to enter this unorthodox (for us) username format and try to live with that for now.

Some final thoughts:
I did notice that the password hash is present in the users table after LDAP login. Is this a security concern? Does this get salted so it is different from the LDAP internal maintained hashes? If the user changes the password here does it only make that change on the DaDaBik user account and not LDAP? I assume it must not but clarification would be nice. This might make keeping the two account passwords straight difficult for the end user. Is there an easy way to suppress giving the user the pw change option in the permissions table so if it does not update LDAP the danger of getting the accounts out of sync will be minimized?

Sorry for all the questions. I just got the product up and running and am excited for all it can do and the time it looks like it will save us!

Thanks
 

eugenio

Administrator
Staff member
Hi h2fuelcell,
I'll answer about the last part: after the first ldap login, the user is copied in the dadabik_users tab, the hash of the password is created using https://www.openwall.com/phpass/ so it is salted but the algorithm used depends on what the system "offers" (see details on the phpass website).
If you change your password in DaDaBIK, it is only changed in DaDaBIK (no LDAP) and if you want you can set $enable_user_password_modification = 0 in config.php.

Storing the ldap password is probably not very useful anyway, I will think about removing this in future releases.

Best,
 
Thanks for the new LDAP features in v11.4. I look forward to testing them out and using them.

So, in the interim we were able to come up with a solution to the problem similar to what Transistor posted Dec. 5 2019.

Here is a rough outline of what we did that will hopefully save someone else some time should they run into this problem...
We modified the config_custom.php script adding the following lines:
PHP:
$shell_cmd = "ldap_get_user_location.sh \"" . $_POST['username_user'] . "\" 2>&1";
$location = shell_exec($shell_cmd);
Then we substituted the $location variable for the previous dn_ar attribute value containing the string that varies for different users.

Finally we wrote a bash script (ldap_get_user_location.sh) containing the following ldap search command and some grep and awk logic
that we use to retrieve the location string. The script gets passed the username and returns the location string. Substitute your LDAP specifics for the capitalized string descriptions.

Bash:
ldapsearch -x  -h "LDAP SERVER ADDRESS" \
                 -D  " SERVICE ACCOUNT DN" \
                 -w $(cat SERVICE ACCOUNT PW FILE) \
                 -b "OU="${LOCATION}",USER DN STRING" cn sAMAccountName | \
                 grep --ignore-case --before-context 3 "${USERNAME}" | \
                 grep "dn:" | awk  --field-separator=, '{print $2}' | \
                 awk  --field-separator='=' '{print $2}'

That was it. Setting the $enable_ldap_debug_mode flag along with some var_dump statements in the custom PHP file was super helpful in debugging at the end.

Hope this helps...
 
Top