如何使用 OAuth 2.0 客户端凭据流和带有 .net 核心的 JWT 证书连接到 Oracle Netsuite
How do I connect to Oracle Netsuite using OAuth 2.0 Client Credentials Flow and JWT certificate with .net core
我正在尝试使用 Netsuite Rest api。以下是我采取的步骤。
https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_162730264820.html
在 Netsuite 中创建了集成记录
创建自签名证书:
openssl req -x509 -newkey rsa:4096 -sha256 -keyout auth-key.pem -out auth-cert.pem -nodes -days 730
将 auth-cert.pem
添加到 Netsuite
中的集成
尝试调用 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;
}
我 运行 遇到了完全相同的问题,下面是我的解决方法。
实际发送请求的函数如下:
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);
}
这个 returns 状态 200,所以如果它仍然不适合你,我会仔细检查你是否正确设置了所有 NetSuite 0Auth 2.0 设置。
我正在尝试使用 Netsuite Rest api。以下是我采取的步骤。 https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_162730264820.html
在 Netsuite 中创建了集成记录
创建自签名证书:
openssl req -x509 -newkey rsa:4096 -sha256 -keyout auth-key.pem -out auth-cert.pem -nodes -days 730
将
中的集成auth-cert.pem
添加到 Netsuite尝试调用 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;
}
我 运行 遇到了完全相同的问题,下面是我的解决方法。
实际发送请求的函数如下:
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);
}
这个 returns 状态 200,所以如果它仍然不适合你,我会仔细检查你是否正确设置了所有 NetSuite 0Auth 2.0 设置。