Jump to content

[SOLVED] LDAP Authentication


JD*

Recommended Posts

Hello all,

 

I'm trying to work with a flexible LDAP setup for logging in to alternate servers. I have the code working for logging in with an ID number, but I'm trying to get it working with a username. I have a set of code that shows me the LDAP attributes on my server, but so far I can't get the cn (as username) to work.

 

The following is the code that I'm using, hopefully it'll help:

 

$connect=ldap_connect($server) or die("Could not find server");
ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);
$bind = ldap_bind($connect, (is_numeric($username) ? "uid" : "cn")."=$username,$dn","$password");
if($bind == 1) { return 1; } else { return 0; }
ldap_unbind($connect);

 

Any help would be greatly appreciated.

Link to comment
Share on other sites

Right now the $dn variable is set to be static, so I'm not too worried about that, I'm more concerned with being able to use a user's name. I'm just not sure how to go about that.

 

As it stands, we're using OS X servers as our LDAP, so their name is "lastname, firstname", but their short name is their ID, so they can log into a computer using either, so I'd like to make it so that they can log into our website using either.

Link to comment
Share on other sites

well, your code would look something like this:

 

<?php
  $connect=ldap_connect($server) or die("Could not find server");
  ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);
  $name = 'lastname, firstname'; //This is set from your login form
  $sr=ldap_search($connect, $dn, 'cn='.$name,array());
  if(ldap_count_entries($connect,$sr) !== 1) die("Too many users match");
  $user_dn = ldap_get_dn($connect,ldap_first_entry($connect,$sr)) or die("Could not get users dn");
  return ldap_bind($connect, $dn, $password);
?>

Link to comment
Share on other sites

I have been messing with ldap authentication for the last couple of months (on and off) and this works as basic authentication:

 

<?php
session_start();


$ldap_host = "ZYX.com;  // domain name goes here eg: XYZ.com
$base_dn = "OU=basedn, DC=XYZ, DC=com"; // replace "basedn" with the lowest branch where your users are & XYZ with your domain
$_session['ldapname'] = $_GET['ldapname'];
$ldapname  = $_GET['ldapname']."@XYZ.com"; // domain name goes here: eg: @XYZ.com
$ldappass = $_GET['ldappass'];

if (!$ldappass) { ?>

Please login below with your windows/citrix username and password!
<form method="GET" action="<?php echo $PHP_SELF; ?>" name="login">
	<table>	
		<tr>
			<td>Username:</td>
			<td><input type="text" name="ldapname"></td>
			<td><a href=".." title="Click for help on this item"><strong>?</strong></td>
		</tr>
		<tr>
			<td>Password:</td>
			<td><input type="password" name="ldappass"></td>
			<td><a href=".." title="Click for help on this item"><strong>?</strong></td>
		</tr>
		<tr>
			<td colspan="2"><input type="submit" value="Login" name="submit"></td>
		</tr>
	</table>
</form>
<?php
} else {
	/*echo 'name: '.$ldapname;
	echo '<br />pass: '.$ldappass;*/

	$connect = ldap_connect( $ldap_host, $ldap_port)
			or exit(">>Could not connect to LDAP server<<");

	//for win2003
	ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);

	//for win2003
	ldap_set_option($connect, LDAP_OPT_REFERRALS, 0);

	$bind = ldap_bind($connect, $ldapname, $ldappass);

	if (!$bind) {
		echo 'Invalid username/password.... try again';
	} else {
		print $_session['ldapname'];
	}
}
?>

 

hope it helps

Link to comment
Share on other sites

I got it figured out, thanks to all of your suggestions.

 

What I do now is, when they submit their credentials, I do a search based on whatever it is they submit (ID Number OR Common Name). Then I pull their actual UID, unbind, and then rebind with the UID and password. This way, at one building where the UID is lastnamefirstinitial, and another where it's firstname.lastname and so on, I can use the same code and just toss in the proper DN.

 

Following is the function I made tot allow this:

 

function ldap_auth2($server=NULL, $username=NULL, $password=NULL, $dn=NULL)
{
	error_reporting(0); // Surpress the error message when an account fails to bind 
	$ds=ldap_connect($server);  // must be a valid LDAP server!
	ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); // Set our protocol or else this won't work
        // Search the server for user with the information they submitted
	if ($ds) {
	   $r=ldap_bind($ds);
	   $sr=ldap_search($ds,$dn, (is_numeric($username) ? "uidnumber=" : "cn=").$username );  
	}		
	$ldapResults = ldap_get_entries($ds, $sr);
	$username = "uid=".$ldapResults[0]['uid'][0]; // Get their UID
                ldap_unbind($ds) // close this connection 

	$connect=ldap_connect($server) or die("Could not find server");
	ldap_set_option($connect, LDAP_OPT_PROTOCOL_VERSION, 3);

	// The above is anonymous, but we can only guarantee access if they can rebind to the server with the uid and password.
	if(ldap_bind($connect, $username.",".$dn, $password) == 1) { return 1; } else { return 0; };
	ldap_unbind($connect); 
}

 

And then the item that calls the function works like this:

 

		case "Log In":
		//Do LDAP login	
		if(ldap_auth2('my.server.com', $_POST['username'], $_POST['password'], "cn=users,dc=my,dc=server,dc=com") ==1) {
			echo "You did it!";
		} else {
			echo "You didn't do it";
		}

 

Thanks guys!

 

Link to comment
Share on other sites

The only thing I would do in addition, is provide better error reporting (which you are probably going to get to eventually). Was the user not found? Was it a bad password? Are there more then one accounts with the same CN (which is possible)? Is the account locked (you can get this from the attributes of the entry)?

 

Otherwise, code looks good

Link to comment
Share on other sites

The only thing I would do in addition, is provide better error reporting (which you are probably going to get to eventually). Was the user not found? Was it a bad password? Are there more then one accounts with the same CN (which is possible)? Is the account locked (you can get this from the attributes of the entry)?

 

Otherwise, code looks good

 

Yeah, in my production version there is my error display function to help them figure out what went wrong.

 

In our future, as we transition from multiple login servers to one master, we'll be making it so that if a user logs in with their name and there is more than one user, we'll give them a list of names with IDs, which will then be used, with the password, to try and complete the bind.

 

I don't know that we've used account locking so far, but that is also something interesting to look into.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.