Delphi XE2-尝试从Intuit获取OAuth访问令牌时总是得到401 Unauthorized() [英] Delphi XE2 - always getting 401 Unauthorized () trying to get OAuth Access Token from Intuit
问题描述
我正在与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:
- 在OAuth HTTP授权方案中定义的HTTP授权标头中。
- 作为具有内容类型的HTTP POST请求正文
- 已添加到查询部分的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
将对进行网址编码在准备
数据,因此请勿将url编码的数据放入 POST
请求时为您提供TStringList 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屋!