2

The objective is to exchange the authorization code for the access and refresh token.

Error:

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

Related code:

$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());

Also tried with state = "state.passed.in" but throws same error.

Can you point out the error in the code snippet. It's using the Feedly API v3 sandbox and the Guzzle HTTP client.

If following the request URL, it throws "get not allowed".

Updated code snippet:

$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());

Error on updated code:

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  

Note: The update code is throwing the same error (after couple of hours) that is

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
Aditya C
  • 899
  • 1
  • 9
  • 21

2 Answers2

1

Starting from the bottom, as per the OAuth 2.0 specification:

The client MUST use the HTTP "POST" method when making access token requests.

(source: section 3.2. The OAuth 2.0 Authorization Framework)

so this explains why navigating to the request URL in a browser will fail (navigating issues a GET and only POST requests are supported).

The next point, is the client authentication, more specifically, how you provide the client_id and client_secret parameters so that the server can validate you're a trusted client application. Again, per the spec, there are two ways this information should be passed:

  1. Through HTTP Basic authentication scheme as defined in [RFC2617] where the client identifier is passed as the username and the client secret is passed as the password. This method must be supported by an OAuth compliant server and is also the recommended way of doing it.*
  2. By including the client credentials in the request-body, usually encoded as application/x-www-form-urlencoded (see example below). This method is optional and may not be available in some OAuth servers.

Example of passing client credentials in the request 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

(source: step four of OAuth Web Application Protocol, click Plain Links in step two to see all the raw HTTP requests in a full authorisation code grant flow)

Now, for the Feedly use case I could not find anything in there documentation about supporting HTTP basic authentication. They do say the following about the parameters required to exchange a code for an access token:

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.

(source: Exchanging an auth code for a refresh token and an access token)

One thing that's surprising is that they seem to allow to pass the client credentials in the URL itself, which is something the OAuth specification clearly forbids:

The parameters (client_id and client_secret) can only be transmitted in the request-body and MUST NOT be included in the request URI.

(source: section 2.3.1. The OAuth 2.0 Authorization Framework)

In conclusion, according to their documentation what you're doing it (passing the parameters in the URL itself) should be possible, unless the documentation is not up-to-date and they already fixed the non-compliance with the specification and no longer support this.

Additionally, there are few things that you're doing that seem wrong. The code parameter is never passed in the Authorisation header, so unless you want to try to pass the client credentials in that header using Basic authentication I would suggest for you to remove this header.

I would also remove the Accept-Encoding header as their docs do not mention supporting anything other than returning a JSON response. If you want to maintain that header, change the value from gzip to application/json.

Finally, you're also not sending any data in the request body, so you may want to also remove the Content-Type header because Feedly might think that if this header is present then the data is on the request instead of the URL.

Community
  • 1
  • 1
João Angelo
  • 56,552
  • 12
  • 145
  • 147
  • The 522 status code is not standard, I know it's used by CloudFare to signal that a server connection timed out, so this may be an issue on Feedly servers. See [Error-522-Connection-timed-out](https://support.cloudflare.com/hc/en-us/articles/200171906-Error-522-Connection-timed-out). – João Angelo Oct 03 '16 at 15:31
  • Thanks for explaining. That was helpful. I updated the code appropriately and am getting a `[status code] 522 [reason phrase] Origin Connection Time-out error`. I have added the updated code and error in the question. I went through the details of the error and found that it is a server side error. Could you shed some light on the error? Is there some fix (in case I am missing something) I can apply from my side? – Aditya C Oct 03 '16 at 15:43
  • The same error has arise with the updated code: `[status code] 400 [reason phrase] Bad Request` after trying for couple of hours. The 522 error is not raised now. Could you please shed some light over this issue? – Aditya C Oct 03 '16 at 17:04
1

Problem: The redirect URI is double-encoded that is I am passing https%253A%252F%252Fdev10.ritepush.com%252Fdashboard, which decodes to https%3A%2F%2Fdev10.ritepush.com%2Fdashboard. I must encode the uri once that is I need to pass https%3A%2F%2Fdev10.ritepush.com%2Fdashboard.

Reason: PHP encodes http requests automatically hence upon applying urlencode to the redirect_uri, I am actually encoding the redirect URI twice but it is decoded only once. Therefore, the encode URI is passed in the request body which results in the error.

Thanks to David Chatenay from Feedly for pointing out the error.

Aditya C
  • 899
  • 1
  • 9
  • 21