NTLM authentication

Hi All!

This is my first post here; actually, I’ve been developing my first Yii project since several weeks. Until now, I’ve had no problems in finding responses to my dubts using past posts and wiki articles, but this one seems a little more hard. If I’m asking something obviuos, please feel free to RTFMing me in the right direction ;^)

The scenario is this: I’m using PHP coupled with IIS 6.0 as a ISAPI module. If I configure IIS to require authentication in default web site properties, it asks the user to provide valid active directory credentials before first request; for IE users this happen automatically, since the browser sends the credentials of the logged user, while non-MS browsers users will se a pop-up similar to the one used for classical 401-header basic auth. Once the user has provided them, request is served.

From the PHP side, this translates in having the following server variables populated:

_SERVER[“AUTH_TYPE”]=‘NTLM’

_SERVER[“AUTH_USER”]=‘AD_DOMAIN\username’

What I’m trying to do is using this values as seed for a UserIdentity. Actually, I’ve already implemented an ldap auth method for UserIdentity that check validity of the username/pwd couple against the domain controller, but this is not satisfactory cause it forces users to input 2 times the credentials if they use a non-MS browser; moreover, it is redundant to use a login form for asking something that I already know (i.e. a validated username).

I would like to automatize login process so it happens without user intervention, still keeping changes to "Yii way" of auth at the minimum.

First try was to write something like




if ($_SERVER['AUTH_TYPE']=='NTLM' && is_string($_SERVER['AUTH_USER'])) {

        	return true;

        }



in a custom authenticate() UserIdentity method; but of course this is never called unless a login controller action is implemented.

So I need to create an automatic action some way. I’ve looked at how autologin works; but that method reads User values from a cookie, giving for granted that they are already been written there before. If I have a user that comes for the first time, I will have to read them from a DB, so I need to call an authenticate method.

So now I’m thinking if maybe overriding Cwebapplication’s init() method or adding a OnBeforeRequest handler could be better ways, but I’m a little confused on how to do that. If someone more experienced on Yii could share some hint, I’ll be extremely grateful!

Bye,

Fabrizio

Hmm… perhaps I’m not being clear enough? Is there really no one that can give some hints on how to implement an automatic pre-authentication? :(

Thanks in advance,

Fabrizio

Check out adLDAP (http://adldap.sourceforge.net/). I did a really interesting access control with it.

Hope this helps…

Good luck,

Caetano

Thanks for the hint, Caetano. Actually I do know adLDAP, but it’s not useful; it’s not the LDAP part that bothers me, I already have a simple LDAP auth functioning. But since IIS already does auth on itself, what I’m trying to do is “binding” IIS integrated auth with Yii’s auth. Now I’m trying to use a behavior following this hint to implement it.

I’ve modified my application config adding this:




	// behavior added to implement automatic login 

	

	'behaviors'=>array(

		'AutoNTLMLogin'=>array(

			'class' => 'application.components.AutoNTLMLogin'

		)

	),



the class works more or less like this (here I’m simplifing the real one that has more checks, logging, auditing, etc.):




class AutoNTLMLogin extends CBehavior {


	public function attach($owner) {

		$owner->attachEventHandler('onBeginRequest', array($this, 'handleBeginRequest'));

	}


	public function handleBeginRequest($event) {

		if(user()->isGuest) {   

			$this->ntlm_authenticate();

		}

	}


	private function ntlm_authenticate() {


		if ($_SERVER['AUTH_TYPE']==='NTLM' && is_string($_SERVER['AUTH_USER'])) {


					$ui = new UserIdentity($_SERVER['AUTH_USER'], '');

					$ui->preauth();

					user()->login($ui);

				}

                }



the preauth() method extract additional infos about the user from a local DB table and authenticates the UserIdentity.

All of this works up until the user()->login call, that generates an error of multiple headers sent. I’ve checked my code and it doesn’t seem like it’s me printing whitespace or the like: it appears that the error is caused by the fact that in this way i’m sending session headers two times in the same request.

I suppose this is because login() function assumes NOT being called within the very first application request.

Next step, I’ll try to reverse-engineer login() call and doing the same things without resending headers. But I’m not very happy with this solution, I feel it is too “hackish”. I would prefer to make it with standard Yii methods.

Bye,

Fabrizio