When an externally authenticated user logs in for the first time, they get registered locally, but do not have to enter an email address. If they edit their profile, they will be forced to enter one (as it's a required field), but if they never do that, then it will be left blank. This can lead to at least two issues:

  • Modules such as contact.module which expect to be able to send mail to users can fail; contact.module in particular doesn't actually check to see if the recipient's email is present, it will attempt to send mail to the empty string (though it does check that the sender's email is valid).
  • There's no way for an external user with a blank email to go through the password recovery process. This might seem an unlikely thing to be doing, but consider what will happen if the user's server for external authentication has vanished from the face of the net - if they have entered an email address in their profile, they can use the password recovery process and they will be emailed a randomly generated password as usual, and this will allow them to log in without using the external authentication server (since the user_authenticate function checks the local pass field for all users, externally authed or not, before trying external auth modules). On a related note, external users get given a random password as their 'local' password by default when they are registered, which seems bizarre.. maybe their password should be null by default?

I've not looked in great depth, but there are a number of places in various parts of the Drupal core and contributed modules that use the user's email address field without validating that it is non-blank or plausible - this is an assumption that just cannot be made if any external authentication modules are in use.

I'm not sure what the best way to solve this would be; adding a way for external authentication modules to return an email address might be a good start - drupal.module can presumably do this fairly easily. Perhaps external users should be required to enter an email address the first time they log in, if the auth module doesn't return one?

The alternative would seem to be to check that emails are valid in all places where they are used...

Comments

killes@www.drop.org’s picture

Version: 4.6.0 » x.y.z

Thanks for the detailed report . Drupal's remote authentication method is a bit dated, IMNSHO. I doubt it will be changed much. Modules that expect mail addresses to be present should probably be fixed to do a check and/or the remote users be reminded to update their user info. Anybody wantes to send a patch?

magico’s picture

There are several modules to allow diferent kinds of authentication, but what is the situation about core remote authentication?

Bèr Kessels’s picture

Version: x.y.z » 6.x-dev

This bug could use a bit more attention. With Drupals (Dries') intention to get openId integrated in core, this needs to be solved soon.

James_Gordon’s picture

Here is a potential work-around that some folks might find useful until such time as the external authentication hooks are enhanced.

The scenario that my work-around addresses is this:

  • I needed to build a custom auth module to authenticate Drupal users against a pre-existing application database. Of course, the current auth hook doesn't provide a facility to pass back the e-mail address to the user module such that the user module automatically adds the correct e-mail address when adding the user.
  • Somewhat conveniently, users in my other application are identified by their e-mail addresses, so all that needs to be done is to duplicate the username field into the e-mail address field.

My authentication module is fairly simple. The first function looks after the external authentication (making sure the user has entered a user ID that includes a domain name) and the second function updates the e-mail address which, in this scenario, I can simply copy from the username. From reading the code in the user module (and the doco) I have found (in Drupal 5.1 anyway) that the user hook below is called AFTER the user has been inserted into the database. By only overwriting the e-mail address when it is blank we get the added benefit that locally added users (who, in all probability, will have a different username to their e-mail address) do NOT get their e-mail address overwritten by the user hook.

function myauth_auth($username, $password, $server)
{
    if ( empty( $server ))
    {
        return false;
    }
    
    $username .= '@' . $server; // $username = e-mail address

    $result = callExternalAPI($username, $password); // <-- Insert a call to some function to do the remote authentication (returns true or false)
    
    return $result;
}

function myauth_user( $op, &$edit, &$account, $category = null )
{
    if ( $op == 'insert' && empty( $account->mail )) // Checking if the e-mail address is empty avoids overwriting it for locally created users
    {
        db_query("UPDATE {users} SET mail = '%s' WHERE uid = %d", $account->name, $account->uid);
    }
}

Please note that the callExternalAPI() function above is simply a placeholder - you should obviously implement your own method, based on whatever design suits your architecture and your security requirements.

There are other use cases that this solution obviously doesn't address, like how to keep the credentials in sync between the two databases, but this is a start at least.

Hopefully this fairly straightforward solution will get a few people up and running with what I believe would be a fairly common integration scenario.

- James.

baturin’s picture

5.x version seems to have this issue too. This is really disappointing :(. Our LDAP has no e-mails filled on regular basis (really not at all). I thought initially that "OK, I will do the LDAP auth and everything will be fine", but didn't find any ways to require a users to specify their e-mail after they have login...
Any hacks against this issue?
Thanks a lot in advance!

moshe weitzman’s picture

Status: Active » Closed (works as designed)