I am trying to call Netsuite api using oath 1.0 from C#.
It works in postman. used postman generated values (timestamp, nonce, signagurebase) in c# then it worked. HMAC-SHA256 is being here.
Generated Signature in code doesn't work, getting "INVALID_LOGIN_ATTEMPT" message.
Main method:
string consumerKey = "******";
string TokenId = "******";
string ConsumerSecret = "******";
string TokenSecret = "******";
string realm = "****";
string signatureMethod = "HMAC-SHA256";
string apiUrl = "https://test-test.api.netsuite.com/app/site/hosting/restlet.nl?script=941&deploy=1&FC=SGD&TC=USD&ED=02/11/2022";
string baseUrl = "https://test-sb1.restlets.api.netsuite.com/app/site/hosting/restlet.nl";
public void run()
{
var timeStamp = ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString();
var nonce = Convert.ToBase64String(Encoding.UTF8.GetBytes(timeStamp));
var signatureBase = GetSignatureBaseString(timeStamp, nonce);
var oauthSignature = encryptSignatureBase(signatureBase, ConsumerSecret, TokenSecret);
var client = new RestClient(apiUrl);
var request = new RestRequest("", Method.Get);
//test with postman values, which is working fine.
//timeStamp = "1669601987";
//nonce = "5D1TNfnx5oW";
//oauthSignature = "C8TXCdaT1If0Od6BU4T8yqukRjFSAz%2BtrO3cZi8lUvw%3D";
var oauthStr = $"OAuth realm =\"{realm}\",oauth_consumer_key=\"{consumerKey}\",oauth_token=\"{TokenId}\",oauth_signature_method=\"HMAC-SHA256\",oauth_timestamp=\"{timeStamp}\",oauth_nonce=\"{nonce}\",oauth_version=\"1.0\",oauth_signature=\"{oauthSignature}\"";
request.AddHeader("Authorization", oauthStr);
request.AddHeader("Content-Type", "application/json");
request.AddHeader("Cookie", "NS_ROUTING_VERSION=LAGGING");
request.AddParameter("application/json", "{}", ParameterType.RequestBody);
var response = client.Execute(request);
Console.WriteLine(response.Content);
}
generateSignature base string
string GetSignatureBaseString(string timestamp, string nounce)
{
//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 + "&";
SortedDictionary<string, string> paramStrings = new SortedDictionary<string, string>();
paramStrings.Add("script", "941");
paramStrings.Add("deploy", "1");
paramStrings.Add("FC", "SGD");
paramStrings.Add("TC", "USD");
paramStrings.Add("ED", "02/11/2022");
//3.Percent encode the URL and append it to the output string.
string PercentEncodedURL = Uri.EscapeDataString(baseUrl);
Signature_Base_String = Signature_Base_String + PercentEncodedURL;
//4.Append the ‘&’ character to the output string.
Signature_Base_String = Signature_Base_String + "&";
//5.append OAuth parameter string to the output string.
var parameters = new SortedDictionary<string, string>
{
{"oauth_consumer_key", consumerKey},
{"oauth_token", TokenId },
{"oauth_signature_method", signatureMethod},
{"oauth_timestamp", timestamp},
{"oauth_nonce", nounce},
{"oauth_version", "1.0"}
};
//6.append parameter string to the output string.
foreach (KeyValuePair<string, string> elt in paramStrings)
{
parameters.Add(elt.Key, elt.Value);
}
bool first = true;
foreach (KeyValuePair<string, string> elt in parameters)
{
if (first)
{
Signature_Base_String = Signature_Base_String + Uri.EscapeDataString(elt.Key + "=" + elt.Value);
first = false;
}
else
{
Signature_Base_String = Signature_Base_String + Uri.EscapeDataString("&" + elt.Key + "=" + elt.Value);
}
}
return Signature_Base_String;
}
encrypt using Mac-sha256
public string encryptSignatureBase(string signatureBase, string consumerSecret, string tokenSecret)
{
HMACSHA256 hmacsha1 = new HMACSHA256();
hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", UrlEncode(consumerSecret), UrlEncode(tokenSecret)));
byte[] dataBuffer = Encoding.ASCII.GetBytes(signatureBase);
byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer);
return Convert.ToBase64String(hashBytes);
}
string unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
protected string UrlEncode(string value)
{
StringBuilder result = new StringBuilder();
foreach (char symbol in value)
{
if (unreservedChars.IndexOf(symbol) != -1)
result.Append(symbol);
else
result.Append('%' + String.Format("{0:X2}", (int)symbol));
}
return result.ToString();
}