对 Feedly API 的授权请求会向 Guzzle 抛出错误请求?
Authorization request to Feedly API throws a bad request with Guzzle?
objective是用授权码换取访问刷新令牌
错误:
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"
但抛出同样的错误。
能否指出代码段中的错误。它使用 Feedly API v3 沙箱和 Guzzle HTTP 客户端。
如果遵循请求 URL,它会抛出 "get not allowed"。
更新的代码片段:
$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 规范,从底部开始:
The client MUST use the HTTP "POST" method when making access token
requests.
(来源:第 3.2 节。The OAuth 2.0 Authorization Framework)
所以这解释了为什么在浏览器中导航到请求 URL 会失败(导航问题 GET
并且仅支持 POST
请求)。
下一点是客户端身份验证,更具体地说,您如何提供 client_id
和 client_secret
参数,以便服务器可以验证您是受信任的客户端应用程序。同样,根据规范,应该通过两种方式传递此信息:
- 通过 [RFC2617] 中定义的 HTTP 基本身份验证方案,其中客户端标识符作为用户名传递,客户端机密作为密码传递。此方法必须由 OAuth 兼容服务器支持,也是推荐的方法。*
- 通过在 request-body 中包含客户端凭据,通常编码为
application/x-www-form-urlencoded
(请参见下面的示例)。此方法是可选的,在某些 OAuth 服务器中可能不可用。
在请求中传递客户端凭据的示例 body:
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 基本身份验证的内容。他们确实说了以下关于交换访问令牌代码所需的参数:
Note: these parameters can either be passed in the URL, as form values, or in a JSON document. If you use a JSON document, make sure you pass the “Content-Type: application/json” header in the request.
(来源:Exchanging an auth code for a refresh token and an access token)
令人惊讶的一件事是它们似乎允许在 URL 本身中传递客户端凭据,这是 OAuth 规范明确禁止的事情:
The parameters (client_id and client_secret) can only be transmitted in the request-body and MUST NOT be included in the
request URI.
(来源:第 2.3.1 节。The OAuth 2.0 Authorization Framework)
总之,根据他们的文档,您正在做的事情(在 URL 本身中传递参数)应该是可能的,除非文档不是 up-to-date 并且他们已经修复了non-compliance 符合规范,不再支持此规范。
此外,您所做的一些事情似乎是错误的。 code
参数从未在 Authorisation
header 中传递,因此除非您想尝试使用基本身份验证在 header 中传递客户端凭据,否则我建议您删除这个 header.
我还会删除 Accept-Encoding
header,因为他们的文档除了返回 JSON 响应外没有提到支持任何其他内容。如果要保持 header,请将值从 gzip
更改为 application/json
。
最后,您也没有在请求 body 中发送任何数据,因此您可能还想删除 Content-Type
header 因为 Feedly 可能认为如果这个 header 存在则数据在请求中而不是 URL.
问题: 重定向 URI 是双重编码的,即我传递的 https%253A%252F%252Fdev10.ritepush.com%252Fdashboard
,解码为 https%3A%2F%2Fdev10.ritepush.com%2Fdashboard
。我必须对 uri 进行一次编码,因为我需要传递 https%3A%2F%2Fdev10.ritepush.com%2Fdashboard
.
原因: PHP 自动对 http 请求进行编码,因此在将 urlencode
应用于 redirect_uri
后,我实际上对重定向 URI 进行了两次编码但它只被解码一次。因此,在导致错误的请求正文中传递了编码 URI。
感谢来自 Feedly 的 David Chatenay 指出错误。
objective是用授权码换取访问刷新令牌
错误:
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"
但抛出同样的错误。
能否指出代码段中的错误。它使用 Feedly API v3 沙箱和 Guzzle HTTP 客户端。
如果遵循请求 URL,它会抛出 "get not allowed"。
更新的代码片段:
$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 规范,从底部开始:
The client MUST use the HTTP "POST" method when making access token requests.
(来源:第 3.2 节。The OAuth 2.0 Authorization Framework)
所以这解释了为什么在浏览器中导航到请求 URL 会失败(导航问题 GET
并且仅支持 POST
请求)。
下一点是客户端身份验证,更具体地说,您如何提供 client_id
和 client_secret
参数,以便服务器可以验证您是受信任的客户端应用程序。同样,根据规范,应该通过两种方式传递此信息:
- 通过 [RFC2617] 中定义的 HTTP 基本身份验证方案,其中客户端标识符作为用户名传递,客户端机密作为密码传递。此方法必须由 OAuth 兼容服务器支持,也是推荐的方法。*
- 通过在 request-body 中包含客户端凭据,通常编码为
application/x-www-form-urlencoded
(请参见下面的示例)。此方法是可选的,在某些 OAuth 服务器中可能不可用。
在请求中传递客户端凭据的示例 body:
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 基本身份验证的内容。他们确实说了以下关于交换访问令牌代码所需的参数:
Note: these parameters can either be passed in the URL, as form values, or in a JSON document. If you use a JSON document, make sure you pass the “Content-Type: application/json” header in the request.
(来源:Exchanging an auth code for a refresh token and an access token)
令人惊讶的一件事是它们似乎允许在 URL 本身中传递客户端凭据,这是 OAuth 规范明确禁止的事情:
The parameters (client_id and client_secret) can only be transmitted in the request-body and MUST NOT be included in the request URI.
(来源:第 2.3.1 节。The OAuth 2.0 Authorization Framework)
总之,根据他们的文档,您正在做的事情(在 URL 本身中传递参数)应该是可能的,除非文档不是 up-to-date 并且他们已经修复了non-compliance 符合规范,不再支持此规范。
此外,您所做的一些事情似乎是错误的。 code
参数从未在 Authorisation
header 中传递,因此除非您想尝试使用基本身份验证在 header 中传递客户端凭据,否则我建议您删除这个 header.
我还会删除 Accept-Encoding
header,因为他们的文档除了返回 JSON 响应外没有提到支持任何其他内容。如果要保持 header,请将值从 gzip
更改为 application/json
。
最后,您也没有在请求 body 中发送任何数据,因此您可能还想删除 Content-Type
header 因为 Feedly 可能认为如果这个 header 存在则数据在请求中而不是 URL.
问题: 重定向 URI 是双重编码的,即我传递的 https%253A%252F%252Fdev10.ritepush.com%252Fdashboard
,解码为 https%3A%2F%2Fdev10.ritepush.com%2Fdashboard
。我必须对 uri 进行一次编码,因为我需要传递 https%3A%2F%2Fdev10.ritepush.com%2Fdashboard
.
原因: PHP 自动对 http 请求进行编码,因此在将 urlencode
应用于 redirect_uri
后,我实际上对重定向 URI 进行了两次编码但它只被解码一次。因此,在导致错误的请求正文中传递了编码 URI。
感谢来自 Feedly 的 David Chatenay 指出错误。