What is the BaseString for request_token?


#1

I’m implementing Twitter Login for our website and I’m stuck at an early step: signing the request. Everything makes sense up to the point where “Creating the signature base string” ([Creating the signature base string documentation][1]) in the documentation.

Since the signature is IN the parameter string, how am I supposed to send the hash that includes it?

At any rate, my request looks something like this so far:
POST https://api.twitter.com/oauth/request_token
(with an empty POST body and the following Authorization header - line-feeds inserted for clarity):
OAuth oauth_callback=“http%3A%2F%2F – the callback url”,
oauth_consumer_key=“ourKey”,
oauth_nonce=“random-32-bits-base-64-encoded”,
oauth_signature=“Not sure what goes here”,
oauth_signature_method=“HMAC-SHA1”,
oauth_timestamp="[timestamp]",
oauth_version=“1.0”

I understand from the documentation that I am to create a string that contains all the parameters, percent encode that, then run it through the HMAC-SHA1 hash algorithm using the ConsumerKey&ConsumerSecret percent encoding each side as the key. I’m just not sure what to send as the string to encode.

Do I just send all the other parameters (except for oauth_signature)? Do I run them all together separated by a comma/space? Is there some other separator? Do I include the quotes?

Guidance on the subject would be most appreciated.

Thanks,
Owen
[1]: https://dev.twitter.com/oauth/overview/creating-signatures


#2

Ah, I responded to your other question (which I’ve now deleted as this is more detailed, and to cut down duplication) - seems you’ve already checked the docs! :smile:

So I would take a look at the example Signature base string included in that page. You’ll see that all of the symbols like = are encoded, and there are no quotes around the values. You can indeed leave out oauth_signature.

If that isn’t clear, another approach would be to take a look at how implementations like Twitter4J or tweepy are achieving this.


#3

Thanks. (Couldn’t see how to delete the other question).

So, for the authorization header I have the following template:
String strAuthFormat = “oauth_callback=”{0}", " +
“oauth_consumer_key=”{1}", " +
“oauth_nonce=”{2}", " +
“oauth_signature=”{3}", " +
“oauth_signature_method=”{4}", " +
“oauth_timestamp=”{5}", " +
“oauth_version=”{6}"";

And for the base string (the string that will be encrypted) I have:
String strBaseFormat = “oauth_callback={0}&” +
“oauth_consumer_key={1}&” +
“oauth_nonce={2}&” +
“oauth_signature_method={3}&” +
“oauth_timestamp={4}&” +
“oauth_version={5}”;

And I’m assuming the encrypting key is the consumer_key followed by ampersand followed by the consumer_secret…


#4

I’m getting a 401 error (not authorized) when I attempt to call the request_token api.
My header is formatted as in my last post.
I’m creating the base string from the format and then prepending "POST&https://api.twitter.com/


#5

I’m getting the same error when trying to call the request_token api.
it will be great if someone answer how to fix it


#6

The rest of the error (in the response body) is:
Failed to validate oauth signature and token


#7

Here’s the c# code that’s not working (secret keys withheld, guidState is a guid):

  String strAuthFormat = "OAuth oauth_callback=\"{0}\", " +
                         "oauth_consumer_key=\"{1}\", " +
                         "oauth_nonce=\"{2}\", " +
                         "oauth_signature=\"{3}\", " +
                         "oauth_signature_method=\"{4}\", " +
                         "oauth_timestamp=\"{5}\", " +
                         "oauth_version=\"{6}\"";
  String strBaseFormat = "OAuth oauth_callback={0}&" +
                         "oauth_consumer_key={1}&" +
                         "oauth_nonce={2}&" +
                         "oauth_signature_method={3}&" +
                         "oauth_timestamp={4}&" +
                         "oauth_version={5}";
  String strURL = strSecureUrl + "ExternalAuthentication.aspx?site=twitter";
  String strRedirect = "https://api.twitter.com/oauth/request_token";
  String strClientID = "The Consumer Key";
  String strClientSecret = "The Consumer Secret";
  String strSignKey = "";
  strSignKey = Uri.EscapeDataString(strClientID) + "&" +Uri.EscapeDataString(strClientSecret);

  var Timestamp = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
  var oauth_Timestamp = Convert.ToInt64(Timestamp.TotalSeconds).ToString();
  String strBaseString = String.Format(strBaseFormat,
                                          strURL, 
                                          strClientID, 
                                          guidState.ToString().Replace("-",""),
                                          "HMAC-SHA1", 
                                          oauth_Timestamp, 
                                          "1.1");
  strBaseString = string.Concat("POST&", Uri.EscapeDataString(strRedirect), "&", Uri.EscapeDataString(strBaseString));
  String strSignature = "";
  using (HMACSHA1 hasher = new HMACSHA1(ASCIIEncoding.ASCII.GetBytes(strSignKey)))
  {
     strSignature = Convert.ToBase64String(hasher.ComputeHash(ASCIIEncoding.ASCII.GetBytes(strBaseString)));
  }
  String strAuthHeader = string.Format(strAuthFormat,
                                        strURL,
                                        strClientID,
                                        guidState.ToString().Replace("-",""),
                                        strSignature,
                                        "HMAC-SHA1",
                                        oauth_Timestamp,
                                        "1.1");
  ServicePointManager.Expect100Continue = false;
  HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(strRedirect);
  objRequest.Headers.Add("Authorization", strAuthHeader);
  objRequest.Method = "POST";
  objRequest.ContentType = "application/x-www-form-urlencoded";
  using (Stream objStream = objRequest.GetRequestStream())
  {
     byte[] objContent = ASCIIEncoding.ASCII.GetBytes("");
     objStream.Write(objContent, 0, 0);
  }
  WebResponse objResponse = null;
  try
  {
     objResponse = objRequest.GetResponse();
     objResponse.Close();
  }
  catch (WebException e)
  {
     Response.Write(e.Message);
     var objErrResponse = (WebResponse)e.Response;
     StreamReader objSR = new StreamReader(objErrResponse.GetResponseStream());
     String strResponse = objSR.ReadToEnd();
     Response.Write("<br/>" + strResponse);
  }

The header generated is (with XXXXXX’s overwritten on part of the key and signature):
OAuth oauth_callback=“https%3A%2F%2Fdev.oursite.com%2Fsecure%2FExternalAuthentication.aspx%3Fsite%3Dtwitter”,oauth_consumer_key=“qqGXXXXXXXXXxFg”,oauth_nonce=“19b37a1aa13b43b58691dfd484cf3ad7”,oauth_signature_method=“HMAC-SHA1”,oauth_timestamp=“1421182206”,oauth_version=“1.1”,oauth_signature=“wZ2zGGtXXXXXXXX1Ttg=”

Any clues what’s wrong?
–Owen