LDAP Authentication done differently

Hi Guys,


I have an ugly hack that I'm going to share with you because it does something that we really want here at UC and because I want to talk about getting it implemented neatly.



Inside user.inc I've modified comparePassword() so that if it finds a username of the form s123456 (which is our standard network login) it doesn't look at the password stored in the database but instead authenticates the entered password against LDAP. Code is attached at the bottom.



This means that we can create normal users and backend users as normal in Matrix and just have their password stored in the LDAP system. It means that we can create groups of users and assign them different types of backend priviledges which is something we couldn't do easily in the LDAP bridge.



Ideally I would like a custom asset extending the user asset which does this so that there is no ugly hack depending on the username. Personally I'm unsure how to start with that. And this method can be extended to authenticating against any other password mechanism. You can just have different user types for different authentication methods.



Here's the code. Tell me your thoughts. Oh of course the hardwired variables need to be moved elsewhere.



function comparePassword($entered_password)

{

$password = $this->attr('password');

$uid = $this->attr('username');

if (preg_match("/s[0-9][0-9][0-9][0-9][0-9][0-9]/", $uid))

{

//print("Username is an LDAP username\n");

$ldap_server = "ldap.canberra.edu.au";

$ldap_port = "7654";



// Set the base dn to search the entire directory.



$base_dn = "o=University of Canberra,c=AU";



// connect to server

if (!($connect=ldap_connect($ldap_server, $ldap_port))) {

print ldap_error( $connect );

die("Could not connect to ldap server");

}



// Anonymous bind

if (!($anon=ldap_bind($connect))) {

print ldap_error( $connect );

die("Could not anonymous bind to ldap server");

}

// Search for entry for user id

$search_results = ldap_search($connect, $base_dn, "uid=".$uid);



$info = ldap_get_entries($connect, $search_results);

$dn=$info[0]["dn"];



// check bind to server using full dn and hence test password



if (!($bind=@ldap_bind($connect, $dn, $entered_password))) {

return 0;

// print ldap_error( $connect );

// die("Unable to bind to server with $uid($dn) and $entered_password");

}

//print ("Success");

return 1;

}

else

{

if (!trim($password)) {

return false;

}



return (crypt($entered_password,$password) == $password);

}

}//end comparePassword()

You can already do this with the LDAP bridge, by reordering the Authentication schemes in the Asset Map. If you place the LDAP bridge higher than the Default Authentication, LDAP gets checked first.


Then, you use LDAP groups (instead of Matrix groups) to assign permissions. Groups in LDAP appear as groups and have the same abilities (i.e. you can assign permissions and security restrictions). Its true that you can't place LDAP users into Matrix groups, which is why you just use LDAP groups instead.

And as a side note, if this couldn't be done or you really needed the normal Matrix groups, creating a new authentication system that extends the LDAP authentication system would probably be an option. You could check the password from LDAP and then ensure that the user also exists in the Matrix DB (which LDAP does not do).


Essentially, you'd use the bridge to create that link between Matrix and LDAP and then get your authentication system to use the bridge linked to it to connect to the LDAP directory (saving the hard-coded LDAP vars).