Delphi XE2 - always getting 401 Unauthorized () trying to get OAuth Access Token from Intuit

為{幸葍}努か 提交于 2019-12-24 20:48:04

问题


I am working on the last step of the OAuth dance with Intuit.

This is a Delphi XE2 desktop app and I am using the Indy components.

I am successfully getting my request token from Intuit and the callback from their website is properly redirecting me to our web service after I authorize my app.

Using the returned verifier from Intuit I build my request to get the access token.

I am always getting back a HTTP/1.1 401 Unauthorized error when I make my call to Intuit. If I post the URL I build into Chrome browser I get a "oauth_problem=signature_invalid" message.

Obviously I don't have the fullest grasp of the OAuth thingy but I am pretty darn sure my signature is correct. I use the signature checking tool from Google here: http://oauth.googlecode.com/svn/code/javascript/example/signature.html and my signature always matches. My signature base matches as well.

Here are the keys/values I am using to generate my signature and the URL I am generating from the result:

http method: GET
URL: https://oauth.intuit.com/oauth/v1/get_access_token
singing method: HMAC-SHA1
version: 1.0
ConsumerKey: qyprdGItCTwCAbvx3qNSJR5vDnCOVX
ConsumerSecret: 7IxtFa7aYU2O0PvMGSKsEqaZRvQFoZFaPCtNqg2D
RequestToken: qyprdsHZZft4b2Xskx7dMh1qKOEDw6hrns2Dh7KhN7H8csZt
TokenSecret: AWYbBHrhYhUTYlD1kdPRal2NXRwWMo8qDZ7HDBTQ
TimeStamp: 1392232483
nonce: 3EE3F797E97810F1F0CDF866BEB1AA68

If I plug all the above into Google's signature tool I get the same signature I got from my code. My signature base matches what I get from Google's tool also.

Signature Base: GET&https%3A%2F%2Foauth.intuit.com%2Foauth%2Fv1%2Fget_access_token&oauth_consumer_key%3DqyprdGItCTwCAbvx3qNSJR5vDnCOVX%26oauth_nonce%3D3EE3F797E97810F1F0CDF866BEB1AA68%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1392232483%26oauth_token%3DqyprdsHZZft4b2Xskx7dMh1qKOEDw6hrns2Dh7KhN7H8csZt%26oauth_version%3D1.0
signature : F7m3ii6is226/waoA5wkhrFN/Ak=
signature URL encoded: F7m3ii6is226%2FwaoA5wkhrFN%2FAk%3D

Pasting the URL I build from my code below into Chrome browser give me the oauth_problem error.

URL:  https://oauth.intuit.com/oauth/v1/get_access_token?oauth_consumer_key=qyprdGItCTwCAbvx3qNSJR5vDnCOVX&oauth_token=qyprdsHZZft4b2Xskx7dMh1qKOEDw6hrns2Dh7KhN7H8csZt&oauth_signature_method=HMAC-SHA1&oauth_signature=F7m3ii6is226%2FwaoA5wkhrFN%2FAk%3D&oauth_timestamp=1392232483&oauth_nonce=3EE3F797E97810F1F0CDF866BEB1AA68&oauth_version=1.0&oauth_verifier=dv9xx1q

Keep in mind my code to generate my signature works fine when building the URL for the get_request_token. It's just this last bit to get the all-important access token and access token secret where things are falling apart for me.

I read in the oauth.net documentation (http://oauth.net/core/1.0a/#auth_step3) that this last call should be done via HTTP POST but I see nothing that describes what the post body should contain and nothing on the Intuit Partner Platform describes the POST body either so I am trying a GET instead. I've tried a POST with an empty body with no luck either.

Any advice is appreciated.

Cheers! TJ


回答1:


When you enter a URL into a browser and let it go, it performs a GET request. But like you mentioned, and what the Intuit documentation you linked to says, the get_access_token request is supposed to be done using a POST request instead.

If you read section 5.2 of Intuit's documentation, it says:

OAuth Protocol Parameters are sent from the Consumer to the Service Provider in one of three methods, in order of decreasing preference:

  1. In the HTTP Authorization header as defined in OAuth HTTP Authorization Scheme.
  2. As the HTTP POST request body with a content-type of application/x-www-form-urlencoded.
  3. Added to the URLs in the query part (as defined by RFC3986 section 3).

You are doing #3 when you should be doing #2 instead. The correct POST request would look something like this:

POST /oauth/v1/get_access_token HTTP/1.1
Host: oauth.intuit.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 307

oauth_consumer_key=qyprdGItCTwCAbvx3qNSJR5vDnCOVX&oauth_token=qyprdsHZZft4b2Xskx7dMh1qKOEDw6hrns2Dh7KhN7H8csZt&oauth_signature_method=HMAC-SHA1&oauth_signature=F7m3ii6is226%2FwaoA5wkhrFN%2FAk%3D&oauth_timestamp=1392232483&oauth_nonce=3EE3F797E97810F1F0CDF866BEB1AA68&oauth_version=1.0&oauth_verifier=dv9xx1q

You mention that you are using Indy, so such a POST request can be sent using code like this:

var
  Params: TStringList;
begin
  Params := TStringList.Create;
  try
    Params.Values['oauth_consumer_key'] := 'qyprdGItCTwCAbvx3qNSJR5vDnCOVX';
    Params.Values['oauth_token'] := 'qyprdsHZZft4b2Xskx7dMh1qKOEDw6hrns2Dh7KhN7H8csZt';
    Params.Values['oauth_signature_method'] := 'HMAC-SHA1';
    Params.Values['oauth_signature'] := 'F7m3ii6is226/waoA5wkhrFN/Ak='; // <-- pay attention here!
    Params.Values['oauth_timestamp'] := '1392232483';
    Params.Values['oauth_nonce'] := '3EE3F797E97810F1F0CDF866BEB1AA68';
    Params.Values['oauth_version'] := '1.0';
    Params.Values['oauth_verifier'] := 'dv9xx1q';

    IdHTTP.Post('https://oauth.intuit.com/oauth/v1/get_access_token', Params);
  finally
    Params.Free;
  end;
  ...
end;

Take particular note of the oauth_signature value. What gets sent to the server must be url-encoded:

F7m3ii6is226%2FwaoA5wkhrFN%2FAk%3D

By default, TIdHTTP will url-encode the TStringList data for you when preparing the POST request, so do not put url-encoded data in the TStringList:

F7m3ii6is226/waoA5wkhrFN/Ak=

However, if you want to put url-encoded data in the TStringList, you will have to disable the hoForceEncodeParams flag in the TIdHTTP.HTTPOptions property. TIdHTTP will still send the TStringList data as name-value pairs with & characters in between each pair, but each pair's name and value will be sent as-is without being url-encoded by TIdHTTP.



来源:https://stackoverflow.com/questions/21738305/delphi-xe2-always-getting-401-unauthorized-trying-to-get-oauth-access-token

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!