问题
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:
- In the HTTP Authorization header as defined in OAuth HTTP Authorization Scheme.
- As the HTTP POST request body with a content-type of application/x-www-form-urlencoded.
- 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