Use the <Login Audit Trail>'s detail column for mo...
# integrations
b
Use the Login Audit Trail's detail column for more information
✔️ 1
r
@battk @scottvonduhn We are getting UnknownAlgorithm message in Login Audit Trail but we never had this issue before with HMAC-SHA256. We are using the same code from past 2 years
b
share the code
r
@battk private TokenPassport computeSignature(string deploy       , string consumerKey       , string consumerSecret       , string tokenId       , string tokenSecret       , string nonce       , long timestamp       , string script       , string method       , string resource)     {       string baseString = “deploy=” + deploy + “&”         + “oauth_consumer_key=” + consumerKey + “&”         + “oauth_nonce=” + nonce + “&”         + “oauth_signature_method=HMAC-SHA256&”         + “oauth_timestamp=” + timestamp.ToString() + “&”         + “oauth_token=” + tokenId + “&”         + “oauth_version=1.0&”         + “script=” + script;       //string baseStringEncode = HttpUtility.UrlEncode(baseString);       string baseStringEncode = System.Net.WebUtility.UrlEncode(baseString);       string fullURL = method + “&”         + System.Net.WebUtility.UrlEncode(this._endpoint + resource) + “&”         + baseStringEncode;       string key = consumerSecret + “&” + tokenSecret;       string signature = “”;       var encoding = new System.Text.ASCIIEncoding();       byte[] keyBytes = encoding.GetBytes(key);       byte[] baseStringBytes = encoding.GetBytes(fullURL);       using (var hmacSha256 = new HMACSHA256(keyBytes))       {         byte[] hashBaseString = hmacSha256.ComputeHash(baseStringBytes);         signature = Convert.ToBase64String(hashBaseString);       }       string signatureEncode = System.Net.WebUtility.UrlEncode(signature);       TokenPassport sign = new TokenPassport();       sign.algorithm = “HMAC-SHA256";       sign.Value = signatureEncode;       return sign;     }
b
not enough code, that only looks like the code for the signature
need the rest of the header
r
@battk private string buildAuth(string value       , string nonce       , string algorithm       , string consumerKey       , string tokenId       , long timestamp       , string realm)     {       string auth = @“OAuth oauth_signature=“”" + value         + @“”",oauth_version=“”" + “1.0”         + @“”",oauth_nonce=“”" + nonce         + @“”",oauth_signature_method=“”" + algorithm         + @“”",oauth_consumer_key=“”" + consumerKey         + @“”",oauth_token=“”" + tokenId         + @“”",oauth_timestamp=“”" + timestamp.ToString()         + @“”",realm=“”" + realm + “\”“;       return auth;     }
b
and what do you call buildAuth with, specifically the algorithm
its probably bad that its not passed to computeSignature
r
@battk This is the complete code
using System; using RestSharp; using RestSharp.Authenticators; using System.Security.Cryptography; using Newtonsoft.Json; public class NetSuiteClient { public NetSuiteClient() { } private RestRequest buildClient(string resource, Method method, string script, string deploy) { _client = new RestClient(this._endpoint); RestRequest request = new RestRequest(resource, method); string creds = CredManager.ReadNetSuite("netsuite").AcctID ?? "notfound"; if (creds == "notfound") { using (Logger _out = new Logger("info")) { _out.info("ERROR", "NetSuiteClient", "No NetSuite Creds set up.", 0, 0); } return null; } //Realm is our instance of NetSuite CredManager.NetSuiteCredential nsc = CredManager.ReadNetSuite("netsuite"); string realm = nsc.AcctID; //Set the keys and secrets string consumerKey = nsc.ConsumerKey.ConvertToUnsecureString(); string consumerSecret = nsc.ConsumerSecret.ConvertToUnsecureString(); string tokenId = nsc.TokenID.ConvertToUnsecureString(); string tokenSecret = nsc.TokenSecret.ConvertToUnsecureString(); //Compute the nonce string nonce = computeNonce(); //Compute the timestamp long timestamp = computeTimestamp(); TokenPassport sign = computeSignature(deploy , consumerKey , consumerSecret , tokenId , tokenSecret , nonce , timestamp , script , "POST" , resource); string auth = buildAuth(sign.Value , nonce , sign.algorithm , consumerKey , tokenId , timestamp , realm); request.AddQueryParameter("script", script); request.AddQueryParameter("deploy", deploy); request.AddParameter("Authorization", auth, ParameterType.HttpHeader); return request; } private TokenPassport computeSignature(string deploy , string consumerKey , string consumerSecret , string tokenId , string tokenSecret , string nonce , long timestamp , string script , string method , string resource) { string baseString = "deploy=" + deploy + "&" + "oauth_consumer_key=" + consumerKey + "&" + "oauth_nonce=" + nonce + "&" + "oauth_signature_method=HMAC-SHA256&" + "oauth_timestamp=" + timestamp.ToString() + "&" + "oauth_token=" + tokenId + "&" + "oauth_version=1.0&" + "script=" + script; //string baseStringEncode = HttpUtility.UrlEncode(baseString); string baseStringEncode = System.Net.WebUtility.UrlEncode(baseString); string fullURL = method + "&" + System.Net.WebUtility.UrlEncode(this._endpoint + resource) + "&" + baseStringEncode; string key = consumerSecret + "&" + tokenSecret; string signature = ""; var encoding = new System.Text.ASCIIEncoding(); byte[] keyBytes = encoding.GetBytes(key); byte[] baseStringBytes = encoding.GetBytes(fullURL); using (var hmacSha256 = new HMACSHA256(keyBytes)) { byte[] hashBaseString = hmacSha256.ComputeHash(baseStringBytes); signature = Convert.ToBase64String(hashBaseString); } string signatureEncode = System.Net.WebUtility.UrlEncode(signature); TokenPassport sign = new TokenPassport(); sign.algorithm = "HMAC-SHA256"; sign.Value = signatureEncode; return sign; } private string buildAuth(string value , string nonce , string algorithm , string consumerKey , string tokenId , long timestamp , string realm) { string auth = @"OAuth oauth_signature=""" + value + @""",oauth_version=""" + "1.0" + @""",oauth_nonce=""" + nonce + @""",oauth_signature_method=""" + algorithm + @""",oauth_consumer_key=""" + consumerKey + @""",oauth_token=""" + tokenId + @""",oauth_timestamp=""" + timestamp.ToString() + @""",realm=""" + realm + "\""; return auth; } private string computeNonce() { //Use System.Security.Cryptography for RNGCryptoServiceProvider RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); byte[] data = new byte[20]; rng.GetBytes(data); int value = Math.Abs(BitConverter.ToInt32(data, 0)); return value.ToString(); } private long computeTimestamp() { return ((long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds); } }
b
what you shared looks ok
probably need to look at TokenPassport
r
@battk We are using this code from past 2 years without any issue and issue started to happen only after midnight
b
most likely case is you implemented the sha-256 method wrong
today is the day only sha-256 works in tba
r
@battk Actually I am not from .Net background. Previous developer with the company has implemented it. If it is implemented wrong from the beginning, it should not work at the first place. I have raised a case with NetSuite support for this issue. @battk Thank you for your help.
@battk Do you see if I need to configure something on the Integration record
b
meh, tried out your code
works as expected
implemented a TokenPassport that basically only has a public Value and algorithm
r
@battk strange it worked for you but not for our environment
b
the only thing i really implemented was TokenPassport
what does your TokenPassport look like
r
@battk sorry for my limited knowledge of .Net, is it not there in the code which I have mentioned above
b
Copy code
TokenPassport sign = new TokenPassport();
whats a TokenPassport?
its a bad idea to touch code in a language that you dont know
i only know c# as basically java
r
@battk Definition of TokenPassport
public partial class TokenPassport     {       private string algorithmField;       private string valueField;       public string algorithm       {         get         {           return this.algorithmField;         }         set         {           this.algorithmField = value;         }       }       public string Value       {         get         {           return this.valueField;         }         set         {           this.valueField = value;         }       }
s
Is that code based on the SuiteTalk Sample Applications from this page: https://www.netsuite.com/portal/developers/resources/suitetalk-sample-applications.shtml
One thing to be aware of with SOAP is to make sure you are using a fairly recent WSDL. It is possible that Netsuite disabled any WSDL’s that won’t be supported in 2021.2 along with the HMAC-SHA1 deprecation. Just speculation, but if I were using SOAP, I’d be updating my WSDL’s from time to time to stay current.
r
@scottvonduhn I will take a look
b
s
though an outdated WSDL would probably not cause an UnknownAlgorithm error
b
go change all the hardcoded parameters
r
@scottvonduhn @battk We rebuild our project and it worked. We did not change anything. Thank you both for your help.
s
Netsuite aborted the test window, which is why it is working now
In other words, don’t be lulled into a false sense of security. When the next test window for this comes around, you will break again.
r
@scottvonduhn Thanks for the update. I will modify my code then