I have a use case where the users $account->name needs to be different to the name users type into the login form. Instead the $account->name is to correspond with an attribute from the users ldap record. Further, the user accounts will be provisioned in Drupal by a system that only knows this attribute and doesn't know the users login ID.

I think this might be a common requirement in corporate environments where it is seen as bad practice for a users login id to be used as an account name.

My proposed solution is to set the Persistent and Unique User Attribute field in the LDAP Server configuration to the name of the ldap attribute to be used as the account name. When a user first logs in using LDAP if this unique_persistent_attr setting exists, this attribute is retrieved from the ldap record and used instead of the login id, to associate an existing account or to provision a new account with that value as the account name. The users login id is stored in the authname field of the authmap entry. And this can be used instead of account name when doing ldap searches for the user.

The small changes I had to make to get this working are in the attached patch file. It has not been heavily tested yet but I'd like some feedback on the solution.

CommentFileSizeAuthor
#5 ldap-account_name_attr.patch12.07 KBjzornig
ldap-upa.patch5.18 KBjzornig

Comments

johnbarclay’s picture

I agree with the goal: keep usernames out of use when security policy dictates it.

What if the UserName attribute field in admin/config/people/ldap/servers/edit/ were allowed to take tokens as the "Email template" field does? This would take care of the derivation of the username.

The initial logon username part is fuzzy. unique_persistent_attr is often a big hex or int number or even a binary value. To get the user setup on initial login, there has to be a way to map the username they initially use to something queryable in ldap. I don't see a good way to do this except perhaps using email as a login. Email would only work if an "Email Template" was not configured. I don't like the idea of cross purposing unique_persistent_attr so it needs to be known by the user. Also keep in mind that the ldap user may never use ldap authentication to logon; they may simply be using ldap authorization or ldap profile so the link between a user and their ldap entry has to be deriveable even if they have never ldap authenticated.

jzornig’s picture

How about we replace the current UserName field in admin/config/people/ldap/servers/edit that is currently described as

UserName attribute: The attribute that holds the users' login name.

with two fields

AuthName attribute: The attribute that holds the users' login name.
AccountName attribute: The unique attribute used to identify the users' drupal account. (In many cases the same as AuthName)

In my usecase, not only is the AuthName different to the AccountName, but the security policy dictates the LDAP can only be anonymously queried using the AuthName and not the AccountName. This allows users to authenticate but prevents someone knowing only their AccountName from finding their DN or any other attributes from the LDAP.
In my case the AccountName is in fact an integer (persistent, unique and about 8 digits long). Users don't know this value and systems are not expected to display it. My drupal systems use the RealName module and LDAP Profile Mapping to get a, not necessarily unique, Display Name attribute from LDAP and use that in place of the AccountName in the site UI.

johnbarclay’s picture

Sounds good. This will just mean adding another fields and altering the UI directions a bit. I think AccountName attribute should default to AuthName if none is supplied. A patch would be appreciated as I'm working through some other issues now.

jzornig’s picture

I'll work on it.

jzornig’s picture

StatusFileSize
new12.07 KB

Here is my patch to add the account name attribute. If no account name attribute is set it defaults to using the auth name as the account name.

johnbarclay’s picture

Component: Code » SimpleTests
Category: feature » task
Status: Needs review » Needs work

Thanks. Appreciate the thoroughness of the patch. It broke one of the simpletests, but it the error was in the simpletest so it worked out well.

I committed everything to 7.x-1.x-dev except the following. Also note there is no test coverage for this. I'm leaving this open until they are added. If you want to add them, they should go in ldap_authentication/tests/ldap_authentication.test

-------------------
1. I didn't understand the need to remove this line.

ldap_authentication/ldap_authentication.inc

@@ -202,7 +205,6 @@
if ($detailed_watchdog_log) {
watchdog('ldap_authentication', '%username : Drupal User Account not found and configuration is set to not create new accounts.', $watchdog_tokens, WATCHDOG_DEBUG);
}
- return FALSE; // don't bother authenticating if account doesn't exists and account creation not allowed
}

--------------------
2. In the schema for account_name_attr, I changed not null to FALSE, so it doesn't become a required field on the form and the database.

'account_name_attr' => array(
'form' => array(
'fieldset' => 'users',
'#type' => 'textfield',
'#size' => 30,
'#title' => t('AccountName attribute'),
'#description' => t('The attribute that holds the unique account name. Defaults to the same as the AuthName attribute.'),
),
'schema' => array(
'type' => 'varchar',
'length' => 255,
'not null' => FALSE,
'default' => '',
),
),

--------------------------------
3. one of the simpletests threw a warning, so I added && isset($drupal_user->uid) to the condition:

function _ldap_servers_get_user_ldap_data($drupal_user, $sid) {

if (is_object($drupal_user) && isset($drupal_user->uid) && $authname = db_query("SELECT authname FROM {authmap} WHERE uid = :uid AND module = 'ldap_authentication'", array(':uid' => $drupal_user->uid))->fetchColumn()) {
$drupal_username = $authname;
}

jzornig’s picture

1. Because at that point we only know the authname and not the accountname so the account might exist but we won't know that until after the user authenticates against the ldap. If the accounts have been provisioned there will not be any authmap entries for them yet.

johnbarclay’s picture

got it. I committed that line to 7.x-1.x-dev.

jzornig’s picture

Many thanks, I'll try to test it today.

johnbarclay’s picture

Version: 7.x-1.x-dev » 7.x-2.x-dev
Component: SimpleTests » Code

I also committed this to 7.x-2.x-dev. I'm leaving as needs work, because I suspect the following may need addtional work and it needs to be tested in 7.x-2.x also. (7.x-2.x-dev is unfunctional now so can't be tested).

ldapServer->deriveUsernameFromLdapEntry()

johnbarclay’s picture

Title: Support $account->name being different to the users login id thru use of Persistent and Unique User Attribute » LDAP User: Support $account->name being different to the users login id thru use of Persistent and Unique User Attribute
Issue tags: +7.x-2.0 release blocker
johnbarclay’s picture