15

The Question
I need to authenticate to an API which needs OAuth encryption.

I'm in the right direction but I am sure something is wrong with my signature base string. Since the HMACSHA1 Hash is based on a Key and BaseString, I get a wrong oauth_signature.

OAuth Signing Process

So far
I have been able to collect all the required pieces of data, which includes:

  • Consumer Key
  • Consumer Secret
  • Acces Token
  • Acces Secret
  • Sha1Hased Value (Based on Key and Message, where Message is the signature Base string)
  • Signature Base String

The Problem
I get a HTTP(401 Bad Request) returned because of a invalid signature.

note: I'm pretty sure it is how I build my Signature Base String. For info about the API Docs I used, please check bottom page.

The Code

GetOAuthToken (Doing the actual request)

public static string GetAuthorizationToken()
{
    string TimeInSecondsSince1970 = ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
    string Nonce = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(TimeInSecondsSince1970
    + TimeInSecondsSince1970 + TimeInSecondsSince1970));
    HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(GetAppleApiUrl.GetUrl(AppleApiUrl.SESSION_TOKEN));
    httpWebRequest.Method = "GET";

    string consumer_secret = Uri.EscapeDataString(Settings.SettingsManager.consumer_secret);
    string token_secret = Uri.EscapeDataString(Settings.SettingsManager.access_secret);

    string signature_base_string = GetSignatureBaseString(TimeInSecondsSince1970, Nonce);
    string SHA1HASH = GetSha1Hash(consumer_secret + "&" + token_secret, signature_base_string);
                
    string Header =
       "OAuth realm=" + '"' + "ADM" + '"' + "," +
       "oauth_consumer_key=" + '"' + Settings.SettingsManager.consumer_key + '"' + "," +
       "oauth_token=" + '"' + Settings.SettingsManager.access_token + '"' + "," +
       "oauth_signature_method=" + '"' + "HMAC-SHA1" + '"' + "," +
       "oauth_signature= " + '"' + SHA1HASH + '"' + "," + 
       "oauth_timestamp=" + '"' + TimeInSecondsSince1970 + '"' + "," +
       "oauth_nonce=" + '"' + Nonce + '"' + "," +
       "oauth_version=" + '"' + "1.0" + '"' + ",";
   
    httpWebRequest.Headers.Add(HttpRequestHeader.Authorization, Header);
    var Result = httpWebRequest.GetResponse();

    return Result.ToString();
}

GetSha1Hash

public static string GetSha1Hash(string key, string message)
{
    var encoding = new System.Text.ASCIIEncoding();

    byte[] keyBytes = encoding.GetBytes(key);
    byte[] messageBytes = encoding.GetBytes(message);

    string Sha1Result = string.Empty;

    using (HMACSHA1 SHA1 = new HMACSHA1(keyBytes))
    {
        var Hashed = SHA1.ComputeHash(messageBytes);
        Sha1Result = Convert.ToBase64String(Hashed);
    }

    return Sha1Result;
}

GetSignatureBaseString

public static string GetSignatureBaseString(string TimeStamp, string Nonce)
{
    //1.Convert the HTTP Method to uppercase and set the output string equal to this value.
    string Signature_Base_String = "Get";
    Signature_Base_String = Signature_Base_String.ToUpper();

    //2.Append the ‘&’ character to the output string.
    Signature_Base_String = Signature_Base_String + "&";

    //3.Percent encode the URL and append it to the output string.
    string PercentEncodedURL = Uri.EscapeDataString(GetAppleApiUrl.GetUrl(AppleApiUrl.SESSION_TOKEN));
    Signature_Base_String = Signature_Base_String + PercentEncodedURL;

    //4.Append the ‘&’ character to the output string.
    Signature_Base_String = Signature_Base_String + "&";

    //5.append parameter string to the output string.
    Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("oauth_consumer_key=" + Settings.SettingsManager.consumer_key);
    Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&oauth_token=" + Settings.SettingsManager.access_token);
    Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&oauth_signature_method=" +"HMAC-SHA1");
    Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&oauth_timestamp=" + TimeStamp);
    Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&oauth_nonce=" + Nonce);
    Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&oauth_version=" + "1.0");

    return Signature_Base_String;
}

Result (Fiddler) Fiddler Result

API Doc enter image description here

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Nick Prozee
  • 2,823
  • 4
  • 22
  • 49
  • Try using this https://msdn.microsoft.com/en-us/library/system.security.cryptography.hmacsha1(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1 to sign – activebiz Jun 08 '15 at 12:08
  • @PreyashDesai - Same response (400). Did generate a different hash though.. Why would I use HMACSHA1 over SHA1Managed? – Nick Prozee Jun 08 '15 at 12:14
  • 2
    see http://blog.aggregatedintelligence.com/2007/10/fips-validated-cryptographic-algorithms.html SHA1Managed is not FIPS compliant while HMACSHA1 is. But its doesnt fix your problem. – activebiz Jun 08 '15 at 12:21
  • Agreed. Thanks for the tip though – Nick Prozee Jun 08 '15 at 12:26
  • 2
    It looks like you should sort parameters alphabetically in `Header` string and within `GetSignatureBaseString` method: http://stackoverflow.com/questions/4789036/problem-with-oauth-post-with-parameters#comment14485789_4789210 https://dev.twitter.com/oauth/overview/creating-signatures – Leonid Vasilev Jun 10 '15 at 10:25
  • You saved my day, I feel kinda stupid though... Thanks a lot, you earned the bounty! Maybe you can post is as answer? – Nick Prozee Jun 10 '15 at 10:54
  • @NickProzee yes, sure – Leonid Vasilev Jun 10 '15 at 11:05

1 Answers1

8

It looks like you should sort parameters alphabetically in Header string and within GetSignatureBaseString method as described in this comment and Twitter OAuth documentation

Community
  • 1
  • 1
Leonid Vasilev
  • 11,910
  • 4
  • 36
  • 50