Test HTTP Requests Tools Blog PHP Quiz API Log In With Github
Test HTTP Requests Tools Blog PHP Quiz API Log In With Github
« Return to the tutorials list
We have updated the website and our policies to make sure your privacy rights and security are respected.
Click here to learn more about the way our website handles your data.

Remove this message.

PHP - A primer on the Basic Authorization Header

Daniel Gheorghe Difficulty: 15 / 50 Tweet
markus-voetter-525896-unsplash

What is this about ...

HTTP basic authentication is a simple challenge and response mechanism with which a server can request authentication information (a user ID and password) from a client. The client passes the authentication information to the server in an Authorization header.

In various PHP projects that I've worked on, very often I have come across code that relies on using PHP's explode function to generate an array from a string based on a delimiter.

This is also the case for how many devs choose to parse the Basic Authorization header:

    <?php
        if (isset($_SERVER["HTTP_AUTHORIZATION"]) {
            $auth = $_SERVER["HTTP_AUTHORIZATION"];
            $auth_array = explode(" ", $auth);
            $un_pw = explode(":", base64_decode($auth_array[1]));
            $un = $un_pw[0];
            $pw = $un_pw[1];
        }

The code above might seem ok, and maybe with some additional user input validation it could work, but not in all cases.

Let's have a look at Symfony's approach to deal with this:

    <?php
        if (isset($_SERVER["HTTP_AUTHORIZATION"]) && 0 === stripos($_SERVER["HTTP_AUTHORIZATION"], 'basic ')) {
            $exploded = explode(':', base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)), 2);
            if (2 == \count($exploded)) {
                list($un, $pw) = $exploded;
            }
        }

Why is the second option better ?

First of all, it checks if the header passed really starts with the string Basic (case insensitive). Then, it uses explode to split the decoded credentials, but it passes along a less known third parameter:

Using explode(':', 'username:pass:123', 2) will generate an array of 2 elements: username and pass:123. This prevents the possibility of obtaining a shorter password string if it contains a colon(':').

Hey, but what about usernames with colons ...

According to the 'RFC 7617' usernames with a colon can not be used in an Authorization header.

Here's the relevant portion from the RFC:

... Furthermore, a user-id containing a colon character is invalid, as the first colon in a user-pass string separates user-id and password from one another; text after the first colon is part of the password. User-ids containing colons cannot be encoded in user-pass strings.

PHP-CGI and the Basic Authorization Header

On servers running Apache with the php-cgi handler, the server will not pass the HTTP Authorization header to PHP.

To avoid smashing your keyboard, just add this to your .htaccess file:

    RewriteEngine On
    RewriteCond %{HTTP:Authorization} ^(.+)$
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Security concerns

The basic authorization header is only secure if your connection is done over HTTPS since otherwise the credentials are sent in encoded plain text (not encrypted) over the network which is a huge security issue.

To conclude, the various implementation flaws that basic authentication has can cause serious concerns. However, since it is already a part of many applications, the best thing we can do is to take all possible precautions.

Photo by Markus Voetter on Unsplash