8000 [HttpFoundation] HTTP Basic authentication is broken with php-cgi under Apache by kepten · Pull Request #3551 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

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

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

Merged
merged 1 commit into from
May 21, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
[HttpFoundation] HTTP Basic authentication is broken with PHP as cgi/…
…fastCGI 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]
  • Loading branch information
kepten committed Apr 20, 2012
commit a450d002f253e32e77d5c2bd3e490435c68a8c09
38 changes: 35 additions & 3 deletions src/Symfony/Component/HttpFoundation/ServerBag.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Bulat Shakirzyanov <mallluhuct@gmail.com>
* @author Robert Kiss <kepten@gmail.com>
*/
class ServerBag extends ParameterBag
{
Expand All @@ -32,10 +33,41 @@ public function getHeaders()
}
}

// PHP_AUTH_USER/PHP_AUTH_PW
if (isset($this->parameters['PHP_AUTH_USER'])) {
$pass = isset($this->parameters['PHP_AUTH_PW']) ? $this->parameters['PHP_AUTH_PW'] : '';
$headers['AUTHORIZATION'] = 'Basic '.base64_encode($this->parameters['PHP_AUTH_USER'].':'.$pass);
$headers['PHP_AUTH_USER'] = $this->parameters['PHP_AUTH_USER'];
$headers['PHP_AUTH_PW'] = isset($this->parameters['PHP_AUTH_PW']) ? $this->parameters['PHP_AUTH_PW'] : '';
} else {
/*
* php-cgi under Apache does not pass HTTP Basic user/pass to PHP by default
* For this workaround to work, add this line to your .htaccess file:
* RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
*
* A sample .htaccess file:
* RewriteEngine On
* RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
* RewriteCond %{REQUEST_FILENAME} !-f
* RewriteRule ^(.*)$ app.php [QSA,L]
*/

$authorizationHeader = null;
if (isset($this->parameters['HTTP_AUTHORIZATION'])) {
$authorizationHeader = $this->parameters['HTTP_AUTHORIZATION'];
} elseif (isset($this->parameters['REDIRECT_HTTP_AUTHORIZATION'])) {
$authorizationHeader = $this->parameters['REDIRECT_HTTP_AUTHORIZATION'];
}

// Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW
if (null !== $authorizationHeader) {
$exploded = explode(':', base64_decode(substr($authorizationHeader, 6)));
if (count($exploded) == 2) {
list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded;
}
}
}

// PHP_AUTH_USER/PHP_AUTH_PW
if (isset($headers['PHP_AUTH_USER'])) {
$headers['AUTHORIZATION'] = 'Basic '.base64_encode($headers['PHP_AUTH_USER'].':'.$headers['PHP_AUTH_PW']);
}

return $headers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public function handle(GetResponseEvent $event)
{
$request = $event->getRequest();

if (false === $username = $request->server->get('PHP_AUTH_USER', false)) {
if (false === $username = $request->headers->get('PHP_AUTH_USER', false)) {
return;
}

Expand All @@ -71,7 +71,7 @@ public function handle(GetResponseEvent $event)
}

try {
$token = $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $request->server->get('PHP_AUTH_PW'), $this->providerKey));
$token = $this->authenticationManager->authenticate(new UsernamePasswordToken($username, $request->headers->get('PHP_AUTH_PW'), $this->providerKey));
$this->securityContext->setToken($token);
} catch (AuthenticationException $failed) {
$this->securityContext->setToken(null);
Expand Down
41 changes: 40 additions & 1 deletion tests/Symfony/Tests/Component/HttpFoundation/ServerBagTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,52 @@ public function testShouldExtractHeadersFromServerArray()
'CONTENT_LENGTH' => '0',
'ETAG' => 'asdf',
'AUTHORIZATION' => 'Basic '.base64_encode('foo:bar'),
'PHP_AUTH_USER' => 'foo',
'PHP_AUTH_PW' => 'bar',
), $bag->getHeaders());
}

public function testHttpPasswordIsOptional()
{
$bag = new ServerBag(array('PHP_AUTH_USER' => 'foo'));

$this->assertEquals(array('AUTHORIZATION' => 'Basic '.base64_encode('foo:')), $bag->getHeaders());
$this->assertEquals(array(
'AUTHORIZATION' => 'Basic '.base64_encode('foo:'),
'PHP_AUTH_USER' => 'foo',
'PHP_AUTH_PW' => ''
), $bag->getHeaders());
}

public function testHttpBasicAuthWithPhpCgi()
{
$bag = new ServerBag(array('HTTP_AUTHORIZATION' => 'Basic '.base64_encode('foo:bar')));

$this->assertEquals(array(
'AUTHORIZATION' => 'Basic '.base64_encode('foo:bar'),
'PHP_AUTH_USER' => 'foo',
'PHP_AUTH_PW' => 'bar'
), $bag->getHeaders());
}

public function testHttpBasicAuthWithPhpCgiRedirect()
{
$bag = new ServerBag(array('REDIRECT_HTTP_AUTHORIZATION' => 'Basic '.base64_encode('foo:bar')));

$this->assertEquals(array(
'AUTHORIZATION' => 'Basic '.base64_encode('foo:bar'),
'PHP_AUTH_USER' => 'foo',
'PHP_AUTH_PW' => 'bar'
), $bag->getHeaders());
}

public function testHttpBasicAuthWithPhpCgiEmptyPassword()
{
$bag = new ServerBag(array('HTTP_AUTHORIZATION' => 'Basic '.base64_encode('foo:')));

$this->assertEquals(array(
'AUTHORIZATION' => 'Basic '.base64_encode('foo:'),
'PHP_AUTH_USER' => 'foo',
'PHP_AUTH_PW' => ''
), $bag->getHeaders());
}
}
0