slim-basic-auth
slim-basic-auth copied to clipboard
Basic case-insensitive and PHP_AUTH_USER
Hi,
I have the following code:
$app->add(new \Slim\Middleware\HttpBasicAuthentication([
"path" => ["/auth", "/user", "/search"],
"realm" => "Protected",
"authenticator" => new PdoAuthenticator([
"pdo" => $authenticator_pdo,
"table" => "users",
"user" => "username",
"hash" => "password_hash"
]),
"callback" => function ($request, $response, $arguments) {
print_r($arguments);
},
"error" => function ($request, $response, $arguments) {
return $response->withJson(array('error' => 'AUTHENTICATION_FAILED'), 403);
}
]));
// Check HTTP Basic Authentication
$app->get('/auth', function ($request, $response, $args) {
$auth_username = $_SERVER['PHP_AUTH_USER'];
// Return
return $response->withJson(array(
'username' => $auth_username,
'status' => 'OK'
), 200);
});
If I pass in the header "Authorization: Basic" (upper case B) the authentication is successful and PHP_AUTH_USER is set:
curl 'http://localhost:8080/auth' -H 'Authorization: Basic bmlsczp0ZXN0MTIzNA=='
Array
(
[user] => nils
[password] => test1234
)
{"username":"nils","status":"OK"}
If I pass in the header "Authorization: basic" (lowercase letter b) the authentication is successful and PHP_AUTH_USER is not set.
curl 'http://localhost:8080/auth' -H 'Authorization: basic bmlsczp0ZXN0MTIzNA=='
Array
(
[user] => nils
[password] => test1234
)
{"username":null,"status":"OK"}
When I remove the case-insensitive (/i) Regular Expression in HttpBasicAuthentication.php then the authentication with basic (lowercase letter b) fails:
curl 'http://localhost:8080/auth' -H 'Authorization: basic bmlsczp0ZXN0MTIzNA=='
{"error":"AUTHENTICATION_FAILED"}
That would be better in my case. I am briefly overflown the RFCs. Basic is always written with (upper case B).
Best regards Nils
According to RFC2617 the authentication scheme is case-insensitive.
HTTP provides a simple challenge-response authentication mechanism that MAY be used by a server to challenge a client request and by a client to provide authentication information. It uses an extensible, case-insensitive token to identify the authentication scheme, followed by a comma-separated list of attribute-value pairs which carry the parameters necessary for achieving authentication via that scheme.
PHP itself is quite picky about format of of headers though. What is the problem current behaviour causes you?
Thanks for the super fast response and the clarification of the RFC.
My problem is that I trust the authentication and expect a PHP_AUTH_USER. I double check this now:
$check_auth_user = function ($request, $response, $next) {
if (isset($_SERVER['PHP_AUTH_USER'])) {
$response = $next($request, $response);
} else {
return $response->withJson(array('error' => 'AUTH_USER'), 403);
}
return $response;
};
// Check HTTP Basic Authentication
$app->get('/auth', function ($request, $response, $args) {
$auth_username = $_SERVER['PHP_AUTH_USER'];
// Return
return $response->withJson(array(
'username' => $auth_username,
'status' => 'OK'
), 200);
})->add($check_auth_user);
You're right. PHP is case sensitive.
basic - ❌ PHP_AUTH_USER:
curl 'http://localhost:8080/bla' -H 'Authorization: basic bmlsczp0ZXN0MTIzNA==' | jq
{
"server": {
"DOCUMENT_ROOT": "/Users/nils/Projekte/slim/livetracking/public",
"REMOTE_ADDR": "127.0.0.1",
"REMOTE_PORT": "52606",
"SERVER_SOFTWARE": "PHP 5.6.28 Development Server",
"SERVER_PROTOCOL": "HTTP/1.1",
"SERVER_NAME": "127.0.0.1",
"SERVER_PORT": "8080",
"REQUEST_URI": "/bla",
"REQUEST_METHOD": "GET",
"SCRIPT_NAME": "/index.php",
"SCRIPT_FILENAME": "/Users/nils/Projekte/slim/livetracking/public/index.php",
"PATH_INFO": "/bla",
"PHP_SELF": "/index.php/bla",
"HTTP_HOST": "localhost:8080",
"HTTP_USER_AGENT": "curl/7.52.1",
"HTTP_ACCEPT": "*/*",
"HTTP_AUTHORIZATION": "basic bmlsczp0ZXN0MTIzNA==",
"REQUEST_TIME_FLOAT": 1488274696.9322,
"REQUEST_TIME": 1488274696
}
}
Basic - ✅ PHP_AUTH_USER:
curl 'http://localhost:8080/bla' -H 'Authorization: Basic bmlsczp0ZXN0MTIzNA==' | jq
{
"server": {
"DOCUMENT_ROOT": "/Users/nils/Projekte/slim/livetracking/public",
"REMOTE_ADDR": "127.0.0.1",
"REMOTE_PORT": "52608",
"SERVER_SOFTWARE": "PHP 5.6.28 Development Server",
"SERVER_PROTOCOL": "HTTP/1.1",
"SERVER_NAME": "127.0.0.1",
"SERVER_PORT": "8080",
"REQUEST_URI": "/bla",
"REQUEST_METHOD": "GET",
"SCRIPT_NAME": "/index.php",
"SCRIPT_FILENAME": "/Users/nils/Projekte/slim/livetracking/public/index.php",
"PATH_INFO": "/bla",
"PHP_SELF": "/index.php/bla",
"HTTP_HOST": "localhost:8080",
"HTTP_USER_AGENT": "curl/7.52.1",
"HTTP_ACCEPT": "*/*",
"HTTP_AUTHORIZATION": "Basic bmlsczp0ZXN0MTIzNA==",
"PHP_AUTH_USER": "nils",
"PHP_AUTH_PW": "test1234",
"REQUEST_TIME_FLOAT": 1488274708.5842,
"REQUEST_TIME": 1488274708
}
}
If the standard says that basic
is OK then the error is in PHP.
You could try to set PHP_AUTH_USER
in the callback.
$app->add(new \Slim\Middleware\HttpBasicAuthentication([
...
"callback" => function ($request, $response, $arguments) {
$_SERVER['PHP_AUTH_USER'] = $arguments['username'];
}
]));
That said middleware could actually do that by default if authentication succeeds and PHP_AUTH_USER
is still null.
Good idea. This works for me. Thank you very much.