Skip to content

http basic authentication broken with PHP as cgi/fastCGI under Apache #1813

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
keymaster opened this issue Jul 26, 2011 · 14 comments
Closed
Labels
Bug Good first issue Ideal for your first contribution! (some Symfony experience may be required) HttpFoundation

Comments

@keymaster
Copy link

The keys PHP_AUTH_USER and PHP_AUTH_PW are not present in the superglobal $_SERVER, so http basic authentication needs to be handled a little differently.

This also affects functional tests which require http basic auth to authenticate.

Basically the workaround is two parts:

  1. A rewrite rule to pack the username and password into an environment variable:

    RewriteEngine on RewriteRule .\* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
  2. Extract the info from the environment variable:

    list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(':' , base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));

See below for more details.

http://orangejuiceliberationfront.com/http-auth-with-php-in-cgi-mode-e-g-on-dreamhost/
http://www.besthostratings.com/articles/http-auth-php-cgi.html

@willdurand
Copy link
Contributor

What about using the apache_request_headers() function ?

See: #1510

@schmittjoh
Copy link
Contributor

@fabpot, should we maybe add some extra abstraction for this to the Request class?

@benjamindulau
Copy link
Contributor

+1, the request should definitly abstract this.

@keymaster
Copy link
Author

The following works as a temporary workaround:

app_dev.php:

if( !isset($_SERVER['PHP_AUTH_USER']) )
{
    if (isset($_SERVER['HTTP_AUTHORIZATION']) && (strlen($_SERVER['HTTP_AUTHORIZATION']) > 0)){
        list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));
        if( strlen($_SERVER['PHP_AUTH_USER']) == 0 || strlen($_SERVER['PHP_AUTH_PW']) == 0 )
        {
            unset($_SERVER['PHP_AUTH_USER']);
            unset($_SERVER['PHP_AUTH_PW']);
        }
    }
}

web/.htaccess

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L] RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ app.php [QSA,L]
</IfModule>

@fabpot
Copy link
Member

fabpot commented Dec 8, 2011

It works fine for me with FastCGI and Nginx.

Can you paste the whole output of $_SERVER when not using the workaround?

@keymaster
Copy link
Author

Here is the output of $_SERVER without the workaround:

    Array
    (
        [ALLUSERSPROFILE] => C:\ProgramData
        [APPDATA] => C:\windows\system32\config\systemprofile\AppData\Roaming
        [asl_log] => Destination=file
        [CLASSPATH] => .;C:\Program Files\Java\jre6\lib\ext\QTJava.zip
        [CommonProgramFiles] => C:\Program Files\Common Files
        [COMPUTERNAME] => HP
        [ComSpec] => C:\windows\system32\cmd.exe
        [DB2INSTANCE] => DB2
        [FP_NO_HOST_CHECK] => NO
        [LOCALAPPDATA] => C:\windows\system32\config\systemprofile\AppData\Local
        [NUMBER_OF_PROCESSORS] => 4
        [OnlineServices] => Online Services
        [OS] => Windows_NT
        [Path] => C:\windows\system32;C:\windows;C:\windows\System32\Wbem;C:\windows\System32\WindowsPowerShell\v1.0\;c:\Program Files\Hewlett-Packard\Drive Encryption\;C:\Program Files\WIDCOMM\Bluetooth Software\;C:\Program Files\Broadcom\Broadcom 802.11\Driver;C:\Program Files\QuickTime\QTSystem\;C:\Program Files\Zend\ZendServer\bin
        [PATHEXT] => .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
        [PCBRAND] => s
        [PHPRC] => C:\Program Files\Zend\ZendServer\etc
        [PHP_FCGI_MAX_REQUESTS] => 10000
        [Platform] => BNB
        [PROCESSOR_ARCHITECTURE] => x86
        [PROCESSOR_IDENTIFIER] => x86 Family 6 Model 37 Stepping 5, GenuineIntel
        [PROCESSOR_LEVEL] => 6
        [PROCESSOR_REVISION] => 2505
        [ProgramData] => C:\ProgramData
        [ProgramFiles] => C:\Program Files
        [PSModulePath] => C:\windows\system32\WindowsPowerShell\v1.0\Modules\
        [PTSM_install_path] => c:\Program Files\Hewlett-Packard\HP ProtectTools Security Manager\Bin
        [PUBLIC] => C:\Users\Public
        [QTJAVA] => C:\Program Files\Java\jre6\lib\ext\QTJava.zip
        [SystemDrive] => C:
        [SystemRoot] => C:\windows
        [TEMP] => C:\Users\User\AppData\Local\Temp
        [TMP] => C:\windows\TEMP
        [USERDOMAIN] => WORKGROUP
        [USERNAME] => HP$
        [USERPROFILE] => C:\windows\system32\config\systemprofile
        [windir] => C:\windows
        [AP_PARENT_PID] => 688
        [_FCGI_CLIENT_PID_] => 2244
        [_FCGI_MUTEX_] => 776
        [_FCGI_NTAUTH_IMPERSONATE_] => 1
        [_FCGI_SHUTDOWN_EVENT_] => 772
        [FCGI_ROLE] => RESPONDER
        [HTTP_HOST] => localhost
        [HTTP_USER_AGENT] => Mozilla/5.0 (Windows NT 6.1; rv:8.0) Gecko/20100101 Firefox/8.0
        [HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
        [HTTP_ACCEPT_LANGUAGE] => en-us,en;q=0.5
        [HTTP_ACCEPT_ENCODING] => gzip, deflate
        [HTTP_ACCEPT_CHARSET] => ISO-8859-1,utf-8;q=0.7,*;q=0.7
        [HTTP_CONNECTION] => keep-alive
        [HTTP_COOKIE] => __utma=1.441182227.1321189418.1322498628.1323267653.4; __utmz=1.1321189418.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); ZDEDebuggerPresent=php,phtml,php3; PHPSESSID=nqtap9dur6uja1rjjumcttmc25
        [HTTP_CACHE_CONTROL] => max-age=0
        [PATH] => C:\windows\system32;C:\windows;C:\windows\System32\Wbem;C:\windows\System32\WindowsPowerShell\v1.0\;c:\Program Files\Hewlett-Packard\Drive Encryption\;C:\Program Files\WIDCOMM\Bluetooth Software\;C:\Program Files\Broadcom\Broadcom 802.11\Driver;"C:\Program Files\Zend\ZendServer\bin";"C:\Program Files\Zend\ZendServer\share\ZendFramework\bin";C:\Program Files\Zend\MySQL51\bin;C:\Program Files\Git\cmd;C:\Program Files\Git\bin;C:\Program Files\TortoiseSVN\bin;C:\Program Files\Common Files\HP\Digital Imaging\bin;C:\Program Files\HP\Digital Imaging\bin\;C:\Program Files\HP\Digital Imaging\bin\Qt\Qt 4.3.3;C:\Program Files\QuickTime\QTSystem\;
        [COMSPEC] => C:\windows\system32\cmd.exe
        [WINDIR] => C:\windows
        [SERVER_SIGNATURE] => 
        [SERVER_SOFTWARE] => Apache/2.2.16 (Win32) mod_ssl/2.2.16 OpenSSL/0.9.8o
        [SERVER_NAME] => localhost
        [SERVER_ADDR] => 127.0.0.1
        [SERVER_PORT] => 80
        [REMOTE_ADDR] => 127.0.0.1
        [DOCUMENT_ROOT] => C:/Program Files/Zend/Apache2/htdocs
        [SERVER_ADMIN] => admin@example.com
        [SCRIPT_FILENAME] => C:/Program Files/Zend/Apache2/htdocs/MySite/web/app_dev.php
        [REMOTE_PORT] => 1740
        [GATEWAY_INTERFACE] => CGI/1.1
        [SERVER_PROTOCOL] => HTTP/1.1
        [REQUEST_METHOD] => GET
        [QUERY_STRING] => 
        [REQUEST_URI] => /MySite/web/app_dev.php/
        [SCRIPT_NAME] => /MySite/web/app_dev.php
        [PATH_INFO] => /
        [PATH_TRANSLATED] => C:\Program Files\Zend\Apache2\htdocs\index.html
        [PHP_SELF] => /MySite/web/app_dev.php/
        [REQUEST_TIME] => 1324019271
        [argv] => Array
            (
            )

        [argc] => 0
    )

@kepten
Copy link
Contributor

kepten commented Mar 10, 2012

Finally I've made a working patch for that, I'll submit it as soon as I figure out how to submit a patch... ;)

@stof
Copy link
Member

stof commented Mar 10, 2012

@vicb
Copy link
Contributor

vicb commented Apr 13, 2012

Task for the BHD: update the associated PR #3551 (there are some comments there)

@towards
Copy link

towards commented Apr 20, 2012

working on this issue today...

@kepten
Copy link
Contributor

kepten commented Apr 20, 2012

has a working PR, just needs review: #3551

kepten added a commit to kepten/symfony that referenced this issue Apr 20, 2012
…fastCGI under Apache

Bug fix: yes
Feature addition: no
Backwards compatibility break: no
Symfony2 tests pass: yes
Fixes the following tickets: symfony#1813
Todo: -

In order to work, add this to the .htaccess:

RewriteEngine on
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ app.php [QSA,L]
fabpot added a commit that referenced this issue May 21, 2012
Commits
-------

a450d00 [HttpFoundation] HTTP Basic authentication is broken with PHP as cgi/fastCGI under Apache

Discussion
----------

[HttpFoundation] HTTP Basic authentication is broken with php-cgi under Apache

Bug fix: yes
Feature addition: no
Backwards compatibility break: no
Symfony2 tests pass: yes
Fixes the following tickets: #1813
Todo: -

In order to work, add this to the .htaccess:

RewriteEngine on
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ app.php [QSA,L]

---------------------------------------------------------------------------

by stof at 2012-03-10T17:34:26Z

you should also add a unit test for this

---------------------------------------------------------------------------

by kepten at 2012-03-11T15:34:04Z

Thanks for the feedback, I committed the changes.

---------------------------------------------------------------------------

by stof at 2012-04-04T01:59:53Z

@fabpot could you review it ?

---------------------------------------------------------------------------

by fabpot at 2012-04-04T07:15:34Z

My comments:

 * `ServerBag` represents what we have in the `$_SERVER` global variables. As such, the code should be moved to the `getHeaders()` method instead like the other tweaks we do for the HTTP headers.

 * A comment must be added explaining why this is needed and the configuration the user must have to make it work (then remove the Github URLs).

 * The code should only be executed when `PHP_AUTH_USER` is not available (to not have any overhead when not needed).

---------------------------------------------------------------------------

by danielholmes at 2012-04-14T13:27:09Z

A quick note on that .htaccess/apache configuration required, if adding to the Symfony SE htaccess file, then it will need to look like this:

```
<IfModule mod_rewrite.c>
    RewriteEngine On

    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ app.php [QSA,L]
</IfModule>
```

NOTE: No **,L** in the Authorization Rewrite as in the original example - it prevents the front controller rewrite from happening

---------------------------------------------------------------------------

by towards at 2012-04-20T16:12:49Z

@kepten you were faster than me applying @fabpot's comments :) nevertheless part of the bug hunt day I also modified the ServerBag class and tested them on a productive LAMP hosting server using Apache and FastCGI

---------------------------------------------------------------------------

by kepten at 2012-04-20T16:15:57Z

ok, so is my PR is useless or should I still fix problems?

---------------------------------------------------------------------------

by towards at 2012-04-20T16:20:26Z

your PR is fine for sure and I don't want to interfere, just wanted to mention that part of the bug hunt day of Symfony I had a go at this PR as an "exercise" but just saw later on that you already fixed the problem, so you can ignore my pushes

---------------------------------------------------------------------------

by vicb at 2012-04-20T16:20:36Z

I have been working with @towards: your PR is useful, please implement his comments and squash your PR.

---------------------------------------------------------------------------

by kepten at 2012-04-20T16:59:07Z

never squashed before, is it okay now? :)

---------------------------------------------------------------------------

by stof at 2012-04-20T17:21:07Z

it is

---------------------------------------------------------------------------

by vicb at 2012-05-20T19:57:51Z

@fabpot this should be ready to be merged
@fabpot fabpot closed this as completed May 21, 2012
fabpot added a commit that referenced this issue Jun 12, 2012
Commits
-------

5d88255 Authorization header should only be rebuild when Basic Auth scheme is used

Discussion
----------

[Regression fix] Authorization header should only be rebuild when Basic Auth scheme is used

Bug fix: yes
Feature addition: no
Backwards compatibility break: no
Symfony2 tests pass: yes
Fixes the following tickets: fixes regression introduced by #1813
Todo: N/A
License of the code: MIT

---------------------------------------------------------------------------

by travisbot at 2012-06-11T14:40:28Z

This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1592604) (merged cf5ee26a into 27100ba).

---------------------------------------------------------------------------

by mvrhov at 2012-06-12T06:13:01Z

fixed

---------------------------------------------------------------------------

by travisbot at 2012-06-12T06:14:55Z

This pull request [passes](http://travis-ci.org/symfony/symfony/builds/1598555) (merged 5d88255 into 27100ba).
fabpot added a commit that referenced this issue Sep 7, 2013
This PR was submitted for the master branch but it was merged into the 2.2 branch instead (closes #8952).

Discussion
----------

[HttpFoundation] Fixing broken http auth digest in some circumstances.

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | can be refered in issue #1813
| License       | MIT
| Doc PR        | n/a

With some apache + php-fpm setup we need to set ```PHP_AUTH_DIGEST``` value if not already setted in GLOBAL vars.

Added some unit tests too.

Commits
-------

9fc994b [HttpFoundation] Fixing broken http auth digest in some circumstances (php-fpm + apache).
@iftikhardirv
Copy link

private $username = 'test';
private $password = 'test';
public function test_auth() {
if($this->authenticate_user()){
echo 'login';exit;
}else{
echo 'failed';exit;
}
}

public function authenticate_user(){
    if( !isset($_SERVER['PHP_AUTH_USER']) )
    {
        header('HTTP/1.0 401 Unauthorized');
        header('HTTP/1.1 401 Unauthorized');
        header('WWW-Authenticate: Basic realm="Realm"');
        echo "You must login to use this service"; // User sees this if hit cancel
        die();            
    }else{
        if($this->username != $_SERVER['PHP_AUTH_USER'] || $this->password != $_SERVER['PHP_AUTH_PW']){
            header('HTTP/1.0 401 Unauthorized');
            header('HTTP/1.1 401 Unauthorized');
            header('WWW-Authenticate: Basic realm="Realm"');
            echo "You must login to use this service"; // User sees this if hit cancel
            die();
        }else{
            return true;
        }
    }
}

ionas added a commit to ionas/docs that referenced this issue Aug 5, 2015
PHP_AUTH_PW might be empty in case of Apache2 + FastCGI-PHP Setup.
See symfony/symfony#1813
@JefferyHus
Copy link

# make HTTP Basic Authentication work on php5-fcgi installs
<IfModule mod_fcgid.c>
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
</IfModule>

@paulwratt
Copy link

thanks for this post, bug fixes and comments - I got this workaround to work on non "symfony", managed to patched "thttpd" web server and "PHP Navigator" file manager with your workarounds.

nicolas-grekas added a commit that referenced this issue Nov 28, 2019
…bison)

This PR was submitted for the master branch but it was merged into the 3.4 branch instead.

Discussion
----------

Simpler example for Apache basic auth workaround

Uses a simpler regex and existing back-reference instead of reading header twice.

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Tickets       | #1813
| License       | MIT

Improvement to code documentation, no change to executed code.

Commits
-------

388528d Simpler example for Apache basic auth workaround
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Good first issue Ideal for your first contribution! (some Symfony experience may be required) HttpFoundation
Projects
None yet
Development

No branches or pull requests