tuupola / slim-basic-auth

PSR-7 and PSR-15 HTTP Basic Authentication Middleware
MIT License
440 stars 66 forks source link

There is a way to update request in callback ? #57

Closed Ducatel closed 6 years ago

Ducatel commented 6 years ago

Hi,

There is a way to add an attribute/header in the request in callback (or authenticator) method ?

Currently I did that in two steps:

  1. In authenticator when credentials are correct I set my attribute in session
  2. In a second middleware I check if the attribute exist in session and I set it to the request

So I would be nice if it's possible to update the request in this middleware.

Thanks for your help ;)

tuupola commented 6 years ago

With 3.x branch yes. I hope to release it this week. See before and after handlers for examples.

Ducatel commented 6 years ago

Ah, very nice ;) I will wait for this release. Thanks for your work ;)

Ducatel commented 6 years ago

Ok, so I have tried with the version 3.0.0-RC5 but I cannot found how pass something between authenticator function and Before function. Is it possible to do that ?

That is what I did actually

$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
    ......
    "authenticator" => function (array $arguments) use ($container) {
        $credentialsManager = new CredentialsManager($container->get('logger'));
        if ($credentialsManager->login($arguments['user'], $arguments['password']) === false) {
            return false;
        }
        $GLOBALS['X-Service'] = $credentialsManager->getService(); // I want to remove that line which is not very proper
    },
    "before" => function (Request $request, Response $response, $arguments) {
        $service = $GLOBALS['X-Service'];
        unset($GLOBALS['X-Service']);
        return $request->withAttribute('X-Service', $service );
    },
 ....
]));
tuupola commented 6 years ago

With before you can alter the PSR-7 request object. However authenticator receives only username and password as parameters. What are you trying to achieve?

Ducatel commented 6 years ago

As you can see in me sample, my CredentialsManager class does the authentication and can grab some extra data about the current credentials used. I need to pass that extra data to the next middleware.

tuupola commented 6 years ago

If the CredentialsManager can retrieve the service based on username then you could do something like:

$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
    ...
    "authenticator" => function (array $arguments) use ($container) {
        $credentialsManager = new CredentialsManager($container->get('logger'));
        if ($credentialsManager->login($arguments['user'], $arguments['password']) === false) {
            return false;
        }
    },
    "before" => function (Request $request, Response $response, $arguments) use ($container) {
        $credentialsManager = new CredentialsManager($container->get('logger'));
        $service = $credentialsManager->getServiceByUser($arguments['user'])
        return $request->withAttribute('X-Service', $service );
    },
    ...
]));

Or if the credentials manager was in the container then something like this would probably work:

$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
    ...
    "authenticator" => function (array $arguments) use ($container) {
        if ($container['credentialsManager']->login($arguments['user'], $arguments['password']) === false) {
            return false;
        }
    },
    "before" => function (Request $request, Response $response, $arguments) {
        $service = ($container['credentialsManager']->getService();
        return $request->withAttribute('X-Service', $service);
    }
    ...
]));
Ducatel commented 6 years ago

Yes, I have found the same first solution. Thanks for you help ;)