This post was really helpful. I finally broke down and read all of https://dev.twitter.com/docs/auth/creating-signature to understand what was happening with the parameters and the auth string
I modifed the awesome code from @LethalChicken
public static string MakeTwitterCall(string resource_url, IEnumerable<KeyValuePair<string, string>> RequestParameters)
{
// oauth application keys
var oauth_token = “----”;
var oauth_token_secret = “-----”;
var oauth_consumer_key = “-----”;
var oauth_consumer_secret = “-----”;
// oauth implementation details
var oauth_version = "1.0";
var oauth_signature_method = "HMAC-SHA1";
// unique request details
var oauth_nonce = Convert.ToBase64String(
new System.Text.ASCIIEncoding().GetBytes(DateTime.Now.Ticks.ToString()));
var timeSpan = DateTime.UtcNow
- new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
var oauth_timestamp = Convert.ToInt64(timeSpan.TotalSeconds).ToString();
//setup the parameters that we will be putting in the authorization
var authorizationParameters = new List<KeyValuePair<string, string>>() {
new KeyValuePair<string, string>("oauth_consumer_key",oauth_consumer_key),
new KeyValuePair<string, string>("oauth_nonce",oauth_nonce),
new KeyValuePair<string, string>("oauth_signature_method",oauth_signature_method),
new KeyValuePair<string, string>("oauth_timestamp",oauth_timestamp),
new KeyValuePair<string, string>("oauth_token",oauth_token),
new KeyValuePair<string, string>("oauth_version",oauth_version)
};
//combine and sort all parameters as per https://dev.twitter.com/docs/auth/creating-signature
var allParameters = authorizationParameters.Union(RequestParameters).OrderBy(tmp => tmp.Key);
//put all paramneters into a & delimited string and make sure our values are % escaped
var baseString = string.Join("&", allParameters.Select(p => string.Format("{0}={1}", p.Key, Uri.EscapeDataString(p.Value))));
//finish the base string
baseString = string.Concat("GET&", Uri.EscapeDataString(resource_url), "&", Uri.EscapeDataString(baseString));
var compositeKey = string.Concat(Uri.EscapeDataString(oauth_consumer_secret),
"&", Uri.EscapeDataString(oauth_token_secret));
//use our composite key to get the auth signature
string oauth_signature=null;
using (System.Security.Cryptography.HMACSHA1 hasher = new System.Security.Cryptography.HMACSHA1(System.Text.ASCIIEncoding.ASCII.GetBytes(compositeKey)))
{
oauth_signature = Convert.ToBase64String(
hasher.ComputeHash(System.Text.ASCIIEncoding.ASCII.GetBytes(baseString)));
}
// create the request header
var headerFormat = "OAuth oauth_nonce=\"{0}\", oauth_signature_method=\"{1}\", " +
"oauth_timestamp=\"{2}\", oauth_consumer_key=\"{3}\", " +
"oauth_token=\"{4}\", oauth_signature=\"{5}\", " +
"oauth_version=\"{6}\"";
//get the actual string version of the auth header and its values
var authHeader = string.Format(headerFormat,
Uri.EscapeDataString(oauth_nonce),
Uri.EscapeDataString(oauth_signature_method),
Uri.EscapeDataString(oauth_timestamp),
Uri.EscapeDataString(oauth_consumer_key),
Uri.EscapeDataString(oauth_token),
Uri.EscapeDataString(oauth_signature),
Uri.EscapeDataString(oauth_version)
);
System.Net.ServicePointManager.Expect100Continue = false;
//add our query string parameters to our url
resource_url += "?" + string.Join("&", RequestParameters.Select(p => string.Format("{0}={1}", p.Key, Uri.EscapeDataString(p.Value))));
//create our request
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(resource_url);
//set our info
request.Headers.Add("Authorization", authHeader);
request.Method = "GET";
request.ContentType = "application/x-www-form-urlencoded";
//get the response and return the result from the stream
using (var response = (System.Net.HttpWebResponse)request.GetResponse())
{
using (var reader = new System.IO.StreamReader(response.GetResponseStream()))
{
return reader.ReadToEnd();
}
}
}