【问题标题】:NetSuite C# Console App Web Services Token Authentication Returning "Ambiguous Authentication"NetSuite C# 控制台应用程序 Web 服务令牌身份验证返回“模糊身份验证”
【发布时间】:2019-02-21 15:39:36
【问题描述】:

我正在尝试更新我的集成,以处理对 NetSuite Web 服务强制使用令牌身份验证的情况。但是,我遇到以下问题:

[System.Web.Services.Protocols.SoapException] 不明确的身份验证

我尝试了各种方法,但没有任何改善。如果我使用预先创建的令牌或生成一个令牌,这似乎并不重要。我没有创建“Cookie 容器”,也没有添加标准 Passport 对象。我尝试了几种不同的方法来生成签名和 nonce 值。我什至在 SHA1 和 SHA256 之间切换,认为这可能会有所作为。我将在此处包含我的代码。希望有人能看到我做错了什么。

仅供参考,这里有一些组件来自尝试我在这篇文章中找到的内容:Ambiguous Authentication in Netsuite Token Based API call

static void Main(string[] args) {
    NameValueCollection _dataCollection = ConfigurationManager.AppSettings;
    NSCreds crd = new NSCreds(_dataCollection); /// just building a data object to handle credentials and keys
    NSWS ns = new NSWS(crd, _dataCollection["appId"]); // token passport gets built here

    // now to make a call to just get a single file from the File Cabinet

    RecordRef pullFile = new RecordRef();
    pullFile.type = RecordType.file;
    pullFile.typeSpecified = true;
    pullFile.internalId = _dataCollection["fileId"];
    ReadResponse rres = ns.service.get(pullFile); // this line throws the error highlighted above
}

public NSWS(NSCreds c, String appId) {
    CheckConnectionSecurity(); // makes sure connection security is set to TLS 1.2
    _pageSize = 100;
    service = new NetSuiteService();
    service.Timeout = 1000 * 60 * 60 * 2;
    service.tokenPassport = prepareTokenPassport(c);
    ApplicationInfo appInfo = new ApplicationInfo();
    appInfo.applicationId = appId;
    service.applicationInfo = appInfo;
}

public TokenPassport prepareTokenPassport(NSCreds c) {
    long TimeStamp = ComputeTimestamp();
    String nonce = CreateNonce_1();
    NSToken token = null;
    if (String.IsNullOrEmpty(c.tokenId) && String.IsNullOrEmpty(c.tokenSecret)) {
        token = GetToken(c.customerKey, c); // make calls to NetSuite to generate token data and build custom object
    } else {
        token = new NSToken(c.tokenId,c.tokenSecret); // build custom object from apps settings data
    }
    String signature = ComputeSignature(c.account, c.customerKey, c.customerSecret, token.tokenId, token.tokenSecret, nonce, TimeStamp);

    TokenPassport tokenPassport = new TokenPassport();
    tokenPassport.account = c.account;
    tokenPassport.consumerKey = c.customerKey;
    tokenPassport.token = token.tokenId;
    tokenPassport.nonce = nonce;
    tokenPassport.timestamp = TimeStamp;
    TokenPassportSignature signatureElement = new TokenPassportSignature();
    signatureElement.algorithm = "HMAC-SHA1"; // "HMAC-SHA256";
    signatureElement.Value = signature;
    tokenPassport.signature = signatureElement;

    return tokenPassport;
}

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

private String CreateNonce_1() {
    int length = 20;
    String AllowedChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    StringBuilder nonce = new StringBuilder();
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    byte[] rnd = new byte[1];

    for (int i = 0; i < length; i++) {
        while (true) {
            rng.GetBytes(rnd);
            char c = (char)rnd[0];
            if (AllowedChars.IndexOf(c) != (-1)) {
                nonce.Append(rnd[0]);
                break;
            }
        }
    }

    return nonce.ToString();
}

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

private String CreateNonce_3() {
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
    byte[] data = new byte[20];
    rng.GetBytes(data);
    int value = Math.Abs(BitConverter.ToInt32(data, 0));
    return value.ToString();
}

private string ComputeSignature(String account, String cKey, String cSecret, String token, String tokenSecret, String nonce, long timeStamp) {
    String baseString = String.Format("{0}&{1}&{2}&{3}&{4}",account,cKey,token,nonce,timeStamp);
    String key = String.Format("{0}&{1}", cSecret, tokenSecret);

    // previous method for encoding the signature
    // Mac is a custom object found from another post here
    // EncryptionMethods is an enumeration from that same post
    /*
    //using (var secretKey = new SecretKeySpec(GetBytes(key), EncryptionMethods.HMACSHA256))
    using (var secretKey = new SecretKeySpec(GetBytes(key), EncryptionMethods.HMACSHA1))
    using (Mac mac = new Mac(secretKey, baseString)) {
        return mac.AsBase64();
    }
    */

    //HMACSHA256 hashObject = new HMACSHA256(Encoding.UTF8.GetBytes(key));
    HMACSHA1 hashObject = new HMACSHA1(Encoding.UTF8.GetBytes(key));
    byte[] signature = hashObject.ComputeHash(Encoding.UTF8.GetBytes(baseString));
    string encodedSignature = Convert.ToBase64String(signature);

    return encodedSignature;
}

【问题讨论】:

    标签: c# token netsuite access-token


    【解决方案1】:

    事实证明,问题出在设置应用程序 ID 的同时还指定了令牌通行证。这样做实际上会与不知道使用哪个进行身份验证的系统产生冲突,因为令牌本身在内部引用了应用程序 ID。因此,删除了将应用程序 ID 设置为服务对象的位,一切都开始正常工作。

    【讨论】:

    • 这对我很有帮助。我从 Header 中删除了整个 ... 部分,只留下了 tokenPassport 并且它起作用了
    【解决方案2】:

    尝试使用此代码进行基于令牌的身份验证

    TokenPassport tokenPassport = new TokenPassport();
    tokenPassport.account = account; //Account ID
    tokenPassport.consumerKey = consumerKey; //Consumer Key
    tokenPassport.token = tokenId; // Token ID
    tokenPassport.nonce = nonce;   //It is some calculated value with the help of RNGCryptoServiceProvider class.
    tokenPassport.timestamp = timestamp;
    tokenPassport.signature = signature; // It is TokenPassportSignature  
    

    TokenPassportSignature 还使用帐户 ID、令牌 ID 和令牌秘密。它有一些算法。

    【讨论】:

      猜你喜欢
      • 2021-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-07
      • 1970-01-01
      • 2018-04-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多