使用PDO身份验证器,Slim 3的HTTP基本身份验证失败

使用PDO身份验证器,Slim 3的HTTP基本身份验证失败

问题描述:

I am using Slim v 3 with JWT for writing REST APIs. I followed https://github.com/tuupola/slim-jwt-auth and it is working fine.

I am generating a token each time the user logs into the appl. To authenticate the user, I followed https://github.com/tuupola/slim-basic-auth to use as auth middleware. On success, I am generating a token using https://github.com/firebase/php-jwt.

I was going through a related question on SO here, JWT: Authentication in slim v3 and Android and I have a query on http basic auth. (I dont have sufficient rep to make a comment there ).

Now my questions:

  1. HttpBasicAuthentication through the 'users' option is working fine but I wouldnt be able to use it against my users table obviously. Many users would be logging into the application and listing all of them in the 'users' is not an option. Am I right here?

  2. If yes, I have to use Pdo Authenticator. I configured it but authentication is failing and I couldnt solve it. The error callback is being fired with "Authentication failed" message. My database has 'users' table with 'user' and 'hash' columns for username and password. Below is the piece of code I am using.

use Slim\Middleware\HttpBasicAuthentication;
use Slim\Middleware\HttpBasicAuthentication\PdoAuthenticator;
$pdo = new \PDO('mysql:host=localhost;dbname=test', $dbUser, $dbPassword);

$middlewareHttpBasicAuthConfig = [
        /*"users" => [
            "user1" => "password"
        ],*/
        "secure" => false,
        "relaxed" => ["localhost", "amruta-pani"],
        "path" => "/*",
        "passthrough" => Utils::httpAuthPassThroughRoutes,
        "realm" => "Protected",

        "authenticator" => new PdoAuthenticator([
            "pdo" => $pdo
        ]),

        "callback" => function($request, $response, $arguments) {
            echo "Through<br>
";
            print_r($arguments);
        },

        "error" => function($request, $response, $arguments) {
            echo "Failed<br>
";
            print_r($arguments);
        }
    ];


    $app->add(new HttpBasicAuthentication($middlewareHttpBasicAuthConfig));

I am using Google Advanced Rest Client for testing it and the output I am seeing is

Failed<br>
Array
(
    [message] => Authentication failed
)

I have added below rule to my Apache webserver

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

What am I missing here?

@Mika Tuupola helped me resolve this problem in the comments and credit goes to him, and I thought it would help somebody. I was hoping that he would answer it for me to mark it.

Passwords should be hashed for HTTPBasicAuthentication middleware to work. Clear text passwords cannot be authenticated with PDO driver, however, if the configuration array has 'users' property, with a clear text password like below, will work which obviously wouldnt be the case in production.

$app->add(new \Slim\Middleware\HttpBasicAuthentication([
    "users" => [
        "root" => "t00r",
        "somebody" => "passw0rd"
    ]
]));

The GitHub documentation at https://github.com/tuupola/slim-basic-auth was good enough to use this middleware however when it mentioned about clear text passwords, quote -

Cleartext passwords are only good for quick testing. You probably...

I went ahead testing it with clear text passwords with PDO and it didnt work till the password is hashed.

It seems you need to pass your database naming scheme to the PdoAuthenticator as described in the blog post.

In your case this would be something like...

"authenticator" => new PdoAuthenticator([
    "pdo" => $pdo,
    "table" => "users",
    "user" => "user",
    "hash" => "hash"
])

...which indeed seem to be the default values. Maybe it's not working due to a simple underlying PDO connection problem. Also, looking at the source, the PdoAuthenticator uses password_verify() internally, so it will only be available in PHP 5 >= 5.5.0 and PHP 7.

You could also roll your own authenticator. As far as your question about handling the credentials in your own authenticator callback goes, you would do something like:

class MyAuthenticator implements AuthenticatorInterface {
    public function __invoke(array $arguments) {
        // $arguments['user'] will contain username
        // $arguments['password'] will contain password
        // Do stuff...
    }
}