如何从CakePHP /身份验证/身份验证器正确重定向以进行OpenID Connect

时间:2019-01-07 00:07:37

标签: cakephp openid-connect

我正在编写一个Web应用程序,由于不同的客户需求,我希望具有灵活的身份验证选项。我使用的是官方的cakephp/authentication库,但是它没有OpenID Connect身份验证器,所以我要自己开发。

我遇到的问题是我无法从Authenticator返回带有重定向头的修改后的Cake\Http\Response对象。 AuthenticatorInterface需要使用authenticate()方法来返回Result对象。我希望不必修改Authenticator类,因为如果我要重写它的流程,这有点违背使用库的目的。

class OidcAuthenticator extends AbstractAuthenticator
{
public function authenticate(ServerRequestInterface $request, ResponseInterface $response)
{
    // non-pertinent code removed for brevity
    return $this->_requestAuthorization($request, $response);
}


private function _requestAuthorization(ServerRequestInterface $request, ResponseInterface $response)
{
    $auth_endpoint = $this->getConfig('authorization_endpoint');
    $response_type = 'code';
    $state = $this->_setState($request, Security::randomString());

    $auth_params = [
        'response_type' => $response_type,
        'redirect_uri' => 'http://localhost:8080/',
        'client_id' => $this->getConfig('client_id'),
        'nonce' => $nonce,
        'state' => $state,
        'scope' => 'openid'
    ];

    $auth_endpoint .= (strpos($auth_endpoint, '?') === false ? '?' : '&') .
        http_build_query($auth_params, null, '&');

    /* What I want to return */
    $response = $response->withHeader('Location', $auth_endpoint);

    /* What I have to return */
    return new Result(null, Result::FAILURE_MISSING_CREDENTIALS);
}
}

我可以和

一起使用
$request->getAttribute('session')->close();
header('Location: ' . $auth_endpoint, true, 302);
exit();

但是这似乎违反了CakePHP约定。理想情况下,我可以将新的响应对象嵌入到Result中,然后身份验证中间件将捕获它并发出它而不是UnauthenticatedException。这是一个最佳实践的问题,但希望它对SO非常具体。

TL; DR:当您无法将响应对象返回到中间件队列时,如何重定向?

1 个答案:

答案 0 :(得分:2)

AFAICT到目前为止,实际上还没有推荐的做法,可能值得开一个问题over at GitHub进行澄清。

您可以使用UnauthorizedException,它与无状态身份验证有点纠结,但是没有什么可以阻止您使用它。与无状态的身份验证器不同,您必须将其放入authenticate()方法调用流中,如下所示:

private function _requestAuthorization(
    ServerRequestInterface $request,
    ResponseInterface $response
) {
    // ...

    $headers = [
        'Location' => $auth_endpoint
    ];
    $body = null;
    $statusCode = 302;

    throw new \Authentication\Authenticator\UnauthorizedException(
        $headers,
        $body,
        $statusCode
    );
}

然后将在AuthenticationMiddleware::__invoke()中对此进行相应处理,并在其中修改并返回响应。