C# OAuth returns invalid Oauth_signature but works in Postman

Viewed 36

I have already read tons of articles, implementations and searched the web but I couldn't find anything useful and surely missing something really simple here with "SIGNATURE".

Scenario: I need to make an automation tool that will take a conversation Id (in my case), check for the status in the API response and then decide next course of actions. i.e. send a notification etc.

The problem: The same API works well in Postman but when I try to implement it in C#.NET, it always give me the same result given below. Even though I've tried different codes and libraries.

Error:

{"code":"0005","debugMessage":"The server will not process the request because it is unauthenticated. Reason: oauth_problem=signature_invalid&oauth_problem_advice=the oauth_signature is invalid"}

Code - Calling Function:

string domainUrl = @"https://xyz-my-server-domain.com/";
string accountId = "XXXXXXXX";
string appKey = "05119901595a443d8XXXXXXXXX";
string appSecret = "54fdc15a0fXXXXXX";
string token = "ae4e2979958b401c97XXXXXXXXXX";
string tokenSecret = "4b075XXXXXXXXXXXX";


Uri uri = new Uri(domainUrl + @"/conversations/conversation/search");
OAuthBase oauthBase = new OAuthBase();
string nonce = oauthBase.GenerateNonce();
string timeStamp = oauthBase.GenerateTimeStamp();
string authSignature = "";


/// <summary>
/// Everything seems ok but still something is wrong here...
/// </summary>
string encodedUrl = GetOAuthSignature(uri, appKey, appSecret, token, tokenSecret, timeStamp, nonce, out authSignature);


var client = new RestClient(encodedUrl);
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
var body = @"{ ..... my request body ..... }";
request.AddParameter("application/json", body, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

GetOAuthSignature Function:

private static string GetOAuthSignature(Uri uri, string consumerKey, string consumerSecret, string token, string tokenSecret, string timeStamp, string nonce, out string signature)
{
    OAuthBase oAuth = new OAuthBase();

    string normalizedUrl = "";
    string normalizedRequestParameters = "";

    /// <summary>
    /// Allowed Signature Methods: HMAC-SHA256 and HMAC-SHA1 only for this API.
    /// </summary>
    string signatureStr = oAuth.GenerateSignature(uri, consumerKey, string.Empty, token, string.Empty, "POST", timeStamp, nonce, OAuthBase.SignatureTypes.HMACSHA1, out normalizedUrl, out normalizedRequestParameters);

    signatureStr = HttpUtility.UrlEncode(signatureStr);

    StringBuilder sb = new StringBuilder(uri.ToString());
    sb.AppendFormat("?oauth_consumer_key={0}&", consumerKey);
    sb.AppendFormat("oauth_token={0}&", token);

    /// <summary>
    /// Allowed Signature Methods: HMAC-SHA256 and HMAC-SHA1 only for this API.
    /// </summary>
    sb.AppendFormat("oauth_signature_method={0}&", "HMAC-SHA1");
    sb.AppendFormat("oauth_timestamp={0}&", timeStamp);
    sb.AppendFormat("oauth_nonce={0}&", nonce);
    sb.AppendFormat("oauth_version={0}&", "1.0");
    sb.AppendFormat("oauth_signature={0}", signatureStr);

    signature = signatureStr;

    return sb.ToString();
}

I suspect, I'm doing something wrong in GetOAuthSignature.

1 Answers

I've managed to resolve it myself. I continued reading random articles on OAuth Signature and found that RFC3986 specifications require encoding in upper case.

Failing Reason: My signature had encoding in lower case. i.e.

**************zHqKh6Yk %2b cKzwA1F8 %3d

while this API specification only supports UPPER case:

**************zHqKh6Yk %2B cKzwA1F8 %3D

Later I found IETF draft with same information (missed it before a couple of times also I had literally no idea about this method specification). Just go to section 3.6. Percent Encoding, it's mentioned:

The two hexadecimal characters used to represent encoded characters MUST be upper case.

Related