Delphi XE2-尝试从Intuit获取OAuth访问令牌时总是得到401 Unauthorized() [英] Delphi XE2 - always getting 401 Unauthorized () trying to get OAuth Access Token from Intuit

查看:131
本文介绍了Delphi XE2-尝试从Intuit获取OAuth访问令牌时总是得到401 Unauthorized()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在与Intuit一起进行OAuth舞蹈的最后一步。

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

这是Delphi XE2桌面应用程序,我正在使用Indy组件。

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

我已经从Intuit成功获取了我的请求令牌,并且在授权我的应用程序之后,他们网站的回调将我正确地重定向到了我们的网络服务。

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.

使用Intuit返回的验证程序,我构建了获取访问令牌的请求。

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

我总是返回 HTTP / 1.1 401致电Intuit时发生未经授权的错误。如果我将我发布的网址发布到Chrome浏览器中,则会收到 oauth_problem = signature_invalid 消息。

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.

很明显,我没有最完整的消息对OAuth的掌握有点麻烦,但是我非常想知道我的签名是正确的。我在这里使用Google的签名检查工具: http://oauth.googlecode .com / svn / code / javascript / example / signature.html 和我的签名始终匹配。我的签名库也匹配。

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.

这是我用于生成签名的键/值以及从结果生成的URL:

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

如果我将以上所有内容插入Google的签名工具,则会得到与我相同的签名我的代码。我的签名库也与我从Google工具获得的签名库相匹配。

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

粘贴我从代码中构建的URL进入Chrome浏览器,请输入以下oauth_problem错误。

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

请记住我的代码以生成我的代码构建get_request_token的URL时,签名可以正常工作。这只是获得所有重要访问令牌和访问令牌密钥的最后一环,这一切对我来说都是崩溃的。

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.

我在oauth.net文档中读过(<最后一次调用的href = http://oauth.net/core/1.0a/#auth_step3 rel = nofollow> http://oauth.net/core/1.0a/#auth_step3 )应该通过HTTP POST完成,但我看不到任何描述帖子正文应包含的内容,而Intuit Partner Platform上也没有描述POST正文,因此我尝试使用GET。我试过了一个没有运气也没有运气的POST。

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.

任何建议都值得赞赏。

干杯!
TJ

Cheers! TJ

推荐答案

当您在浏览器中输入URL并放开它时,它会执行 GET 请求。但是就像您提到的那样,您链接到的 Intuit文档说的是, get_access_token 请求应该使用 POST 请求完成。

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.

如果您阅读Intuit文档的第5.2 节,则其内容为:

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


OAuth协议参数以三种递减的方式从消费者发送到服务提供者,以降低优先级的顺序:

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


  1. 在OAuth HTTP授权方案中定义的HTTP授权标头中。

  2. 作为具有内容类型的HTTP POST请求正文

  3. 已添加到查询部分的URL中(如RFC3986第3节所定义)。


您应该执行#3,而应该执行#2。正确的 POST 请求如下所示:

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

您提到您正在使用Indy,因此可以发送这样的 POST 请求使用这样的代码:

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;

请特别注意 oauth_signature 的值。发送到服务器的内容必须经过url编码:

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

F7m3ii6is226%2FwaoA5wkhrFN%2FAk%3D

默认情况下, TIdHTTP 将对进行网址编码在准备 POST 请求时为您提供TStringList 数据,因此请勿将url编码的数据放入 TStringList

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=

但是,如果要将url编码的数据放入 TStringList ,则必须禁用<$ TIdHTTP.HTTPOptions 属性中的c $ c> hoForceEncodeParams 标志。 TIdHTTP 仍将 TStringList 数据作为 name-value 发送每对之间使用& 字符,但是每对的名称和值将按原样发送,而不会由 TIdHTTP进行url编码

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.

这篇关于Delphi XE2-尝试从Intuit获取OAuth访问令牌时总是得到401 Unauthorized()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆