By ccamporeale on
I am currently developing an external login module for Drupal. This module replaces the user login block/page and allows authentication against an external source.
My current module (see below), is intentionally hard-coded to permit all users for testing purposes. This code is a conglomerate of examples and tests.
The code does not seem to "take over" the user login routine, and users are not being authenticated as expected.
Any advice or suggestions would be appreciated.
I know that there are many examples and explanations of similar problems; perhaps it is my lack of understanding the Drupal User auth API.
/**
* Implementation of hook_help().
*/
function fbauth_auth_help( $path, $arg )
{
switch ( $path )
{
case 'admin/help#fbauth_auth':
{
return( '<p>' . t('This module allows users who login with e-mail addresses to authenticate off of external.') . '</p>' );
}
}
}
/**
* Implementation of hook_form_alter().
*
* Change the normal form login form behaviour.
*/
function fbauth_auth_form_user_login_alter( &$form, $form_state )
{
unset($form['links']);
$form['#validate'] = array( 'user_login_name_validate', 'fbauth_auth_login_validate', 'user_login_final_validate' );
}
function fbauth_auth_form_user_login_block_alter( &$form, $form_state )
{
return fbauth_auth_form_user_login_alter( $form, $form_state );
}
/**
* The custom_auth_auth() function attempts to authenticate a user off the external system using their e-mail address.
*/
function fbauth_auth_login_validate( $form, &$form_state )
{
$username = $form_state['values']['name'];
// In our case we're assuming that any username with an '@' sign is an e-mail address, hence we're going to check the credentials against our external system.
if ( strpos( $username, '@' ) !== false )
{
// Look for user in external database
if ( externalUserExists( $username ))
{
// Looks like we found them - now we need to check if the password is correct
if ( externalUserValidPassword( $username, $form_state['values']['pass'] )
{
user_external_login_register( $username, 'custom_auth' );
user_authenticate_finalize( $form_state['values'] );
} // else drop through to the end and return nothing - Drupal will handle the rejection for us
}
}
else
{
// Username is not an e-mail address, so use standard Drupal authentication function
user_login_authenticate_validate( $form, &$form_state );
}
}
/**
* The custom_auth_user() function gets called by Drupal after a new user has been added. If the e-mail address has
* already been set then we don't want to overwrite it, as the user is probably being added manually. Thankfully
* the only time a user can be added without the e-mail being set is when custom_auth_auth() gets run for a first-time
* user, at which point a user is inserted without an e-mail address. That is the case we're dealing with in this
* function.
*/
function fbauth_auth_user( $op, &$edit, &$account, $category = null )
{
switch( $op )
{
case( 'insert' ): // This hook is called during the registration process, AFTER the new user has been added to the users table but BEFORE the roles are written to the users_roles table
{
if ( empty( $account->mail ))
{
db_query("UPDATE {users} SET mail = '%s' WHERE uid = %d", $account->name, $account->uid);
}
// Note: you can do other stuff here, like set the password to be the md5 hash of the remote password. This might be handy if you wanted to allow people to log on when the external system is unavailable, but, of course, it introduces the hassle of keeping the passwords in sync.
// This is where we set that additional role to indicate that the user is authenticated externally. Note that EXTERNAL_AUTH_RID is undefined in this sample code but would normally be set to whatever Role ID is in the database. (So that is, create the new role, do a query to find the RID for that role and set EXTERNAL_AUTH_RID to that RID. Or just hard code it in the following line.)
$edit['roles'][EXTERNAL_AUTH_RID] = 'external_auth';
return;
}
case( 'update' ): // This hook is called BEFORE the record in the database (or $account) has been updated
{
if ( strpos( $account->name, '@' ) !== false )
{
// If the user is identified by their e-mail address and they are trying to change their e-mail address, don't let them.
if ( strcmp( $account->mail, $edit['mail'] ))
{
unset( $edit['mail']);
drupal_set_message( 'Sorry, users who use their e-mail address to login cannot change their e-mail address.', 'error' );
}
// If the user is identified by their e-mail address and they are trying to change their password, don't let them.
if ( $edit['pass'] != '' )
{
unset( $edit['pass']);
drupal_set_message( 'Please access the external system to change your password.', 'error' );
}
}
return;
}
}
}
function externalUserExists( $username )
{
return true;
}
function externalUserValidPassword( $username, $password )
{
return true;
}
Comments
=-=
posts aren't deleted unless they are spam. Please don't blank out your post with a note to be deleted. Thanks.