我正在与Intuit一起开展OAuth舞蹈的最后一步。
这是一个Delphi XE2桌面应用程序,我使用的是Indy组件。
我成功从Intuit获取请求令牌,并且在我授权我的应用后,他们网站的回调正确地将我重定向到我们的网络服务。
使用Intuit中返回的验证程序构建我的请求以获取访问令牌。
当我拨打Intuit电话时,我总是收到 HTTP / 1.1 401 Unauthorized 错误。如果我将构建的网址发布到Chrome浏览器中,则会收到“ oauth_problem = signature_invalid ”消息。
显然,我没有充分掌握OAuth的东西,但我很确定我的签名是正确的。我在这里使用Google的签名检查工具:http://oauth.googlecode.com/svn/code/javascript/example/signature.html,我的签名总是匹配。我的签名基础也匹配。
以下是我用来生成签名的键/值以及我从结果中生成的URL:
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工具中获得的一致。
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
将我在下面的代码中构建的网址粘贴到Chrome浏览器中会给我oauth_problem错误。
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时,生成我的签名的代码可以正常工作。最后一点是获取最重要的访问令牌和访问令牌秘密,其中事情正在崩溃。
我在oauth.net文档(http://oauth.net/core/1.0a/#auth_step3)中读到,最后一次调用应该通过HTTP POST完成,但我没有看到任何描述帖子正文应该包含的内容,并且Intuit合作伙伴平台上没有任何内容描述POST身体要么所以我正在尝试GET。我已经尝试了一个没有运气的空机身的POST。
感谢任何建议。
干杯! TJ
答案 0 :(得分:0)
当您在浏览器中输入URL并将其移除时,它会执行GET
请求。但是,正如您所提到的,以及您链接的Intuit documentation所说的内容,get_access_token
请求应该使用POST
请求来完成。
如果您阅读了Intuit文档的section 5.2,它会说:
OAuth协议参数以三种方法之一从消费者发送到服务提供商,按优先顺序递减:
- 在OAuth HTTP授权方案中定义的HTTP授权标头中。
- 作为内容类型为application / x-www-form-urlencoded的HTTP POST请求正文。
- 添加到查询部分中的URL(由RFC3986第3节定义)。
醇>
当你应该做#2时,你正在做#3。正确的POST
请求看起来像这样:
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
请求:
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编码的:
F7m3ii6is226%2FwaoA5wkhrFN%2FAk%3D
默认情况下,TIdHTTP
会在准备TStringList
请求时为您的POST
数据进行网址编码,因此请勿将网址编码的数据放入TStringList
:
F7m3ii6is226/waoA5wkhrFN/Ak=
但是,如果要将url编码的数据放在TStringList
中,则必须禁用hoForceEncodeParams
属性中的TIdHTTP.HTTPOptions
标记。 TIdHTTP
仍然会将TStringList
数据作为name-value
对发送,每对中包含&
个字符,但每对的名称和值将按原样发送,而不是网址 - 由TIdHTTP
编码。