简体   繁体   中英

Ambiguous Authentication in Netsuite Token Based API call

I am trying to make SOAP calls to the Netsuite API using Token Based Authentication. I have a C# client that is generated from WDSL and it is sending the following request (with the secrets replaced).

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:messages_2016_2.platform.webservices.netsuite.com" xmlns:urn1="urn:core_2016_2.platform.webservices.netsuite.com">
   <soapenv:Header>
      <urn:partnerInfo>
         <urn:partnerId>[MyAccountId]</urn:partnerId>
      </urn:partnerInfo>
      <urn:applicationInfo>
         <urn:applicationId>[MyApplicationId]</urn:applicationId>
      </urn:applicationInfo>
      <urn:tokenPassport>
         <urn1:account>[MyAccountId]</urn1:account>
         <urn1:consumerKey>[MyConsumerKey]</urn1:consumerKey>
         <urn1:token>[MyTokenId]</urn1:token>
         <urn1:nonce>1574515852</urn1:nonce>
         <urn1:timestamp>1499135589</urn1:timestamp>
         <urn1:signature algorithm="HMAC-SHA1">Ll8DbLvTWsBh/G7UtenErR03OrM=</urn1:signature>
      </urn:tokenPassport>
   </soapenv:Header>
   <soapenv:Body>
      <urn:getDataCenterUrls>
         <urn:account>[MyAccountId]</urn:account>
      </urn:getDataCenterUrls>
   </soapenv:Body>
</soapenv:Envelope>

I am getting the following response

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Body>
      <soapenv:Fault>
         <faultcode>soapenv:Server.userException</faultcode>
         <faultstring>Ambiguous authentication</faultstring>
         <detail>
            <platformFaults:invalidCredentialsFault xmlns:platformFaults="urn:faults_2016_2.platform.webservices.netsuite.com">
               <platformFaults:code>USER_ERROR</platformFaults:code>
               <platformFaults:message>Ambiguous authentication</platformFaults:message>
            </platformFaults:invalidCredentialsFault>
            <ns1:hostname xmlns:ns1="http://xml.apache.org/axis/">partners-java20004.sea.netledger.com</ns1:hostname>
         </detail>
      </soapenv:Fault>
   </soapenv:Body>
</soapenv:Envelope>

I have tried lots of different ways of generating the signature, nonce and timestamp. Currently I have the following:

private string computeNonce()
{
    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);
}

private TokenPassportSignature computeSignature(string accountId, string consumerKey, string consumerSecret, string tokenId, string tokenSecret, string nonce, long timestamp)
{
    string baseString = accountId + "&" + consumerKey + "&" + tokenId + "&" + nonce + "&" + timestamp;
    string key = consumerSecret + "&" + tokenSecret;
    string signature = "";
    var encoding = new System.Text.ASCIIEncoding();
    byte[] keyBytes = encoding.GetBytes(key);
    byte[] baseStringBytes = encoding.GetBytes(baseString);
    using (var hmacSha1 = new HMACSHA1(keyBytes))
    {
        byte[] hashBaseString = hmacSha1.ComputeHash(baseStringBytes);
        signature = Convert.ToBase64String(hashBaseString);
    }
    TokenPassportSignature sign = new TokenPassportSignature();
    sign.algorithm = "HMAC-SHA1";
    sign.Value = signature;
    return sign;
}

Does anyone have any ideas? Thanks!

I was also struggling with this unhelpful error after switching to TBA. Turns out I was still sending the ApplicationInfo property along with the new Consumer Key and Consumer Secret .

I found this on NetSuite's "SuiteAnswers" site and wanted to quote it here for anyone else still having this problem.

Ambiguous Authentication Errors

When you use token-based authentication (TBA) in web services, an ambiguous authentication error response is returned if you use another authentication mechanism together with the TBA header.

You receive this error if besides the TBA header, your request contains an Application ID, a passport object with an email address and a password, or a valid JSESSIONID.

The error occurs in the following cases:

  • If a single web services request contains a combination of the Passport, TokenPassport and SsoPassport complex types.

  • If a single web services request contains both the tokenPassport and the ApplicationInfo complex types, and therefore contains the application ID in the SOAP header.

Source: Token-Based Authentication Errors in Web Services

The getDataCenter calls don't need the passport. I just had the same issue with the mapSso function. It looks like the 2017.1 release made them stricter on not accepting the passport

I know this is an old question, but I struggled with the same issue, and found a working solution.

private static void CreateTokenPassport()
{
    // Initialize the netsuite web service proxy.
    _netSuiteService = new NetSuiteService();

    // A valid Token passport signature consists of the following:
    // Create a base string.
    //     The base string is variable created from concatenating a series of values specific to the request.Use an ampersand as a delimiter between values.
    //     The values should be arranged in the following sequence:
    // NetSuite account ID
    // Consumer key
    // Token
    // Nonce(a unique, randomly generated alphanumeric string, with a minimum of six characters and maximum of 64)
    // Timestamp
    // See: https://system.na1.netsuite.com/app/help/helpcenter.nl?fid=section_4395630653.html#bridgehead_4398049137

    string consumerSecret = "";
    string tokenSecret = "";
    string accountId = "";
    string consumerKey = "";
    string tokenId = "";
    string nonce = ComputeNonce();
    long timestamp = ComputeTimestamp();

    string baseString = string.Format("{0}&{1}&{2}&{3}&{4}", accountId, consumerKey, tokenId, nonce, timestamp);
    string secretKey = string.Format("{0}&{1}", consumerSecret, tokenSecret);

    // Initialize the keyed hash object using the secret key as the key
    HMACSHA256 hashObject = new HMACSHA256(Encoding.UTF8.GetBytes(secretKey));

    // Computes the signature by hashing the data with the secret key as the key
    byte[] signature = hashObject.ComputeHash(Encoding.UTF8.GetBytes(baseString));

    // Base 64 Encode
    string encodedSignature = Convert.ToBase64String(signature);

    TokenPassport tokenPassport = new TokenPassport
    {
        signature = new TokenPassportSignature
        {
            Value = encodedSignature,
            algorithm = "HMAC_SHA256"
        },
        account = accountId,
        consumerKey = consumerKey,
        token = tokenId,
        nonce = nonce,
        timestamp = timestamp
    };

    _netSuiteService = new NetSuiteService
    {
        tokenPassport = tokenPassport
    };
}

Utility Methods:

private static string ComputeNonce()
{
    return Guid.NewGuid().ToString("N");
}

private static long ComputeTimestamp()
{
    return ((long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
}

我不得不修改 XML 并删除 tokenpassport(account,comsumer key,token,nonce,timestamp) 标签并且它起作用了。

I don't know how it's done in C# with HMAC-SHA1 but in Javascript with CryptoJS HMAC-SHA256 you first sign the string and then encode it in Base64:

var baseString = ACCOUNT_ID + "&" + NETSUITE_CONSUMER_KEY + "&" + NETSUITE_TOKEN_ID + "&" + NONCE + "&" + TIMESTAMP;
var key = NETSUITE_CONSUMER_SECRET + '&' + NETSUITE_TOKEN_SECRET;
var HMAC256_Sig = cryptoJS.HmacSHA256(baseString, key);
var HMAC256_Sig_Base64 = cryptoJS.enc.Base64.stringify(HMAC256_Sig);

Then you output it like:

'<platformCore:signature algorithm = "HMAC_SHA256">' + HMAC256_Sig_Base64 + '</platformCore:signature>'

Remove the passport. Sadly, NetSuite fails if you have this in the code when using Token Auth. :/

As per Netsuite SuiteTalk SOAP API document:

Ambiguous Authentication Errors When you use token-based authentication (TBA) in SOAP web services, an ambiguous authentication error response is returned if you use another authentication mechanism together with the TBA header. You receive this error if besides the TBA header, your request contains an Application ID, a passport object with an email address and a password, or a valid JSESSIONID. The error occurs in the following cases:

■ If a single SOAP web services request contains a combination of the Passport, TokenPassport and SsoPassport complex types.

■ If a single SOAP web services request contains both the tokenPassport and the ApplicationInfo complex types, and therefore contains the application ID in the SOAP header.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM