【问题标题】:How to redirect from an authenticator to an external authentication endpoint?如何从身份验证器重定向到外部身份验证端点?
【发布时间】:2019-06-01 16:30:18
【问题描述】:

我正在编写一个网络应用程序,由于不同客户的需求,我希望它具有灵活的身份验证选项。我正在使用官方的 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 的约定。理想情况下,我可以将新的响应对象嵌入到结果中,并且身份验证中间件会捕获并发出它,而不是 UnauthenticatedException。这是一个最佳实践问题,但希望它对 SO 来说足够具体。

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

【问题讨论】:

    标签: authentication cakephp openid-connect


    【解决方案1】:

    AFAICT 目前没有真正推荐的做法,可能值得打开一个问题 over at GitHub 进行澄清。

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

    private function _requestAuthorization(
        ServerRequestInterface $request,
        ResponseInterface $response
    ) {
        // ...
    
        $headers = [
            'Location' => $auth_endpoint
        ];
        $body = null;
        $statusCode = 302;
    
        // in CakePHP 4.x / Authentication 2.x
        throw new \Authentication\Authenticator\AuthenticationRequiredException (
            $headers,
            $body,
            $statusCode
        );
    
        // in CakePHP 3.x / Authentication 1.x
        throw new \Authentication\Authenticator\UnauthorizedException(
            $headers,
            $body,
            $statusCode
        );
    }
    

    这将在AuthenticationMiddleware::__invoke() 中进行相应的处理,其中将修改并返回响应。

    【讨论】:

    • 这看起来很棒!我目前处于 AFK 状态,但当我回来时,我会尝试并标记为已回答。
    • 完美运行!我已将问题标记为已回答,并按照您的建议在 GitHub 上发布了一个问题 (#231)。感谢您的帮助!
    猜你喜欢
    • 2014-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-25
    • 1970-01-01
    相关资源
    最近更新 更多