22

I'm trying to use Basic HTTP Authentication and followed the example on the PHP manual page. But it doesn't work for me. The variable $_SERVER['PHP_AUTH_USER'] doesn't seem to be set. When a user try to log in, the user is prompted whith a new login-dialog. The server is running PHP 5.3.3 and I have tried with Google Chrome and Internet Explorer.

Here is the simple example that I used:

<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="Jonas Realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'User pressed Cancel';
    exit;
} else {
    echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
    echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as you password.</p>";
}
?>

What is wrong? How can I use Basic HTTP Authentication in PHP?

Jonas
  • 121,568
  • 97
  • 310
  • 388
  • Rather than trying to do this with PHP, why don't you use the web server, eg http://httpd.apache.org/docs/2.2/howto/auth.html – Phil Nov 11 '10 at 00:52
  • 1
    @James: I think my web host uses Apache. – Jonas Nov 11 '10 at 00:53
  • 1
    @Phil: Then will my PHP code be denpendent of my web server, and I can't easyli change to another web server. I would like to follow the HTTP standard. – Jonas Nov 11 '10 at 00:54
  • 1
    Unauthorized is misspelled, first. Your example is shorter than the link you referenced. – James Black Nov 11 '10 at 00:57
  • @James: Thanks, but it didn't help. – Jonas Nov 11 '10 at 01:01
  • @Jonas Fair enough, it's just so easy using `htpasswd` :) – Phil Nov 11 '10 at 01:01
  • 1
    Have you read through the comments on the link you followed? There are suggestions for different web servers and several versions of the program, one of these may work better for your needs. For PHP I find the manual comments to be more useful than the description in the manual. – James Black Nov 11 '10 at 11:05

5 Answers5

19

Try this::

<?php
    /*
    ** Define a couple of functions for
    ** starting and ending an HTML document
    */
    function startPage()
    {
        print("<html>\n");
        print("<head>\n");
        print("<title>Listing 24-1</title>\n");
        print("</head>\n");
        print("<body>\n");
    }

    function endPage()
    {
        print("</body>\n");
        print("</html>\n");
    }
    /*
    ** test for username/password
    */
    if( ( isset($_SERVER['PHP_AUTH_USER'] ) && ( $_SERVER['PHP_AUTH_USER'] == "leon" ) ) AND
      ( isset($_SERVER['PHP_AUTH_PW'] ) && ( $_SERVER['PHP_AUTH_PW'] == "secret" )) )
    {
        startPage();

        print("You have logged in successfully!<br>\n");

        endPage();
    }
    else
    {
        //Send headers to cause a browser to request
        //username and password from user
        header("WWW-Authenticate: " .
            "Basic realm=\"Leon's Protected Area\"");
        header("HTTP/1.0 401 Unauthorized");

        //Show failure text, which browsers usually
        //show only after several failed attempts
        print("This page is protected by HTTP " .
            "Authentication.<br>\nUse <b>leon</b> " .
            "for the username, and <b>secret</b> " .
            "for the password.<br>\n");
    }
?>
MsO
  • 87
  • 1
  • 13
Mazhar Ahmed
  • 1,523
  • 2
  • 24
  • 41
13

For PHP-CGI:

in .htaccess add this:

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
</IfModule>

and at the beginning of your script add this:

list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(':' , base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
Teddy
  • 993
  • 10
  • 20
  • 1
    That `substr()` is suspicious. I would first break the string at the first space and make sure the type of authentication is indeed set to `Basic` (ignoring case). Then get the second part and decode it. – Alexis Wilke Aug 21 '17 at 21:02
  • How can I implement auto login? I have added above code but I am bit confused where to start in my application –  Oct 25 '18 at 04:24
11

How is PHP being run? If it's through Apache mod_cgi, I'm afraid you cannot get hold of the authentication information at all. Apache won't pass it to CGI apps unless you compile it with the SECURITY_HOLE_PASS_AUTHORIZATION flag. (Whether it's actually a security hole or not depends on whether other users on your server have a lower or greater privilege than your website users.)

If it's IIS CGI, you have to ensure that only ‘Anonymous’ directory access is configured, or IIS will try to step in and authenticate credentials itself.

echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";

HTML-injection security hole (well, if it worked). Use htmlspecialchars(). Man, is that PHP doc page full of highly questionable advice and code.

You can try to look at $_SERVER['HTTP_AUTHORIZATION'] as well, though I suspect it's the mod_cgi issue in which case neither variable will be present and you will have to resort to cookie-based login instead. Or change to a host with a more modern approach to PHP hosting, such as FastCGI or mod_php.

bobince
  • 528,062
  • 107
  • 651
  • 834
1

I think the PHP methods rely on Basic Authentication being configured on the Web Server. An easy way to do this is to include a .htaccess file in the directory you want to enable basic authentication for.

Most unix-based web hosts allow you to do this by just uploading this file. A separate file (call this .htauth) will hold the user logins that are allowed to access the site or directory.

Ken Richards
  • 2,937
  • 2
  • 20
  • 22
0

Check if you have overrided your variable $_SERVER[‘PHP_AUTH_USER’] and$_SERVER[‘PHP_AUTH_PW’] before the place where you are trying to access the both variables.

If above is not the case then chek if you are using php as cgi mod or not. IF you are using php as cgi mod then in the most of case you will not get $_SERVER[‘PHP_AUTH_USER’] and$_SERVER[‘PHP_AUTH_PW’] because generraly we do not compile the apache with option SECURITY_HOLE_PASS_AUTHORIZATION So if you want to get both variable then re-compile apache with option SECURITY_HOLE_PASS_AUTHORIZATION or you can use .htaccess approach.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343