So you have an LDAP server and you'd like to add authentication to a PHP based website. Well you have came to the right place! I started hosting my own mail server (Don't ask) and used LDAP for authentication so it made sense to create a website with LDAP and webmail/roundcube as well. I will go over step by step instructions on how to get this set up including code snippets. You will need to modify the code to fit your environment but my guide should get you most of the way there!


Add PHP LDAP extension to underlying server or host

  1. First things first. You need to add the LDAP extension to your PHP code base to be able to use it. On synology DSM webstation, this is done very easily.
  2. Open Webstation
  3. Select your PHP webservice and select Edit. I used a containerized webservice
  4. Click on Extensions and look for the ldap extension and check the box. Then click apply
  5. The container or service should pull the extension and automatically install it. Thats it!

  6. NOTE: Now is a good time to install the google/recaptcha module if you have not done that yet. On Synology, this is done very easily by editting the PHP service like before and selecting the dependency tab. Then enter in "google/recaptcha" in the box and click apply. This will come in handy for adding a recaptcha to your login, which is basically mandatory.


Adding the LDAP PHP code to your page


Now that you'd installed the extension, you can add authentication to your PHP webpage! The code is rather simple and easy. Here is a rundown of the code...

<?php
// LDAP authentication
$ldap_host = "ldap.example.com";
$ldap_dn = "ou=people,dc=example,dc=com";
$ldap_user = "username";
$ldap_pass = "password";

// Connect to LDAP server
$ldapconn = ldap_connect($ldap_host) or die("Could not connect to LDAP server.");

// Set some ldap options for talking to
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);

// Bind to the LDAP server
$ldapbind = ldap_bind($ldapconn, $ldap_user, $ldap_pass);

// Verify the binding
if ($ldapbind) {
    echo "LDAP bind successful...";
} else {
    echo "LDAP bind failed...";
}

// Image verification or Recaptcha
$captcha = new ReCaptcha('YOUR_SECRET_KEY');
$resp = $captcha->verifyResponse($_SERVER["REMOTE_ADDR"], $_POST["g-recaptcha-response"]);
if ($resp != null && $resp->success) {
    echo "Captcha verified";
} else {
    echo "Captcha verification failed";
}
?>


Now this is a very basic set up and does not include the forms and html portion. You can use this code as a starting point for your own environment. Since I've already done the work of creating code for a full login, I will provide that below.

The following code includes sanitized inputs as well as the forms required for user input. 

<?php
session_start();
//Check if a session already exists and if so, redirect them.
//This prevents people from having to login every time they visit
if(isset($_SESSION['id']))
{
    if($_SESSION['id'] == session_id())
    {
        header("Location: https://example.com/login.php");
        exit;
    }
}
function ldapSanitize($val) 
{
    $sanitized=array('\\' => '\5c',
        '*' => '\2a',
        '(' => '\28',
        ')' => '\29',
        '\x00' => '\00',
        This email address is being protected from spambots. You need JavaScript enabled to view it.' => '');
    return str_replace(array_keys($sanitized),array_values($sanitized),$val);
}
// Get a key from https://www.google.com/recaptcha/admin/create
$publickey = 
$privatekey = 
if(isset($_POST['submitlogin']))
{
    $success = null;
    $failed = null;
    $ercaptcha = null;
    $recaptcha = $_POST['g-recaptcha-response']; 
    // Hitting request to the URL, Google will 
    // respond with success or error scenario 
    $url = 'https://www.google.com/recaptcha/api/siteverify?secret='
        . $privatekey . '&response=' . $recaptcha; 
    // Making request to verify captcha 
    $response = file_get_contents($url); 
    $response = json_decode($response); 
    // Checking, if response is true or not 
    if ($response->success == true) 
    { 
        $ldapuser = "uid=".ldapSanitize($_POST["username"]);
        $user = $_POST["username"];
        $ldaprdn  = $ldapuser."DC=subdomain,DC=example,DC=com";
        $ldappass = $_POST["password"];
        $ldapconn = ldap_connect("ldaps://subdomain.example.com", 636) or die("Could not connect to LDAP server.");
        ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
        ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
        if ($ldapconn) 
        {
            $ldapbind = @ldap_bind($ldapconn, $ldaprdn, $ldappass);
            if ($ldapbind) 
            {
                $justthese = array("displayName", "mail");
                $Result = ldap_search($ldapconn, "DC=subdomain,DC=example,DC=com", $ldapuser, $justthese);
                $data = ldap_get_entries($ldapconn, $Result);
                $_SESSION['id'] = session_id();
                $_SESSION['ldapuser'] = $ldapuser;
                $_SESSION['ldaprdn'] = $ldaprdn;
                $_SESSION['password'] = $ldappass;
                $_SESSION['username'] = $user;
                //Write all needed information into session variables before session write close
                //and then redirect to your next page where the user will be logged in.
                session_write_close();
                header("Location: https://example.com/login.php"); 
                exit;
            }
            else 
            {
                $failed = ldap_error($ldapconn);
            }
        } 
    }
    else 
    {
        $ercaptcha = "Error with reCAPTCHA, try again";
    }
}
?>
//HTML CODE STARTS HERE
//Insert Your HTML Here - See the next code block for example HTML
<?php
    if(isset($_POST['submitlogin']))
    {
        if($ercaptcha)
        {
            echo "<br><br><span style=background-color:#ffcc00;>".$ercaptcha."</span>";
        }
        if($failed)
        {
        echo "<br><br><span style=background-color:#ffcc00;>".$failed."</span>";
        }
    }
?>

Thats it! Below is an example of HTML you can use between the two portions of PHP in the previous block.

<!--PHP CODE STARTS BEFORE THIS-->
<body><form action="" method="post"><br><table class="GeneratedTable"><thead>
    <tr>
      <th>Username</th>
      <th>Password</th>
    </tr>
    </thead>
<tbody>
    <tr>
      <td><input type="text" name="username" /></td>
      <td><input type="password" name="password" /></td>
    </tr>
  </tbody>
</table>
<br>
<div class="g-recaptcha" data-sitekey="6Lek354oAAAAAB5GfEUYvOnn8TnwlX-aOX_di8l6">
</div>
<br>
<input type="submit" name="submitlogin" /> 
</form>
<div class ="LoginMessage">
<!--PHP CODE BEGINS HERE-->
You can see I used LDAPS with port 636 but you can simply change that to 389 if your ldap server is not using LDAPS. I am also limiting the LDAP search to just displayname and mail as those are the only two attributes I care about matching. Because I run the sanitize against the username input, the user may login with email address or username. Both will work!
 
The second example also captures error messages in the $failed variable and will echo them to the user so they can tell whether the issue is the username, the password, or the recaptcha verification.
 
For the google recaptcha module to work, you will need to get your own public and private site keys. You can do that here https://www.google.com/recaptcha/admin/create

Conclusion

We went over installing the LDAP extension as well as the google recaptcha extension and I gave a simple code example as well as a more advanced example using sanitized inputs. Hopefully this article was useful. Feel free to email me at This email address is being protected from spambots. You need JavaScript enabled to view it. if you have any feedback.

No comments