Skip to main content

HTTP authentication logout via PHP


What is the correct way to log out of HTTP authentication protected folder?



There are workarounds that can achieve this, but they are potentially dangerous because they can be buggy or don't work in certain situations / browsers. That is why I am looking for correct and clean solution.


Source: Tips4allCCNA FINAL EXAM

Comments

  1. Mu. No correct way exists, not even one that's consistent across browsers.

    This is a problem that comes from the HTTP specification (section 15.6):


    Existing HTTP clients and user agents typically retain authentication
    information indefinitely. HTTP/1.1. does not provide a method for a
    server to direct clients to discard these cached credentials.


    On the other hand, section 10.4.2 says:


    If the request already included Authorization credentials, then the 401
    response indicates that authorization has been refused for those
    credentials. If the 401 response contains the same challenge as the
    prior response, and the user agent has already attempted
    authentication at least once, then the user SHOULD be presented the
    entity that was given in the response, since that entity might
    include relevant diagnostic information.


    In other words, you may be able to show the login box again (as @Karsten says), but the browser doesn't have to honor your request - so don't depend on this (mis)feature too much.

    ReplyDelete
  2. Method that works nicely in Safari. Also works in Firefox and Opera, but with a warning.

    Location: http://logout@yourserver.example.com/


    This tells browser to open URL with new username, overriding previous one.

    ReplyDelete
  3. Workaround (not a clean, nice (or even working! see comments) solution):

    Disable his credentials one time.

    You can move your HTTP authentication logic to PHP by sending the appropriate headers (if not logged in):

    Header('WWW-Authenticate: Basic realm="protected area"');
    Header('HTTP/1.0 401 Unauthorized');


    And parsing the input with:

    $_SERVER['PHP_AUTH_USER'] // httpauth-user
    $_SERVER['PHP_AUTH_PW'] // httpauth-password


    So disabling his credentials one time should be trivial.

    ReplyDelete
  4. The simple answer is that you can't reliably log out of http-authentication.

    The long answer:
    Http-auth (like the rest of the HTTP spec) is meant to be stateless. So being "logged in" or "logged out" isn't really a concept that makes sense. The better way to see it is to ask, for each HTTP request (and remember a page load is usually multiple requests), "are you allowed to do what you're requesting?". The server sees each request as new and unrelated to any previous requests.

    Browsers have chosen to remember the credentials you tell them on the first 401, and re-send them without the user's explicit permission on subsequent requests. This is an attempt at giving the user the "logged in/logged out" model they expect, but it's purely a kludge. It's the browser that's simulating this persistence of state. The web server is completely unaware of it.

    So "logging out", in the context of http-auth is purely a simulation provided by the browser, and so outside the authority of the server.

    Yes, there are kludges. But they break RESTful-ness (if that's of value to you) and they are unreliable.

    If you absolutely require a logged-in/logged-out model for your site authentication, the best bet is a tracking cookie, with the persistence of state stored on the server in some manner (mysql, sqlite, flatfile, etc). This will require all requests to be evaluated, for instance, with PHP.

    ReplyDelete
  5. Typically, once a browser has asked the user for credentials and supplied them to a particular web site, it will continue to do so without further prompting. Unlike the various ways you can clear cookies on the client side, I don't know of a similar way to ask the browser to forget its supplied authentication credentials.

    ReplyDelete
  6. The best solution I found so far is (it is sort of pseudo-code, the $isLoggedIn is pseudo variable for http auth):

    At the time of "logout" just store some info to the session saying that user is actually logged out.

    function logout()
    {
    //$isLoggedIn = false; //This does not work (point of this question)
    $_SESSION['logout'] = true;
    }


    In the place where I check for authentication I expand the condition:

    function isLoggedIn()
    {
    return $isLoggedIn && !$_SESSION['logout'];
    }


    Session is somewhat linked to the state of http authentication so user stays logged out as long as he keeps the browser open and as long as http authentication persists in the browser.

    ReplyDelete
  7. My solution tu the problem is the following. You can find the function http_digest_parse , $realm and $users definitionin the second example of this page: http://php.net/manual/en/features.http-auth.php.

    session_start();

    function LogOut() {
    session_destroy();
    session_unset($_SESSION['session_id']);
    session_unset($_SESSION['logged']);

    header("Location: /", TRUE, 301);
    }

    function Login(){

    global $realm;

    if (empty($_SESSION['session_id'])) {
    session_regenerate_id();
    $_SESSION['session_id'] = session_id();
    }

    if (!IsAuthenticated()) {
    header('HTTP/1.1 401 Unauthorized');
    header('WWW-Authenticate: Digest realm="'.$realm.
    '",qop="auth",nonce="'.$_SESSION['session_id'].'",opaque="'.md5($realm).'"');
    $_SESSION['logged'] = False;
    die('Accesso Negato.');
    }
    $_SESSION['logged'] = True;
    }

    function IsAuthenticated(){
    global $realm;
    global $users;


    if (empty($_SERVER['PHP_AUTH_DIGEST']))
    return False;

    // check PHP_AUTH_DIGEST
    if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
    !isset($users[$data['username']]))
    return False;// invalid username


    $A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
    $A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);

    // Give session id instead of data['nonce']
    $valid_response = md5($A1.':'.$_SESSION['session_id'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);

    if ($data['response'] != $valid_response)
    return False;

    return True;
    }

    ReplyDelete
  8. AFAIK, there's no clean way to implement a "logout" function when using htaccess (i.e. HTTP-based) authentication.

    This is because such authentication uses the HTTP error code '401' to tell the browser that credentials are required, at which point the browser prompts the user for the details. From then on, until the browser is closed, it will always send the credentials without further prompting.

    ReplyDelete
  9. I needed to reset .htaccess authorization so I used this:

    <?php
    if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="My Realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Text to send if user hits Cancel button';
    exit;
    }
    ?>


    Found it here :
    http://php.net/manual/en/features.http-auth.php

    Go figure.

    A number of solutions reside on that page and it even notes at the bottom: Lynx, doesn't clear the auth like other browsers ;)

    I tested it out on my installed browsers and once closed, each browser seems like it consistently requires reauth on reentry.

    ReplyDelete
  10. While the others are correct in saying that its impossible to logout from basic http authentication there are ways to implement authentication which behave similarly. One obvious appeoach is to use auth_memcookie. If you really want to implement Basic HTTP authentication (i.e. use the browser dialogs for logging in trather than an HTTP form) using this - just set the authentication to a seperate .htaccess protected directory containing a PHP script which redirects back where te user came after createing the memcache session.

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex