如何使用 OAuth 2.0 客户端凭证流和带有 .net core 的 JWT 证书连接到 Oracle Netsuite

问题描述 投票:0回答:2

我正在尝试使用 Netsuite Rest api。以下是我采取的步骤。 https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_162730264820.html

  1. 在 Netsuite 中创建集成记录

  2. 创建自签名证书:

    openssl req -x509 -newkey rsa:4096 -sha256 -keyout auth-key.pem -out auth-cert.pem -nodes -days 730
    
  3. auth-cert.pem
    添加到 Netsuite 中的集成

  4. 尝试调用 TokenUrl 端点来获取访问令牌

当我调用

GetNetsuiteJwtAccessToken(string signedJWTAssertion)
从 TokenUrl 获取访问令牌时,我不断收到错误请求(状态代码 400)。

static void Main(string[] args)
    //static string Scope = "rest_webservices"; 
    //static string Aud = "https://<Tenant>-sb1.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/token";
    //static string TokenUrl = "https://<Tenant>-sb1.suitetalk.api.netsuite.com/services/rest/auth/oauth2/v1/token";
//static string TenantName = "<Tenant>";

    //static string ClientId = "<ClientId>";
    //static string Issuer = ClientId;
    //static string ClientSecret = "<Client Secret>";
    //static string AppId = "<AppId>";
    //static string Kid = "<Key from the Netsuite for the uploaded Cert">;
{
      var jwt= GenerateNetsuiteJWTFromPEMFile("auth-key.pem");
      var accessToken = GetNetsuiteJwtAccessToken(signedJWTAssertion: jwt);
               
}

public static string GenerateNetsuiteJWTFromPEMFile(string PEMFile)
{
            var tokenHandler = new JwtSecurityTokenHandler();

            var rsaPem = File.ReadAllText(PEMFile);

            var privatekey = RSA.Create();
            privatekey.ImportFromPem(rsaPem);

            var key = new RsaSecurityKey(privatekey);
            //key.KeyId = Kid;

            var signingCredentials = new SigningCredentials(
                key: key,
                algorithm: SecurityAlgorithms.RsaSha256 
            );
            //signingCredentials.Key.KeyId = Kid;


            var Now = DateTimeOffset.UtcNow;
            var Exp = Now.AddMinutes(30).ToUnixTimeSeconds();
            var Iat = Now.ToUnixTimeSeconds();

            var jwt = new SecurityTokenDescriptor
            {
                Issuer = Issuer,
                Claims = new Dictionary<string, object>()
                {
                    ["iss"] = Issuer,
                    ["scope"] = Scope,
                    ["aud"] = Aud,
                    ["exp"] = Exp,
                    ["iat"] = Iat                
                },

                SigningCredentials = signingCredentials

            };
            var jws = tokenHandler.CreateToken(jwt);
            var encoded = new JwtSecurityTokenHandler().WriteToken(jws);
            return encoded;
        }

 public static string GetNetsuiteJwtAccessToken(string signedJWTAssertion)
        {
            string accessToken;

              HttpClient _httpClient = new HttpClient();

            _httpClient.DefaultRequestHeaders.Clear();

            var requestParams = new List<KeyValuePair<string, string>>
            {
                new KeyValuePair<string, string>("grant_type", "client_credentials"),
                new KeyValuePair<string, string>("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"),
                new KeyValuePair<string, string>("assertion", signedJWTAssertion)
            };

            using (var content = new FormUrlEncodedContent(requestParams))
            {
                var response = _httpClient.PostAsync(TokenUrl, content).Result;
                var responseContent = response.Content.ReadAsStringAsync().Result;
                accessToken = responseContent;
            }

            return accessToken;
        }
oauth jwt client netsuite credentials
2个回答
7
投票

我遇到了完全相同的问题,这是我解决的方法。

下面的函数实际发送请求:

public async Task GetAccessToken()
        {
            string tokenBaseUrl = <token endpoint URL>;
            string consumerKey = <consumer key/client ID from NetSuite>;

           // Don't worry about _configurationService below        
           string assertion = new JwtToken(_configurationService).GetJwtToken(consumerKey);

            var parameters = new Dictionary<string, string>
            {
                {"grant_type", "client_credentials" },
                {"client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" },
                {"client_assertion", assertion } // use client_assertion, not assertion, the example provided in the docs uses the former 
            };

            var content = new FormUrlEncodedContent(parameters);

            var response = await _httpClient.PostAsync(tokenBaseUrl, content);
        }

您可以在最后从响应中提取访问令牌。我只是还没有做到这一点。

现在奇迹发生在下面的函数中,它创建了 JWT 令牌:

public string GetJwtToken()
        {

            try
            {
                // Read the content of a private key PEM file, PKCS8 encoded. 
                string privateKeyPem = File.ReadAllText(<file path to private key>);

                // keep only the payload of the key. 
                privateKeyPem = privateKeyPem.Replace("-----BEGIN PRIVATE KEY-----", "");
                privateKeyPem = privateKeyPem.Replace("-----END PRIVATE KEY-----", "");

                // Create the RSA key.
                byte[] privateKeyRaw = Convert.FromBase64String(privateKeyPem);
                RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
                provider.ImportPkcs8PrivateKey(new ReadOnlySpan<byte>(privateKeyRaw), out _);
                RsaSecurityKey rsaSecurityKey = new RsaSecurityKey(provider);

                // Create signature and add to it the certificate ID provided by NetSuite.
                var signingCreds = new SigningCredentials(rsaSecurityKey, SecurityAlgorithms.RsaSha256);
                signingCreds.Key.KeyId = <certificate ID provided when auth cert uploaded to NetSuite>;

                // Get issuing timestamp.
                var now = DateTime.UtcNow;

                // Create token.
                var handler = new JsonWebTokenHandler();

                string token = handler.CreateToken(new SecurityTokenDescriptor
                {
                    Issuer = <consumer key/client ID>,
                    Audience = <token endpoint URL>,
                    Expires = now.AddMinutes(5),
                    IssuedAt = now,
                    Claims = new Dictionary<string, object> { { "scope", new[] { "rest_webservices" } } },
                    SigningCredentials = signingCreds
                });

                return token;
            }
            catch (Exception e)
            {
                throw new <custom exception>("Creating JWT bearer token failed.", e);
            }

这会返回状态 200,因此如果它仍然对您不起作用,我会仔细检查您是否正确设置了所有 NetSuite 0Auth 2.0 设置。


0
投票

我发现在本地存储中安装证书然后使用以下代码生成 JWT 比分发 *.pem 文件并从中读取更安全。

private string GetJwtToken() {
// load certificate from the store
var store = new X509Store("My", StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);

var certificates = store.Certificates.Find(
    X509FindType.FindBySubjectName, "<<subjectNameHere>>", 
    validOnly: false);
var certificate = certificates[0];
var signingCreds = new X509SigningCredentials(certificate);

signingCreds.Key.KeyId = _config.ClientId; // this is the certificate Id that is generated by Netsuite when you upload the cert.pem file

// Get issuing timestamp.
var now = DateTime.UtcNow;

// Create token.
var tokenHandler = new JwtSecurityTokenHandler();

var tokenDescriptor = new SecurityTokenDescriptor
{
    Issuer = _config.ClientSecret, // same as the ConsumerSecret
    Audience = $"{_config.BaseUrl}/services/rest/auth/oauth2/v1/token",
    Expires = now.AddMinutes(5),
    IssuedAt = now,
    Claims = new Dictionary<string, object> {
                                                { "scope", new[] { "rest_webservices", "restlets" } }
                                            },
    SigningCredentials = signingCreds
};

var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenText = tokenHandler.WriteToken(token);

return tokenText;
}
© www.soinside.com 2019 - 2024. All rights reserved.