I wrote a new auth module for authentication with remote IMAP servers. My hook_auth implementation returns TRUE but users can't login. Should I implement another hooks?

Any hint? This is the code:

 
...
 

/**
 * Implementation of hook_auth().
 */
function imapauth_auth($username, $password, $server) {
  
  //IMAP extension not loaded
  if (!function_exists('imap_open')) {
  	watchdog('php', t('IMAP extension not loaded. IMAP module couldn\'t be used to authenticate users.'), WATCHDOG_WARNING);
    return false;
  }

  if (variable_get('imapauth_enabled', 0) == 0) {
    return false;
  }
  
  $domains = split("/\r\n|\n|\r/", variable_get('imapauth_domains', array()));
 
  $valid = false;
  foreach ($domains as $d) {
    $domain_settings = split(",", $d, 2);
    
    if ((trim($domain_settings[0]) == $server) or trim($domain_settings[0]) == '*') {
      $valid = true;
      
      if (array_key_exists(1, $domain_settings)) {
        $mailbox = trim($domain_settings[1]);
      }
      else {
        $mailbox = "{" . $server . ":143}INBOX";
      }
    }
  }
  
  //This domain is not valid for IMAP authentication
  if (!$valid) {
      return false;
  }

  $mbox = @imap_open($mailbox, $username, $password);
  
  if ($mbox) {
		$minfo = @imap_mailboxmsginfo($mbox);
		
    if ($minfo) {
    	$login = true;
    }
    else {
    	$login = false;
    }
    @imap_close($mbox);
    

  } else {
  	$mbox = @imap_open($mailbox, $username . '@' . $server, $password);

    if ($mbox) {
  		$minfo = @imap_mailboxmsginfo($mbox);
		
      if ($minfo) {
      	$login = true;
      }
      else {
      	$login = false;
      }
      @imap_close($mbox);
    } 
    else {
    	$login = false;
    }
  }
  
  return $login;
}

...

/**
 * Implementation of hook_info().
 */

...

/**
 * Implementation of hook_settings().
 */

...

/**
 * Implementation of hook_help().
 */

...

Comments

rla’s picture

Are you sure your hook is getting executed? Try adding a watchdog to it and see if it's logged, ie; watchdog('user','imapauth test'); .

I'm trying to do something very similar, but my _auth hook never gets called. My _help and _info hooks do get called, but not _auth. The docs say to look a contributed jabber_auth module for implementation details, but I can't see to find it. I'll post here if I get any further.

yecarrillo’s picture

Yes, my watches report that _auth returns TRUE!, but users can't get logged in!.

naudefj’s picture

Try "return 1;" instead of "return true;".

Best regards.

Frank

yecarrillo’s picture

Just I tried this. It doesn't work. ...

yecarrillo’s picture

Solution to this enigma is very trivial.

Looking at user.module, line 878, you will see:

          if (variable_get('user_register', 1) == 1) {

This means that: to allow external user authentication you need change settings in "admin/user/configure"

"Public registrations:"
"Visitors can create accounts and no administrator approval is required."

Thats all! :-(

rla’s picture

Thanks for pointing this out. It lead me to a nearby bit of code that was preventing my auth module from calling the _auth hook. It only calls the _auth hook if there is a "@" in the username and a string (server) after this. I was trying to write a module to replace the local authentication and this was driving me nuts. Once I added the @server to the user id, it worked. Unfortunately, all my users will be from the same domain and I don't want them to have to type the domain part. Back to the drawing board. What I'd really like is to perform authentication against a LDAP server, auto-create the user if it doesn't already exist in Drupal, but does exist in LDAP and turn off all the local password stuff completely (no pw changes, recovery, etc).

naudefj’s picture

Same problem here - it is easy to write a module to authenticate remote users, but how does one authenticate local users?

Also, see my post at http://drupal.org/node/27959

Best regards.

Frank

moshe weitzman’s picture

you might like webserver_auth module in contrib

naudefj’s picture

What is the purpose of the "webserver_auth_webserver_auth" function in webserver_auth.module?

If I base a new module on it (say xxx.module), do I need to rename this function to xxx_webserver_auth or to xxx_xxx?

rla’s picture

Maybe IIS is different, but under Apache the REMOTE_USER environmental variable (which webserver_auth depends on) is not set unless the page you're viewing is restricted to authorized users only. There is no concept of optional authentication. How do you allow visitors to browse the site, but let your content editors log in?

A hack to solve this problem:

In .htaccess add:

<Files login.php>
 AuthType basic
 AuthName "Enter your username and password"
 require valid-user
</Files>

Create a new file "login.php":

<?
include_once 'includes/bootstrap.inc';
$_SESSION['userid'] = $_SERVER['REMOTE_USER'];
header("Location: index.php");
?>

And change webserver_auth.module line that says:

if ($name = $_SERVER["REMOTE_USER"]) {

to:

if ($name = $_SESSION['userid']) {

Add a block that has a link to login.php. Hide regular login block.

The login.php file is "protected" by .htaccess and has REMOTE_USER set, save value in a session variable. Read the session variable in the webserver_auth module and if set, use this value. Seems to work ok, but I'm sure someone can improve on this.