?
Solved

Getting PHP to authenticate with LDAP correctly?

Posted on 2008-10-15
14
Medium Priority
?
3,220 Views
Last Modified: 2013-12-19
Hello.

I'm testing connecting to the LDAP using PHP. I have found a script (see code snippet), although when trying to run it, it just keeps asking for a username and password and after 3 tries will just say Authorization Failed. Ive tried entering in different usernames and password but to no avail. We created a user called changepassword to test the script with.

Is there anything missing or anything that needs to be done on the server in order to get this to work?

Webserver - Windows XP using Xampp web server

Main server - Windows Server 2008

Any advice is appreciated.


<?php
 
$ldapconfig['host'] = 'alumwell-s.walsall.sch.uk';
$ldapconfig['port'] = NULL;
$ldapconfig['basedn'] = 'DC=Alumwell-s,DC=walsall,DC=sch,DC=uk';
$ldapconfig['authrealm'] = 'alumwell-s.walsall.sch.uk';
 
function ldap_authenticate() {
    global $ldapconfig;
    global $PHP_AUTH_USER;
    global $PHP_AUTH_PW;
    
    if ($PHP_AUTH_USER = "changepassword" && $PHP_AUTH_PW = "changeme") {
      $ds=@ldap_connect($ldapconfig['host']);
       $r = @ldap_search( $ds, $ldapconfig['basedn'], 'uid=' . $PHP_AUTH_USER);
       if ($r) {
          $result = @ldap_get_entries( $ds, $r);
          if ($result[0]) {
              if (@ldap_bind( $ds, $result[0]['dn'], $PHP_AUTH_PW) ) {
                 return $result[0];
          }
         }
       }
    }
    header('WWW-Authenticate: Basic realm="'.$ldapconfig['authrealm'].'"');
    header('HTTP/1.0 401 Unauthorized');
    return NULL;
}
 
if (($result = ldap_authenticate()) == NULL) {
    echo('Authorization Failed');
    exit(0);
}
echo('Authorization success');
print_r($result);
 
?>

Open in new window

0
Comment
Question by:alumwell
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 6
14 Comments
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 22722620
What version of PHP?

Try $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW'


<?php
 
$ldapconfig['host'] = 'alumwell-s.walsall.sch.uk';
$ldapconfig['port'] = NULL;
$ldapconfig['basedn'] = 'DC=Alumwell-s,DC=walsall,DC=sch,DC=uk';
$ldapconfig['authrealm'] = 'alumwell-s.walsall.sch.uk';
 
function ldap_authenticate() {
    global $ldapconfig;
    
    if ($_SERVER['PHP_AUTH_USER'] = "changepassword" && $_SERVER['PHP_AUTH_PW'] = "changeme") {
      $ds=@ldap_connect($ldapconfig['host']);
       $r = @ldap_search( $ds, $ldapconfig['basedn'], 'uid=' . $_SERVER['PHP_AUTH_USER']);
       if ($r) {
          $result = @ldap_get_entries( $ds, $r);
          if ($result[0]) {
              if (@ldap_bind( $ds, $result[0]['dn'], $_SERVER['PHP_AUTH_PW']) ) {
                 return $result[0];
          }
         }
       }
    }
    header('WWW-Authenticate: Basic realm="'.$ldapconfig['authrealm'].'"');
    header('HTTP/1.0 401 Unauthorized');
    return NULL;
}
 
if (($result = ldap_authenticate()) == NULL) {
    echo('Authorization Failed');
    exit(0);
}
echo('Authorization success');
print_r($result);
 
?>

Open in new window

0
 

Author Comment

by:alumwell
ID: 22728731
Thanks for your reply.

I have just tried that code although i am still getting the login box coming up:

-----------
The server localhost at alumwell-s.walsall.sch.uk requires a username and password.

Warning: This server is requesting that your username and password be sent in an insecure manner (basic authentication without a secure connection).
-----------

Any other ideas? Are there any settings that need to be turned on etc? Do i need to be logged on to a certain user? etc etc

Thanks.
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 22728958
Can you remove the @'s. These will hide any errors.

Add at the top of your script ...

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
set_time_limit(0);
//... Your code now ...

Let's see what else you may get.
0
Are You Using the Best Web Development Editor?

The worlds of web hosting and web development are constantly evolving. Every year we see design trends change, coding standards adapt and new frameworks/CMS created. With such a quick pace of change it’s easy to get lost trying to keep up.

See if your editor made the list.

 

Author Comment

by:alumwell
ID: 22729103
Thank you for your reply.

I've put that code in and taken out the '@'s and i now get this error:

---------
Warning: ldap_search() [function.ldap-search]: Search: Operations error in C:\xampp\htdocs\test.php on line 17

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\test.php:17) in C:\xampp\htdocs\test.php on line 27

Warning: Cannot modify header information - headers already sent by (output started at C:\xampp\htdocs\test.php:17) in C:\xampp\htdocs\test.php on line 28
Authorization Failed
---------

Is this a step forward? Any ideas now? Current code is attached.

Thanks again.
<?php
 
 error_reporting(E_ALL);
ini_set('display_errors', 1);
set_time_limit(0);
 
$ldapconfig['host'] = 'alumwell-s.walsall.sch.uk';
$ldapconfig['port'] = NULL;
$ldapconfig['basedn'] = 'DC=Alumwell-s,DC=walsall,DC=sch,DC=uk';
$ldapconfig['authrealm'] = 'alumwell-s.walsall.sch.uk';
 
function ldap_authenticate() {
    global $ldapconfig;
    
    if ($_SERVER['PHP_AUTH_USER'] = "changepassword" && $_SERVER['PHP_AUTH_PW'] = "changeme") {
      $ds=ldap_connect($ldapconfig['host']);
       $r = ldap_search( $ds, $ldapconfig['basedn'], 'uid=' . $_SERVER['PHP_AUTH_USER']);
       if ($r) {
          $result = ldap_get_entries( $ds, $r);
          if ($result[0]) {
              if (ldap_bind( $ds, $result[0]['dn'], $_SERVER['PHP_AUTH_PW']) ) {
                 return $result[0];
          }
         }
       }
    }
    header('WWW-Authenticate: Basic realm="'.$ldapconfig['authrealm'].'"');
    header('HTTP/1.0 401 Unauthorized');
    return NULL;
}
 
if (($result = ldap_authenticate()) == NULL) {
    echo('Authorization Failed');
    exit(0);
}
echo('Authorization success');
print_r($result);
 
?>

Open in new window

0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 22729427
You may find your ldap server isn't allowing anonymous connections / searching.

So you need to ldap_bind() right after ldap_connect().

By binding with the supplied credentials, you know if they are valid or not. No need to try and find the user first.

0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 22729436
If you can't bind because you don't know the full DN, then you will need to bind using a set of known credentials first (I would recommend creating an account with readonly access to limited parts of the LDAP if that is possible).
0
 

Author Comment

by:alumwell
ID: 22730394
Gettin closer. Right, i now have the code that i will attach, i am getting this message:

-------------
Congratulations! changepassword is authenticated.
Warning: ldap_search() [function.ldap-search]: Search: Operations error in C:\xampp\htdocs\test2.php on line 25
Error in search query
------------

So there is something wrong with the search operation. Cannot figure out what though. The only thing i'm not sure about is the $query variable. Any ideas or advice?

Once again, thanks for your help.
<?php
$ldaphost = "alumwell-s.walsall.sch.uk";
$ldapport = 389;
 
$ds = ldap_connect($ldaphost, $ldapport)
or die("Could not connect to $ldaphost");
 
if ($ds)
{
    $username = "changepassword";
    $upasswd = "changeme";
 
    $ldapbind = ldap_bind($ds, $username, $upasswd);
                              
    if ($ldapbind)
        {print "Congratulations! $username is authenticated.";}
    else
        {print "Nice try, kid. Better luck next time!";}
}
 
// create the search string
$query = "(&(name=" . $_POST['name'] . "))";
 
ldap_search($ds,"DC=Alumwell-s,DC=walsall,DC=sch,DC=uk", $query) or die("Error in search
query");
 
// get entry data as array
$info = ldap_get_entries($ds, $result);
 
// iterate over array and print data for each entry
echo "<ul>";
for ($i=0; $i<$info["count"]; $i++)
{
echo "<li>".$info[$i]["sn"][0]." - ".$info[$i]["mail"][0]." -
".$info[$i]["dn"]."</li>"; } echo "</ul>";
 
// print number of entries found
echo "Number of entries found: " . ldap_count_entries($ds, $result) .
"<p>";
 
// all done? clean up
ldap_close($ds);
 
?>

Open in new window

0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 22730650
Can you try ...

$query = "name={$_POST['name']}";
0
 

Author Comment

by:alumwell
ID: 22731436
Tried that to no avail. Says the same thing.

Any other suggestions are welcomed. Thanks again.
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 22731596
There is a difference between the login name and the name.

Try ...

$query = 'name=' . $_POST['name']{0} . '*';

This will wild card based upon the first letter of their name.

Also try ...

$query = "samaccountname={$_POST['name']}";

Is this to Active Directory (that's where I get samaccountname from).

For example, my login account name is RichardQ (samaccountname = RichardQ, but my name is Richard A. Quadling


0
 

Author Comment

by:alumwell
ID: 22731771
Well going on username i now have what is attached in the code snippet. A number of usernames start in st, so i've tried using the wildcard to get some results. But i still get the same error:

-------
Congratulations! changepassword is authenticated.
Warning: ldap_search() [function.ldap-search]: Search: Operations error in C:\xampp\htdocs\test2.php on line 27
Error in search query
------

line 27 being the 'ldap_search' line.

Any other ideas?

Thanks for your help so far.
<?php
$ldaphost = "alumwell-s.walsall.sch.uk";
$ldapport = 389;
 
$ds = ldap_connect($ldaphost, $ldapport)
or die("Could not connect to $ldaphost");
 
if ($ds)
{
    $username = "changepassword";
    $upasswd = "changeme";
 
    $ldapbind = ldap_bind($ds, $username, $upasswd);
                              
    if ($ldapbind)
        {print "Congratulations! $username is authenticated.";}
    else
        {print "Nice try, kid. Better luck next time!";}
}
 
 
 
// create the search string
$name = "st";
$query = "samaccountname=" . $name{0} . '*';
 
ldap_search($ds,"DC=Alumwell-s,DC=walsall,DC=sch,DC=uk", $query) or die("Error in search query");
 
// get entry data as array
$info = ldap_get_entries($ds, $result);
 
// iterate over array and print data for each entry
echo "<ul>";
for ($i=0; $i<$info["count"]; $i++)
{
echo "<li>".$info[$i]["sn"][0]." - ".$info[$i]["mail"][0]." -
".$info[$i]["dn"]."</li>"; } echo "</ul>";
 
 
 
 //print number of entries found
echo "Number of entries found: " . ldap_count_entries($ds, $result) .
"<p>";
 
 
 
// all done? clean up
ldap_close($ds);
 
?>

Open in new window

0
 
LVL 40

Accepted Solution

by:
Richard Quadling earned 1500 total points
ID: 22732069
ldap_search returns a resource.

Try using ...

$result = ldap_search(...);

http://docs.php.net/ldap_search
0
 

Author Comment

by:alumwell
ID: 22738394
Thanks. I had a look on that link and used what you'd said previously with it and i now have a working piece of code. Now i will have a go with it. Thanks again.
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 22738637
Excellent.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Recently I was talking with Tim Sharp, one of my colleagues from our Technical Account Manager team about MongoDB’s scalability. While doing some quick training with some of the Percona team, Tim brought something to my attention...
There are times when I have encountered the need to decompress a response from a PHP request. This is how it's done, but you must have control of the request and you can set the Accept-Encoding header.
Video by: Steve
Using examples as well as descriptions, step through each of the common simple join types, explaining differences in syntax, differences in expected outputs and showing how the queries run along with the actual outputs based upon a simple set of dem…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

801 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question