[Delphi] Could not authenticate with OAuth for /1/statuses/update.json


#1

I’m getting through every step of the OAuth process and get the access token. Go to post a tweet and get ‘Could not authenticate with OAuth’. I post the tweet right after getting the access token.

Double slashed lines are the comments. They are the results of the variable directly above them for analysis. Also note I’ve tried every type of combination every which way.

function TTwitter.SendRequest(Method: String; URI: String; Params: Array of String): ISuperObject;
const
  AuthHeaderFormat = 'OAuth oauth_nonce="%s", oauth_signature_method="%s", oauth_timestamp="%s", oauth_consumer_key="%s", oauth_token="%s", oauth_signature="%s", oauth_version="%s"';
var
  oauth_nonce,
  oauth_timestamp,
  SignKey,
  BaseString,
  Signature,
  AuthHeader,
  ResposeStr : String;
  BaseStringParams : Array of String;
  JSON : ISuperObject;
  I, J : Integer;
  EmptyParams : TStringList;
begin
  oauth_nonce := GenerateNonce;
  oauth_timestamp := GenerateTimeStamp;
  SignKey := fConsumerSecret + '&' + fAccessToken;
  J := 0;
  SetLength(BaseStringParams, Length(Params) + 6);
  For I := Low(Params) To High(Params) Do
    begin
    BaseStringParams[J] := Params[I];
    Inc(J);
  end;
  BaseStringParams[J] := 'oauth_consumer_key=' + fConsumerKey;
  BaseStringParams[J + 1] := 'oauth_nonce=' + oauth_nonce;
  BaseStringParams[J + 2] := 'oauth_signature_method=' + oauth_signature_method;
  BaseStringParams[J + 3] := 'oauth_token=' + fOAuthToken;
  BaseStringParams[J + 4] := 'oauth_timestamp=' + oauth_timestamp;
  BaseStringParams[J + 5] :=  'oauth_version=' + oauth_version;
  BaseString := CreateBaseString('POST', URI, BaseStringParams);
  //POST&http%3A%2F%2Fapi.twitter.com%2F1%2Fstatuses%2Fupdate.json&oauth_consumer_key%3DXXXXXXXXXXXXXXXX%26oauth_nonce%3D0F95A680F2231F689C702FCECAD1D449%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1314988258%26oauth_token%3DXXXXXX-XXXXXXXXXXXXXXXX%26oauth_version%3D1.0%26status%3DThis%2520is%2520a%2520test.
  Signature := HMAC_SHA1_Sign(BaseString, SignKey);
  AuthHeader := Format(AuthHeaderFormat, [oauth_nonce,
                                          oauth_signature_method,
                                          oauth_timestamp,
                                          fConsumerkey,
                                          fOAuthToken,
                                          Signature,
                                          oauth_version]);
  //OAuth oauth_nonce="0F95A680F2231F689C702FCECAD1D449", oauth_signature_method="HMAC-SHA1", oauth_timestamp="1314988258", oauth_consumer_key="XXXXXXXXXXXXXXXXXX", oauth_token="XXXXXX-XXXXXXXXXXXXXXXX", oauth_signature="XXXXXXXXXXXXXXXXXXXXX", oauth_version="1.0"
  fHTTP.Request.CustomHeaders.AddValue('Authorization', AuthHeader);
  EmptyParams := TStringList.Create;
  Try
    URI := URI + '?';
    For I := Low(Params) To High(Params) Do
      begin
      URI := URI + Params[I] + '&';
    end;
    URI := Copy(URI, 1, Length(URI) - 1);
    //http://api.twitter.com/1/statuses/update.json?status=This%20is%20a%20test.
    ResposeStr := fHTTP.Post(URI, EmptyParams);
    JSON := SO(ResposeStr);
    Result := JSON;
  Except
    On E:EIdHTTPProtocolException Do
      begin
      MessageBox(0, PChar(E.ErrorMessage), '', 0);
      //{"error":"Could not authenticate with OAuth.","request":"\/1\/statuses\/update.json?status=This%20is%20a%20test."}
    end;
  end;
  EmptyParams.Free;
end;

Called like this:

SendRequest('POST', 'http://api.twitter.com/1/statuses/update.json', ['status=' + urlEncodeRFC3986(Text)]);

#2

I’m having the same exact problem… and still can’t find a fix for it…


#3

Are you able to execute a GET-based request with the access token? Perhaps to /1/account/verify_credentials.json ?

The error “could not authenticate with OAuth” indicates that your signature and credentials are syntactically correct, but there is another issue with the authentication – likely the oauth_token being used is expired in some way. Your commented examples of the signature base string and headers all look correct to me.


#4

No, I get the same issue with a GET based request for /1/account/verify_credentials.json as well. How could the oauth_token expire when I get it only seconds before?


#5

Let’s examine more on how you’re obtaining the token – is there any way you’re persisting the wrong value for oauth_token and oauth_token_secret? (Considering that the fields are named the same for both a request token and an access token).


#6

I replace the request tokens and token secret with the access token. It is verified because the oauth_token for the access token has the user id prepended to it.

Edit: Breakpointed at the point when the access token info is received and when I use the token in the SendRequest method. They are the correct tokens.

I also want to point out that I don’t receive any more specific errors such as if I purposely screw up the signature expecting a “Invalid Signature” error.


#7

So I found out that on this line:

fHTTP.Request.CustomHeaders.AddValue(‘Authorization’, AuthHeader);

The way the component handles custom headers is that the delimiter for text is a comma. This means the program was adding a \r\n (new line) after every parameter I included for OAuth. No wonder it failed! Twitter wasn’t even receiving the parameters!

Since I was checking the header before I added it to the headers I didn’t even think that was the problem.

Thank you for your help! I probably wouldn’t have delved into the code this deeply otherwise.


#8

well i didn’t I’m not familiar with the whole codes thing so can you help


#9

Can i have TTwitter components? with all procedure used in the example? Kindly.