How to De-Authenticate a Windows Auth user with PHP

Go To StackoverFlow.com

2

If a user logged in to my site with windows auth, how do I log the person out so that they will have to be authenticated again? (this is with IIS)

For example the user logs in like this:

auth

Then the $_SERVER variable contains:

[REMOTE_ADDR] => 172.34.567.891
[REMOTE_HOST] => 172.34.567.891
[REMOTE_PORT] => 44601
[REMOTE_USER] => DOMAIN\username

And the user is not asked again for his username or password with windows auth unless the computer is restarted, or he uses a different browser.

How do I force the user to be authenticated again with PHP?


Update:

I found a way to do this, but it only works in chrome (all other browsers just throw a 401 unauthorized, even if the login is correct):

My code:

logout.php

    //clear session
    //then:
    $user = isset($_SESSION['userName']);
    $userNotSet = (!$user || (is_array($user) && count($user) == 0));


    if(!isset($_SESSION['401']) && $userNotSet) {
        $_SESSION['401'] = true;
        $realm = 'mysite';
        header('HTTP/1.1 401 Unauthorized');
        header('WWW-Authenticate: Digest realm="'.$realm.
           '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
        exit;
    }
    elseif($userNotSet) {
        header('HTTP/1.1 401 Unauthorized');
        list($domain, $user) = explode("\\", $_SERVER['REMOTE_USER']);
        $_SESSION['userName'] = $user;
        $_SESSION['LoggedIn'] = true;
    }
    else    {
        header('Location: '.WEBROOT.INDEX);
    }
    exit;

Why doesn't this work in any other browser aside from Chrome? Is there a cross-browser solution?

2012-04-03 19:26
by Neal
I assume the underlying principles are similar to standard HTTP authentication. It's not possible to log-out programmatically then. See HTTP authentication logout via PHP - hakre 2012-04-03 19:33
Why don't you get PHP to communicate directly with Active Directory or whatever is handling Windows Auth. and relay it to the user? That's what I did when I had a similar problem. This way PHP had total control over the user's session - NullUserException 2012-04-03 19:54
@NullUserException what did you do - Neal 2012-04-03 20:08
I worked in a company where all user authentication was handled by Active Directory, so you had one username and password combination for everything. I wrote an internal web application in PHP which used their AD for authentication, but the sessions themselves were managed by PHP - NullUserException 2012-04-03 20:15
@NullUserException is there any code you can show me, or is it all proprietary - Neal 2012-04-03 21:15
The communications with AD were largely handled by this opensource project: http://adldap.sourceforge.net - NullUserException 2012-04-03 21:20
@NullUserException see my update.. - Neal 2012-04-04 13:03
AD is just LDAP with extras, and most LDAP libraries can handle it - Greg Bair 2012-04-06 02:02
Which route through the if/elseif/else is the non-Chrome browser taking - Rob Allen 2012-04-11 14:25


1

If you are using PHP with HTTP Basic Auth, then there are two $_SERVER variables you need to be using and testing: $_SERVER['PHP_AUTH_USER'] & $_SERVER['PHP_AUTH_PW'].

To force the display of the browser's HTTP basic auth login dialog, you send a 401 header. It doesn't matter if the user is logged in or not, you can send the 401 header at any time to force the user to re-enter their credentials.

This code shows the basics:

<?php

// If the force_login request variable exists, then we want the user to
// re-enter their login details.
if (isset($_GET['force_login']) && $_GET['force_login'] == 1) {
    header('WWW-Authenticate: Basic realm="realm"'); 
    header('HTTP/1.0 401 Unauthorized'); 
    exit;
}

// Login process
if (!$_SERVER['PHP_AUTH_USER']) {
    // The browser has not supplied $_SERVER['PHP_AUTH_USER'], so we need 
    // the user to log in 
    header('WWW-Authenticate: Basic realm="realm"'); 
    header('HTTP/1.0 401 Unauthorized'); 
    exit;

} else {
    // Test that the username/password combination are correct
    $expectedUsername = 'test';
    $expectedPassword = '1234';
    if ($_SERVER['PHP_AUTH_USER'] != $expectedUsername 
            && $_SERVER['PHP_AUTH_PW'] != $expectedPassword ) { 
        // not valid username/password - try again!
        header('WWW-Authenticate: Basic realm="realm"'); 
        header('HTTP/1.0 401 Unauthorized'); 
        exit;
    }
} 
// End login process


// The user is logged in here. we can display the page content
echo '<a href="?force_login=1">Force login</a>';

(As a side note, if you're using HTTP basic auth, ensure you're using SSL too!)

2012-04-11 06:02
by Rob Allen
+1 for the note about using SSL with HTTP basic auth. (HTTP basic auth sends the user name and password in clear text) - ErJab 2012-04-11 06:04
@RobAllen -- I am using IIS Windows Based Authentication, will it still work then - Neal 2012-04-11 12:53
Hmm. I'm not sure. I've always managed authentication within my app. I think you don't need to worry about the PHP_AUTH Stuff and can simply send the 401 - Rob Allen 2012-04-11 14:21