c# OAuth and Signatures

11,107

The problem with the code is here.

In the GenerateSignature function, you are setting variable:

var signatureKey = string.Format("{0}&{1}", ClientId, "");

This should be:

var signatureKey = string.Format("{0}&{1}", ClientSecret , "");
Share:
11,107
r3plica
Author by

r3plica

SOreadytohelp

Updated on June 04, 2022

Comments

  • r3plica
    r3plica almost 2 years

    I am trying to use the Vimeo API and I have been having some problems generating the signature....

    Basically I have this class

    public class OAuthParameters
    {
        public string RedirectUrl { get; set; }
    
        public string ClientId { get; set; }
        public string ClientSecret { get; set; }
    
        protected string NormalizeParameters(SortedDictionary<string, string> parameters)
        {
            StringBuilder sb = new StringBuilder();
    
            var i = 0;
            foreach (var parameter in parameters)
            {
                if (i > 0)
                    sb.Append("&");
    
                sb.AppendFormat("{0}={1}", parameter.Key, parameter.Value);
    
                i++;
            }
    
            return sb.ToString();
        }
    
        private string GenerateBase(string nonce, string timeStamp, Uri url)
        {
            var parameters = new SortedDictionary<string, string>
            {
                {"oauth_consumer_key", ClientId},
                {"oauth_signature_method", "HMAC-SHA1"},
                {"oauth_timestamp", timeStamp},
                {"oauth_nonce", nonce},
                {"oauth_version", "1.0"}
            };
    
            var sb = new StringBuilder();
            sb.Append("GET");
            sb.Append("&" + Uri.EscapeDataString(url.AbsoluteUri));
            sb.Append("&" + Uri.EscapeDataString(NormalizeParameters(parameters)));
            return sb.ToString();
        }
    
        public string GenerateSignature(string nonce, string timeStamp, Uri url)
        {
            var signatureBase = GenerateBase(nonce, timeStamp, url);
            var signatureKey = string.Format("{0}&{1}", ClientId, "");
            var hmac = new HMACSHA1(Encoding.ASCII.GetBytes(signatureKey));
            return Convert.ToBase64String(hmac.ComputeHash(new ASCIIEncoding().GetBytes(signatureBase)));
        }
    }
    

    The code that calls this is in another class and it has this method

    public string GetAuthorizationUrl(string Url)
    {
        var sb = new StringBuilder();
        var nonce = Guid.NewGuid().ToString();
        var timeStamp = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds.ToString();
        var signature = parameters.GenerateSignature(nonce, timeStamp, new Uri(Url));
    
        sb.Append(GenerateQueryStringOperator(sb.ToString()) + "oauth_consumer_key=" + Uri.EscapeDataString(parameters.ClientId));
        sb.Append("&oauth_nonce=" + Uri.EscapeDataString(nonce));
        sb.Append("&oauth_timestamp=" + Uri.EscapeDataString(timeStamp));
        sb.Append("&oauth_signature_method=" + Uri.EscapeDataString("HMAC-SHA1"));
        sb.Append("&oauth_version=" + Uri.EscapeDataString("1.0"));
        sb.Append("&oauth_signature=" + Uri.EscapeDataString(signature));
    
        return Url + sb.ToString();
    }
    
    private string GenerateQueryStringOperator(string currentUrl)
    {
        if (currentUrl.Contains("?"))
            return "&";
        else
            return "?";
    }
    

    the Url I am passing (to get my auth token) is https://vimeo.com/oauth/request_token but whenever I call this I get an error stating

    401 Unauthorized - Invalid signature - The oauth_signature passed was not valid.
    

    This is driving me nuts. I can't see what could be causing the issue.

    If anyone can give me some help, that would be great.

    Update 1

    Someone stated that using Uri.EscapeDataString was not the correct way to encode my strings. I was using this function before I moved the EscapeDataString:

        protected string UrlEncode(string unencodedString)
        {
            var encodedString = new StringBuilder();
            var unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
    
            foreach (char symbol in unencodedString)
                if (unreservedChars.IndexOf(symbol) != -1)
                    encodedString.Append(symbol);
                else
                    encodedString.Append('%' + String.Format("{0:X2}", (int)symbol));
    
            return encodedString.ToString();
        }
    

    but this still not help. Also using http://hueniverse.com/oauth/guide/authentication/ did not provide any insights into what is causing my issue :(

    Update 2

    So, I ran the code through hueniverse and found that my timestamp was not exact (it had decimal places) so I changed the way I generate my time stamp using this function:

        public string GenerateTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0, 0));
            string timeStamp = ts.TotalSeconds.ToString();
            timeStamp = timeStamp.Substring(0, timeStamp.IndexOf("."));
            return timeStamp;
        }
    

    So now when I look at my base signature I get:

    POST&https%3A%2F%2Fvimeo.com%2Foauth%2Frequest_token%2F&oauth_consumer_key%3Dmykey%26oauth_nonce%3D66c80d6b-9ff6-404b-981b-56f40f356a31%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1370444366%26oauth_token%3D%26oauth_version%3D1.0
    

    and if I compare it to the one generated from hueniverse, it generates:

    POST&https%3A%2F%2Fvimeo.com%2Foauth%2Frequest_token%2F&oauth_consumer_key%3Dmykey%26oauth_nonce%3D00b81872-688b-4184-a978-206e5fbcc531%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1370446860%26oauth_token%3D%26oauth_version%3D1.0
    

    If the length of the generated strings are anything to go by, then they are exact. My next test is to create it exactly the same timestamp and all to see if they generate the same signature....

  • r3plica
    r3plica almost 11 years
    hey mate, I updated my question but I have already tried the two suggestions you have made to no avail :(
  • Dashron
    Dashron almost 11 years
    This was a best guess, Unfortunately I have no c# experience. Maybe one of the recommended c# libraries can help you