Skip to content
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

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

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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 35 additions & 3 deletions src/Symfony/Component/HttpFoundation/ServerBag.php
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
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
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());
}
}