Using LDAP and PHP to create a log in system


#1

Hi there,

I've been scouring the internet to make a log in using LDAP.

So far I've got some code but as soon as I hit submit nothing seems to be happening, I don't know if i'm missing something so painfully obvious or i've coded it wrong but I would appreciate any help you can give.

Code in question:

index.html

<!DOCTYPE html>
<html lang="en">
<head>

  <meta charset="utf-8">
  <title>Hyperslice</title>
  <meta name="description" content="">
  <meta name="author" content="">

  <meta name="viewport" content="width=device-width, initial-scale=1">

  <link href="//fonts.googleapis.com/css?family=Raleway:400,300,600" rel="stylesheet" type="text/css">

  <link rel="stylesheet" href="css/normalize.css">
  <link rel="stylesheet" href="css/skeleton.css">

  <link rel="icon" type="image/png" href="images/favicon.png">

</head>
<body>

<?php
// initialize session
session_start();
 
include("authenticate.php");
 
// check to see if user is logging out
if(isset($_GET['out'])) {
	// destroy session
	session_unset();
	$_SESSION = array();
	unset($_SESSION['user'],$_SESSION['access']);
	session_destroy();
}
 
// check to see if login form has been submitted
if(isset($_POST['uname'])){
	// run information through authenticator
	if(authenticate($_POST['uname'],$_POST['psw']))
	{
		// authentication passed
		header("Location: protected.php");
		die();
	} else {
		// authentication failed
		$error = 1;
	}
}
 
// output error to user
if(isset($error)) echo "Login failed: Incorrect user name, password, or rights<br />";
 
// output logout success
if(isset($_GET['out'])) echo "Logout successful";
?>
  <div class="container">
    <div class="row">
      <div class="one-half column" style="margin-top: 25%">
        <form method="post" action="index.html">
 

  <div class="container">
    <label for="uname"><b>Username</b></label>
    <input type="text" placeholder="Enter Username" name="uname" required>

    <label for="psw"><b>Password</b></label>
    <input type="password" placeholder="Enter Password" name="psw" required>

    <input type="submit" name="submit" value="submit" ></input>
    <label>
      <input type="checkbox" checked="checked" name="remember"> Remember me
    </label>
  </div>

</form> 
      </div>
    </div>
  </div>
  
</body>
</html>

Authenticate.php (i've changed the contents of the variables for security purposes)

<?php
function authenticate($user, $password){
	if(empty($user) || empty($password)) return false;
	
	$ldap_host = "1234.net";
	
	$ldap_dn = "OU=departments,DC=1234,DC=net";
	
	$ldap_user_group = "Users";
	
	$ldap_manager_group = "managers";
	
	$ldap_usr_dom = "@1234.net";
	
	$ldap = ldap_connect($ldap_host);
	
	ldap_set_option($ldap,LDAP_OPT_PROTOCOL_VERSION,3);
	ldap_set_option($ldap,LDAP_OPT_REFERRALS,0);
 
	// verify user and password
	if($bind = @ldap_bind($ldap, $user.$ldap_usr_dom, $password)) {
		// valid
		// check presence in groups
		$filter = "(sAMAccountName=".$user.")";
		$attr = array("memberof");
		$result = ldap_search($ldap, $ldap_dn, $filter, $attr) or exit("Unable to search LDAP server");
		$entries = ldap_get_entries($ldap, $result);
		ldap_unbind($ldap);
 
		// check groups
		$access = 0;
		foreach($entries[0]['memberof'] as $grps) {
			// is manager, break loop
			if(strpos($grps, $ldap_manager_group)) { $access = 2; break; }
 
			// is user
			if(strpos($grps, $ldap_user_group)) $access = 1;
		}
 
		if($access != 0) {
			// establish session variables
			$_SESSION['user'] = $user;
			$_SESSION['access'] = $access;
			return true;
		} else {
			// user has no rights
			return false;
		}
 
	} else {
		// invalid name or password
		return false;
	}
}
?>

protected.php

<?php
// initialize session
session_start();
 
if(!isset($_SESSION['user'])) {
	// user is not logged in, do something like redirect to login.php
	header("Location: index.html");
	die();
}
 
if($_SESSION['access'] != 2) {
	// another example...
	// user is logged in but not a manager, let's stop him
	die("Access Denied");
}
?>
 
<p>Welcome <?= $_SESSION['user'] ?>!</p>
 
<p><strong>Secret Protected Content Here!</strong></p>
 
<p>Mary Had a Little Lamb</p>
 
<p><a href="index.html?out=1">Logout</a></p>

Any help would be appreciated since i've been stumped on this for a few hours now.

Thanks!


#2

You can't call session_start() after you've sent output to the browser. Don't you get an error message for that?

You also can't do header redirects after any browser output. Might this be why it's not working as you want it to? That is, could you just stick an echo() statement before each header redirect and see if it's getting there but just not redirecting?


#3

I don't get any error messages. Once I click submit, the form just clears itself


#4

OK, so maybe the form is submitting, then getting to your authentication check function, getting a valid user, not being able to header redirect (because of the previous browser output), then hitting die(), and doing exactly that. Add some debugging echo() statements to follow what it's doing, then remove them later. Or enable error messaging.

But, with all that HTML before your PHP in index.html, session and header functions will not work. You'll need to change the order around. Even a blank line before your opening <?php tag will stop those functions working, because as soon as you send output to the browser, headers are automatically sent and cannot be sent again.


#5

After putting the echo before the header and trying again, nothing echo'd out. Seems like the redirect isn't working. Also, at the top of the screen i'm getting this as soon as I load the page: "; // output logout success if(isset($_GET['out'])) "Logout successful"; ?>

I'm gonna add some echo statements and change the code around so the php is at the top and i'll update with what I find. Seems to me like it's automatically saying i've just logged out without actually inputting anything into the form itself.


#6

That suggests that, for some reason, PHP is not processing that line of code, just displaying it. I can't see anything from your post why that might be, could there be something on the previous line that causes it?


#7

Also, is your server configured to process PHP code inside files that are not saved with a .php extension? I'm guessing it must be, to have got this far with a file called index.html.


#8

I'm currently doing it through the run feature in notepad++

I haven't really done much php since college about two years ago so i'm incredibly rusty but i'm the only one here with any sort of experience within the language.


#9

I've never tried that, I would be tempted to look at how that is configured, or try to set up a test WAMP or XAMPP server.


#10

I've got it set up on a server with php installed. The line before the error is just a blank line:

// check to see if login form has been submitted
if(isset($_POST['uname'])){
	// run information through authenticator
	if(authenticate($_POST['uname'],$_POST['psw']))
	{
		// authentication passed
		header("Location: protected.php");
		die();
	} else {
		// authentication failed
		$error = 1;
	}
}
 
// output error to user
if(isset($error))echo "Login failed: Incorrect user name, password, or rights<br />";

// output logout success
if(isset($_GET['out'])) echo "Logout successful";
?>

#11

I've managed to get rid of the text showing up at the top by removing the <br />. However, it still is not redirecting me to the protected page


#12

And have you changed the layout so that nothing is being sent to the browser before you try to use any session and header-related functions?

If you put an echo statement just before the header redirect, does it display?

Show the latest version of the code if you are still having trouble.


#13

Why do yourself a favor and use one of the many ldap packages out there instead of struggling with basic php issues? For example: https://symfony.com/doc/current/security/ldap.html


#14

// check to see if login form has been submitted
if(isset($_POST['userLogin'])){
    echo "Hello";
	// run information through authenticator
	if(authenticate($_POST['userLogin'],$_POST['userPassword']))
	{
		// authentication passed
		header("Location: protected.php");
		die();
	} else {
		// authentication failed
		$error = 1;
	}
}

This will correctly display an echo command. However if I place the echo command just above the header, nothing happens. This seems to suggest to me that the header redirect is not working. I managed to get the script to actually run by changing it from index.html to index.php (the fact it took me so long to figure that out is quite embarrassing) but i'll always get the error of "Login failed: Incorrect user name, password or rights".

Going into the web server I can see that it is communicating with our LDAP server but if the log in fails nothing gets logged in our event viewer.


#15

Which in itself is surprising, as your echo() is in no-mans land between the end of your if() condition and the opening curly-brace of the commands to run if the condition evaluates as true. I'd have expected a parse error but I am not well up on how it deals with this kind of thing.

It suggests to me that the if() condition is not evaluating to true, because the execution flow is not getting inside the curly braces, the code is only executed for true.

if(authenticate($_POST['userLogin'],$_POST['userPassword']))

Have you changed the form to reflect this change in form variable names? Obviously the userLogin part has changed or your echo wouldn't.


#16

I just edited it now since I was wrong. It displays where i've put it now


#17

Yes, I was just elaborating on it and saw you'd changed it. There, it would work, and if it doesn't work inside the next if(), then that isn't coming back as true.


#18

Is the case mode of your ldap groups correct in both instances? I notice that one starts with a capital and the other does not.


#19

So that must mean that that specific IF statement isn't functioning correctly. I've changed all the variables in index.php and authenticate.php to be user and password instead of userLogin and userPassword everywhere.

Also, with the echo command being there now, the error message will now have 'Hello' before it. Does this mean that the strings are being put together somehow?

Also yes they are correct.


#20

No, it's just that the echo command displays "Hello", and then the error message displays. The point of the echo() was just to show where it is getting in the execution of the code, now you know it's getting to that point, but not inside the if(), you know where it's stopping. So now you can remove that first echo, and start figuring out which part of the authenticate() function is not working as you want it to.

// check to see if login form has been submitted
if(isset($_POST['userLogin'])){
    echo "Hello"; // *** GETS HERE 
	// run information through authenticator
	if(authenticate($_POST['userLogin'],$_POST['userPassword']))
	{
                // *** DOESN'T GET HERE
		// authentication passed
		header("Location: protected.php");
		die();
	} else {
		// authentication failed
		$error = 1;
	}
}

Therefore, problem is between "GETS HERE" and "DOESN'T GET HERE".