【问题标题】:Authorization request to Feedly API throws a bad request with Guzzle?Feedly API 的授权请求向 Guzzle 抛出错误请求?
【发布时间】:2017-02-10 09:10:48
【问题描述】:

目的是用授权码交换访问和刷新令牌。

错误:

GuzzleHttp\Exception\ClientException #400

Client error response 
[url] http://sandbox.feedly.com/v3/auth/token?code=[auth_code]&client_id=sandbox&client_secret=[secret]&redirect_uri=https%253A%252F%252F[site url]&grant_type=authorization_code&state=%23 
[status code] 400 
[reason phrase] Bad Request

相关代码:

$client = new GuzzleHttp\Client();
$parameters = ['code'=>$_GET['code'],'client_id'=>'sandbox','client_secret'=> '[secret]','redirect_uri'=>urlencode('https://[site url]'),'grant_type'=>'authorization_code', 'state'=>'#'];
$params = http_build_query($parameters);
$request = $client->createRequest('POST', 'http://sandbox.feedly.com/v3/auth/token?'.$params);
$request->addHeader('Accept-Encoding','GZIP');
$request->setHeader('Authorization', "auth-code");
$request->addHeader('Content-Type','application/json');
$response = $client->send($request);
var_dump($response->json());

也尝试使用state = "state.passed.in",但抛出相同的错误。

你能指出代码sn-p中的错误吗?它使用 Feedly API v3 沙盒和 Guzzle HTTP 客户端。

如果跟随请求 URL,它会抛出“get not allowed”。

更新代码 sn-p:

$client = new GuzzleHttp\Client();
    $parameters = ['code'=>$_GET['code'],'client_id'=>'sandbox','client_secret'=> '[secret]','redirect_uri'=>urlencode('https://[site url]'),'grant_type'=>'authorization_code', 'state'=>'#'];
    $params = http_build_query($parameters);
    $request = $client->createRequest('POST', 'http://sandbox.feedly.com/v3/auth/token?'.$params);
    $response = $client->send($request);
    var_dump($response->json());

更新代码出错:

GuzzleHttp\Exception\ServerException #522

Server error response [url] http://sandbox.feedly.com/v3/auth/token?code=[auth_code]&client_id=sandbox&client_secret=[secret]&redirect_uri=https%253A%252F%252F[site url]&grant_type=authorization_code&state=%23 
[status code] 522 
[reason phrase] Origin Connection Time-out  

注意:更新代码会抛出同样的错误(几个小时后)

GuzzleHttp\Exception\ClientException #400

Client error response 
[url] http://sandbox.feedly.com/v3/auth/token?code=[auth_code]&client_id=sandbox&client_secret=[secret]&redirect_uri=https%253A%252F%252F[site url]&grant_type=authorization_code&state=%23 
[status code] 400 
[reason phrase] Bad Request

【问题讨论】:

    标签: oauth-2.0 authorization guzzle feedly


    【解决方案1】:

    从底层开始,按照 OAuth 2.0 规范:

    客户端在制作访问令牌时必须使用 HTTP“POST”方法 请求。

    (来源:第 3.2 节。The OAuth 2.0 Authorization Framework

    所以这就解释了为什么在浏览器中导航到请求 URL 会失败(导航问题为 GET 并且仅支持 POST 请求)。

    下一点是客户端身份验证,更具体地说,是如何提供client_idclient_secret 参数,以便服务器可以验证您是受信任的客户端应用程序。同样,根据规范,应该通过两种方式传递此信息:

    1. 通过 [RFC2617] 中定义的 HTTP Basic 身份验证方案,其中客户端标识符作为用户名传递,客户端密码作为密码传递。此方法必须由符合 OAuth 的服务器支持,并且也是推荐的方法。*
    2. 通过在请求正文中包含客户端凭据,通常编码为application/x-www-form-urlencoded(参见下面的示例)。此方法是可选的,在某些 OAuth 服务器中可能不可用。

    在请求正文中传递客户端凭据的示例:

    POST https://YOUR_NAMESPACE/oauth/token
     Content-type: application/x-www-form-urlencoded
    
    client_id=YOUR_CLIENT_ID
    &redirect_uri=http://YOUR_APP/callback
    &client_secret=YOUR_CLIENT_SECRET
    &code=AUTHORIZATION_CODE
    &grant_type=authorization_code
    

    (来源:OAuth Web Application Protocol 的第四步,单击第二步中的普通链接可查看完整授权码授予流程中的所有原始 HTTP 请求)

    现在,对于 Feedly 用例,我在文档中找不到有关支持 HTTP 基本身份验证的任何内容。他们确实说了以下关于交换访问令牌代码所需的参数:

    注意:这些参数既可以在 URL 中作为表单值传递,也可以在 JSON 文档中传递。如果您使用 JSON 文档,请确保在请求中传递“Content-Type: application/json”标头。

    (来源:Exchanging an auth code for a refresh token and an access token

    令人惊讶的是,它们似乎允许在 URL 本身中传递客户端凭据,这是 OAuth 规范明确禁止的:

    参数(client_id and client_secret)只能在request-body中传输,不能包含在 请求 URI。

    (来源:第 2.3.1 节。The OAuth 2.0 Authorization Framework

    总之,根据他们的文档,您正在做的事情(在 URL 本身中传递参数)应该是可能的,除非文档不是最新的并且他们已经修复了不符合规范的问题并且不再支持这个。

    此外,您所做的一些事情似乎是错误的。 code 参数永远不会在 Authorisation 标头中传递,因此除非您想尝试使用基本身份验证在该标头中传递客户端凭据,否则我建议您删除此标头。

    我还会删除 Accept-Encoding 标头,因为他们的文档除了返回 JSON 响应之外没有提到支持任何内容。如果要保留该标头,请将值从 gzip 更改为 application/json

    最后,您也没有在请求正文中发送任何数据,因此您可能还希望删除 Content-Type 标头,因为 Feedly 可能认为如果此标头存在,则数据在请求中而不是网址。

    【讨论】:

    • 522 状态码不是标准的,我知道 CloudFare 使用它来表示服务器连接超时,所以这可能是 Feedly 服务器上的问题。见Error-522-Connection-timed-out
    • 感谢您的解释。那很有帮助。我适当地更新了代码并得到了[status code] 522 [reason phrase] Origin Connection Time-out error。我在问题中添加了更新的代码和错误。我查看了错误的详细信息,发现这是一个服务器端错误。你能解释一下这个错误吗?是否有一些修复(以防我遗漏某些东西)我可以从我这边申请?
    • 尝试了几个小时后,更新的代码出现了同样的错误:[status code] 400 [reason phrase] Bad Request。现在没有引发 522 错误。能否请您解释一下这个问题?
    【解决方案2】:

    问题:重定向 URI 是双重编码的,即我传递 https%253A%252F%252Fdev10.ritepush.com%252Fdashboard,它解码为 https%3A%2F%2Fdev10.ritepush.com%2Fdashboard。一旦我需要传递https%3A%2F%2Fdev10.ritepush.com%2Fdashboard,我必须对uri进行编码。

    原因: PHP 会自动对 http 请求进行编码,因此在将 urlencode 应用于 redirect_uri 时,我实际上对重定向 URI 进行了两次编码,但它只被解码一次。因此,在请求正文中传递了编码 URI,从而导致错误。

    感谢 FeedlyDavid Chatenay 指出错误。

    【讨论】:

      猜你喜欢
      • 2015-03-03
      • 2020-10-28
      • 1970-01-01
      • 2016-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-02
      相关资源
      最近更新 更多