I’d rather not use an external library, as I have custom needs I’d like to include in my own library and would like to know exactly how my code works. Thank you for the suggestion though, I have been using the source of some libraries as reference.
That being said - my system time is accurate, so I don’t feel like that would be the issue. I have compared the sent headers between my requests and the console tool/OAuth tool on the doc pages, and they look exactly the same. (except for nonce, timestamp, signature of course) Which leads me to believe the only possible thing that could be wrong is my signature generation. Would you mind taking a look at my generation method and see if anything pops out as wrong to you? Sorry for the giant block of code, the generation process is fairly long. This is in C#.
/* Helper classes */
public class OAuthInfo
{
public string ConsumerKey { get; set; }
public string ConsumerSecret { get; set; }
public string AccessToken { get; set; }
public string AccessSecret { get; set; }
}
/* OAuth Methods */
public static string GenerateOAuthHeader(OAuthInfo Info, string Url)
{
string nonce = new Random().Next(0x0000000, 0x7fffffff).ToString("X8");
string method = "HMAC-SHA1";
string timestamp = ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
string version = "1.0";
var baseFormat2 = "oauth_consumer_key={0}&oauth_signature_method={1}&oauth_nonce={2}" +
"&oauth_timestamp={3}&oauth_token={4}&oauth_version={5}";
var baseString2 = string.Format(baseFormat2,
Info.ConsumerKey,
method,
nonce,
timestamp,
Info.AccessToken,
version);
baseString2 = string.Concat("POST&", UtilityBelt.EncodeRFC3986(Url),
"&", UtilityBelt.EncodeRFC3986(baseString2));
var compositeKey2 = string.Concat(UtilityBelt.EncodeRFC3986(Info.ConsumerSecret),
"&", UtilityBelt.EncodeRFC3986(Info.AccessSecret));
string oauth_signature2;
using (HMACSHA1 hasher = new HMACSHA1(ASCIIEncoding.ASCII.GetBytes(compositeKey2)))
{
oauth_signature2 = Convert.ToBase64String(
hasher.ComputeHash(ASCIIEncoding.ASCII.GetBytes(baseString2)));
}
var headerFormat2 = "OAuth oauth_consumer_key=\"{0}\", oauth_nonce=\"{1}\", " +
"oauth_signature=\"{2}\", oauth_signature_method=\"{3}\", " +
"oauth_timestamp=\"{4}\", oauth_token=\"{5}\", " +
"oauth_version=\"{6}\"";
var authHeader2 = string.Format(headerFormat2,
UtilityBelt.EncodeRFC3986(Info.ConsumerKey),
UtilityBelt.EncodeRFC3986(nonce),
UtilityBelt.EncodeRFC3986(oauth_signature2),
UtilityBelt.EncodeRFC3986(method),
UtilityBelt.EncodeRFC3986(timestamp),
UtilityBelt.EncodeRFC3986(Info.AccessToken),
UtilityBelt.EncodeRFC3986(version)
);
return authHeader2;
}
And the EncodeRFC3986 method:
public static string EncodeRFC3986(string value)
{
if (string.IsNullOrEmpty(value))
return string.Empty;
var encoded = Uri.EscapeDataString(value);
return System.Text.RegularExpressions.Regex
.Replace(encoded, "(%[0-9a-f][0-9a-f])", c => c.Value.ToUpper())
.Replace("(", "%28")
.Replace(")", "%29")
.Replace("$", "%24")
.Replace("!", "%21")
.Replace("*", "%2A")
.Replace("'", "%27")
.Replace("%7E", "~");
}
Perhaps the issue is encoding somewhere or something, but when comparing my code to other libraries it looks like I encode properly in all the right places, so I’m really not sure where an error could be.