Custom Authentication with Drupal 7

Was looking into Drupal 7 yesterday. One of my requirements would be to use my own authentication system.

The problem with Drupal, which seems to be a great piece of software, with generally good documentation is all the damn different versions. Most of the sample code I found on this topic was for Drupal 6.x or 5.x, and it is slightly difficult to figure out what goes where.

In the end, I resorted to doing what I dislike and reading the code to learn how it works. Reminds me of Rails ;-)

Here’s how I did it, this is very rough code.

Create a folder in the module directory.  Create a file of the same name, with a .info extension, in my case geospike.info:

name = geospike
description = Authenticates with Geospike.com
package = Other
core = 7.x

Create another file with the same name, but .module, in my case geospike.module.

<?php

function geospike_form_user_login_block_alter(&$form, &$form_state) {
	_geospike_user_login_form_alter($form, $form_state);
}

function geospike_form_user_login_alter(&$form, &$form_state) {
	_geospike_user_login_form_alter($form, $form_state);
}

function _geospike_user_login_form_alter(&$form, &$form_state) {
	$saveForm = $form;

	$form = array();
	
	// overrides the default validator
	foreach( $saveForm as $key => $value ) {
		if( $key == '#validate' ) {

			$form[ $key ] = array();
			foreach( $value as $validator ) {
				if( $validator == 'user_login_authenticate_validate' ) {
					$validator = 'geospike_authenticate_validate';
				}
				$form[ $key ][] = $validator;
			}
		} else {
			$form[ $key ] = $value;
		}
	}
}

function geospike_authenticate_validate( $form, &$form_state ) {

	$name = $form_state[ 'values' ][ 'name' ];
	$pass = $form_state[ 'values' ][ 'pass' ];

	// use Drupal authentication for this user
	if ($name == 'your_admin_username')
	{
		return user_login_authenticate_validate($form, $form_state);
	}
	
	$authenticated = your_awesome_authentication_method($name, $pass)
	
	if ($authenticated)
	{
		// this sets up the external user with Drupal by creating a local entry. If they don't exist they are added
		user_external_login_register($name, "geospike");
		
		// we must set the 'uid' to pass back.  this looks up the logged in user and sets the Drupal UID
		$account = user_external_load($name);
	    $form_state['uid'] = $account->uid;
	}
	else
	{
		// do nothing, Drupal will handle the errors
		
	}
}

Obviously you need to implement your_awesome_authentication_method.

I boiled that code down from the tutorial found here p2 p3

With 7.0, you may get a PHP warning which you have to patch Drupal to fix.

 

Now… if you want to remove the registration and password recovery forms (as I did), one approach is to create a “sub-theme” to override these forms with whatever info you like.

From the docs (note that in that example, for Drupal 7, ‘user_register’ should be ‘user_register_form’, that’s a bug).

Creating a geospike folder in the themes directory with the file geospike.info:

name = Geospike
core = 7.x
engine = phptemplate
base theme = bartik
stylesheets[all][] = geospike.css

And in template.php, specifying the forms to override.

<?php
/**
* Registers overrides for various functions.
*
* In this case, overrides three user functions
*/
function geospike_theme() {
	// get these form value names user.module:user_menu

  return array(
    // 'user_login' => array(
    //   'template' => 'user-login',
    //   'arguments' => array('form' => NULL),
    // ),
    'user_register_form' => array(
      'template' => 'user-register',
      'arguments' => array('form' => NULL),
    ),
    'user_pass' => array(
      'template' => 'user-pass',
      'arguments' => array('form' => NULL),
    ),
  );
}

// function geospike_preprocess_user_login(&$variables) {
//   $variables['intro_text'] = t('This is my awesome login form');
//  // $variables['rendered'] = drupal_render($variables['form']);
// }

function geospike_preprocess_user_register(&$variables) {
  $variables['intro_text'] = t('This is my super awesome reg form');
  $variables['rendered'] = drupal_render($variables['form']);
}

function geospike_preprocess_user_pass(&$variables) {
  $variables['intro_text'] = t('This is my super awesome insane password form');
  //$variables['rendered'] = drupal_render($variables['form']);
}

?>

Finally, create files to match your ‘template’ specifications above, so user-register.tpl.php and user-pass.tpl.php. Put whatever you want there!

And vola! Custom authentication, and new users are redirected anywhere I like.

After all this, I’m not sure if I’m going to go with Drupal. Seems like a pretty amazing and extensible system. But the problem with being jack of all trades, is that you’re not generally the best at any of them.


11 comments on “Custom Authentication with Drupal 7

  1. Drupal can be great at anything you want to use it for. It can be a simple CMS to a development platform. There are a lot of good API’s and you can pick and choose whatever you want to use.

  2. In my opinion it is a jack of all trades. Good at everything, but not truly great at anything. For example, the forum modules are very lacking when compared to something like phpBB, and the Wiki modules when compared to MediaWiki.

    Great piece of software, and I’m sure you can customise it a lot. But if you’re looking for a turnkey Wiki + Blog + Forum, then I recommend MediaWiki + phpBB + WordPress. YMMV I guess ;)

  3. Certainly there are advantages to all those software in terms of being a turnkey solution. However, if you need to do any customization, you are learning how to customize three different software solutions. Imagine if you had to integrate all those solutions Active Directory or Shiboleth, or ADFS 2.

    There are several forum solutions for Drupal, but the built in solution leaves a lot to be desired.

    Your article on authentication is great. I have found it very useful and it helped me to jump start my custom authentication.

    Thanks,

    Randall

  4. Hi Randall,

    Glad it helped :)

    There were a few factors that went into my decision, one was that I already had some data & working MediaWiki/phpBB installs, so in the end it was easier to actually integrate them into my authentication system, than try to move everything over to Drupal.  I completely respect that Drupal is a great framework and you can do a lot with it, but I really found the forum modules quite lacking, even “advanced forum”, they promise a lot, but under-deliver. I would definitely consider Drupal again for a new project, but for this one it simply didn’t make sense.

    Best of luck with everything!

    Cheers,
    Will

  5. This worked a treat for me – I am looking to migrate a website to Drupal (or similar) and this will enable me to do it in stages.

    I am not sold on the drupal way of coding – would like some sort of class structure so the code is less Drupal specific, but will give it a shot.

  6. I’m a noob at the module development aspect of Drupal. What’s a working example of:

    $authenticated = your_awesome_authentication_method($name, $pass)

  7. Pingback: User anonymity while using user_external_login_register()? | Q&A System

  8. thanks for your post. i am newbie to drupal and have a requirement to allow external database users into my drupal portal.I followed your approch and done succesfull login.

    I have a query is it possible to authenticate users with out inserting data into my drupal table.

  9. Hi Will,
    Thanks a lot for this tutorial. The links provided after geospike module (“I boiled that code down from the tutorial found here p2 p3) appear to be broken. Could you please update the links. This information will be really useful to me.

    Thanks,
    RJ

  10. Looks like that site has gone. I don’t have updated links for you I’m afraid, but my code was distilled from that tutorial, perhaps you can use my code directly and adapt it for your needs.

  11. how can i provide the custom form for login authentication where user can enter email and password which is belong to another website and authenticate using REST API and after that user login on drupal website. If user exist on drupal website then simply login otherwise create new user with parameter information which is send by WEB API response