downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | conferences | my php.net

search for in the

Voting

Please answer this simple SPAM challenge: min(nine, five)?
(Example: nine)

The Note You're Voting On

meint at meint dot net
3 years ago
The definitive "logout" solution for Basic Authentication

As asserted by many on this page "Basic Authentication" has nog "logout" feature. There is however a standards based method (RFC2617) by which you can make the basic authentication session unique and therefore can emulate a log out function. This function works in all situations and across all browsers which is not the case for most solutions on this page.

The RFC2617 HTTP Authentication standard states that two elements determine the protection space:
- realm, a self chosen, server provided string identifier
- abs_path (i.e. the url)

By making both elements unique and changing them at the log out you will break (and "logout") the basic authentication.

The solution requires the use of mod_rewrite to direct traffic for non-existent resources to the index.php file. Please place a .htaccess file with the following contents in the folder that you wish to protect:

.htaccess:
RewriteEngine On
RewriteCond %{REQUEST_URI} !^$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [NC,L]

Please place an index.php file in the same folder (/auth in this example) with the following content:
<?php

session_start
();

if (empty(
$_SESSION['session_id'])) {
   
session_regenerate_id();
   
$_SESSION['session_id'] = session_id();
   
header("Location: /auth/" . $_SESSION['session_id'] . "/", TRUE, 301);
}

$url_action = (empty($_REQUEST['action'])) ? 'HomePage' : $_REQUEST['action'];
if (isset(
$url_action)) {   
    if (
is_callable($url_action)) {
       
call_user_func($url_action);
    } else {
        print
'Function does not exist, request terminated';
    }
}

function
HomePage() {   
    print
'<h1>Homepage</h1>';
    print
'<p><a href="?action=LogIn">LogIn</a></p>';
    print
'<p><a href="?action=LogOut">LogOut</a></p>';
    print
'<p><a href="?action=SecureContent">Secure Content</a></p>';
}

function
LogIn($url='') {
   
$session_id = $_SESSION['session_id'];
    while (!
IsAuthenticated()) {
       
header('WWW-Authenticate: Basic realm="' . $session_id . '"');
       
header('HTTP/1.1 401 Unauthorized');
        die(
'Authorization Required');
    }
    if (!empty(
$url)) {
        return
TRUE;
    } else {
       
header("Location: /auth/" . $_SESSION['session_id'] . "/", TRUE, 301);   
    }
}   

function
LogOut() {
   
session_destroy();
   
session_unset($_SESSION['session_id']);
   
header("Location: /auth/", TRUE, 301);   
}

function
SecureContent() {
    if (
LogIn("SecureContent")) {
        print
'<h1>Secure Content</h1>';
        print
'<p>This is secure content</p>';
        print
'<p><a href="/auth/' . $_SESSION['session_id'] . '/?action=HomePage">Home Page</a></p>';
    } else {
        print
'<h1>Not Authorized</h1>';
    }
}

function
IsAuthenticated() {
    if (isset(
$_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
       
$httpd_username = filter_var($_SERVER['PHP_AUTH_USER'], FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
       
$httpd_password = filter_var($_SERVER['PHP_AUTH_PW'], FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_HIGH|FILTER_FLAG_ENCODE_LOW);
        if (
$httpd_username == "test" && $httpd_password == "test") {
            return
TRUE;
        } else {
            return
FALSE;
        }
    }
    return
FALSE;
}

?>

Both files need to be put in a folder named /auth for these examples to work. You can change the folder name in the index.php example to suit your own environment.

A the start of the script a unique id is generated through PHP session mechanism and this session id is inserted into the url (hence the requirement for mod_rewrite to catch these urls). A redirect takes place to this new url and the homepage is shown. If you click on login a 401 header is generated using a realm that uses the same session id. If you click logout the current session id is destroyed and you are redirected to the start of the script where a new session id is generated. If you click on a protected item without a login the login function is called.

<< Back to user notes page

 
show source | credits | stats | sitemap | contact | advertising | mirror sites