gpt4 book ai didi

c# - 如何从 .net 核心客户端生成 JWT Bearer Flow OAuth 访问 token ?

转载 作者:行者123 更新时间:2023-12-05 03:53:03 25 4
gpt4 key购买 nike

我无法让我的 .NET Core 客户端为需要“JWT Bearer Flow”类型的 OAuth 的 salesforce 端点生成 OAuth 访问 token 。

似乎有有限的 .NET Framework 示例显示 .NET 客户端执行此操作,但没有一个显示 .NET Core 客户端执行此操作例如 https://salesforce.stackexchange.com/questions/53662/oauth-jwt-token-bearer-flow-returns-invalid-client-credentials

所以在我的 .NET Core 3.1 应用程序中,我生成了一个自签名证书,在加载证书时将私钥添加到上面示例的代码中,但是在这一行发生了 System.InvalidCastExceptionexception 异常:

var rsa = certificate.GetRSAPrivateKey() as RSACryptoServiceProvider;

异常(exception):

System.InvalidCastException: 'Unable to cast object of type 'System.Security.Cryptography.RSACng' to type 'System.Security.Cryptography.RSACryptoServiceProvider'.'

看起来这个私钥在 JWT Bearer Flow 中用作签名的一部分,并且 RSACryptoServiceProvider 可能不像在 .NET Framework 中那样在 .NET Core 中使用。

我的问题是 - 在 .NET Core 中实际上有一种方法可以为 OAuth JWT Bearer Flow 生成访问 token 吗?

我正在使用的完整代码:

static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var token = GetAccessToken();
}

static dynamic GetAccessToken()
{
// get the certificate
var certificate = new X509Certificate2(@"C:\temp\cert.pfx");

// create a header
var header = new { alg = "RS256" };

// create a claimset
var expiryDate = GetExpiryDate();
var claimset = new
{
iss = "xxxxxx",
prn = "xxxxxx",
aud = "https://test.salesforce.com",
exp = expiryDate
};

// encoded header
var headerSerialized = JsonConvert.SerializeObject(header);
var headerBytes = Encoding.UTF8.GetBytes(headerSerialized);
var headerEncoded = ToBase64UrlString(headerBytes);

// encoded claimset
var claimsetSerialized = JsonConvert.SerializeObject(claimset);
var claimsetBytes = Encoding.UTF8.GetBytes(claimsetSerialized);
var claimsetEncoded = ToBase64UrlString(claimsetBytes);

// input
var input = headerEncoded + "." + claimsetEncoded;
var inputBytes = Encoding.UTF8.GetBytes(input);

// signature
var rsa = (RSACryptoServiceProvider) certificate.GetRSAPrivateKey();

var cspParam = new CspParameters
{
KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName,
KeyNumber = rsa.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2
};
var aescsp = new RSACryptoServiceProvider(cspParam) { PersistKeyInCsp = false };
var signatureBytes = aescsp.SignData(inputBytes, "SHA256");
var signatureEncoded = ToBase64UrlString(signatureBytes);

// jwt
var jwt = headerEncoded + "." + claimsetEncoded + "." + signatureEncoded;

var client = new WebClient();
client.Encoding = Encoding.UTF8;
var uri = "https://login.salesforce.com/services/oauth2/token";
var content = new NameValueCollection();

content["assertion"] = jwt;
content["grant_type"] = "urn:ietf:params:oauth:grant-type:jwt-bearer";

string response = Encoding.UTF8.GetString(client.UploadValues(uri, "POST", content));

var result = JsonConvert.DeserializeObject<dynamic>(response);

return result;
}

static int GetExpiryDate()
{
var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
var currentUtcTime = DateTime.UtcNow;

var exp = (int)currentUtcTime.AddMinutes(4).Subtract(utc0).TotalSeconds;

return exp;
}

static string ToBase64UrlString(byte[] input)
{
return Convert.ToBase64String(input).TrimEnd('=').Replace('+', '-').Replace('/', '_');
}

最佳答案

好吧 - 事实证明,向 stackoverflow 发帖会让大脑的齿轮转动起来。

答案最终是深入研究以在此处找到类似问题并使用 x509certificate2 sign for jwt in .net core 2.1 中的解决方案

我最终替换了以下代码:

var cspParam = new CspParameters
{
KeyContainerName = rsa.CspKeyContainerInfo.KeyContainerName,
KeyNumber = rsa.CspKeyContainerInfo.KeyNumber == KeyNumber.Exchange ? 1 : 2
};
var aescsp = new RSACryptoServiceProvider(cspParam) { PersistKeyInCsp = false };
var signatureBytes = aescsp.SignData(inputBytes, "SHA256");
var signatureEncoded = ToBase64UrlString(signatureBytes);

使用 System.IdentityModel.Tokens.Jwt nuget 包的代码:

var signingCredentials = new X509SigningCredentials(certificate, "RS256");
var signature = JwtTokenUtilities.CreateEncodedSignature(input, signingCredentials);

解决后的完整代码:

static void Main(string[] args)
{
Console.WriteLine("Hello World!");
var token = GetAccessToken();
}

static dynamic GetAccessToken()
{
// get the certificate
var certificate = new X509Certificate2(@"C:\temp\cert.pfx");

// create a header
var header = new { alg = "RS256" };

// create a claimset
var expiryDate = GetExpiryDate();
var claimset = new
{
iss = "xxxxx",
prn = "xxxxx",
aud = "https://test.salesforce.com",
exp = expiryDate
};

// encoded header
var headerSerialized = JsonConvert.SerializeObject(header);
var headerBytes = Encoding.UTF8.GetBytes(headerSerialized);
var headerEncoded = ToBase64UrlString(headerBytes);

// encoded claimset
var claimsetSerialized = JsonConvert.SerializeObject(claimset);
var claimsetBytes = Encoding.UTF8.GetBytes(claimsetSerialized);
var claimsetEncoded = ToBase64UrlString(claimsetBytes);

// input
var input = headerEncoded + "." + claimsetEncoded;
var inputBytes = Encoding.UTF8.GetBytes(input);

var signingCredentials = new X509SigningCredentials(certificate, "RS256");
var signature = JwtTokenUtilities.CreateEncodedSignature(input, signingCredentials);

// jwt
var jwt = headerEncoded + "." + claimsetEncoded + "." + signature;

var client = new WebClient();
client.Encoding = Encoding.UTF8;
var uri = "https://test.salesforce.com/services/oauth2/token";
var content = new NameValueCollection();

content["assertion"] = jwt;
content["grant_type"] = "urn:ietf:params:oauth:grant-type:jwt-bearer";

string response = Encoding.UTF8.GetString(client.UploadValues(uri, "POST", content));

var result = JsonConvert.DeserializeObject<dynamic>(response);

return result;
}

static int GetExpiryDate()
{
var utc0 = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
var currentUtcTime = DateTime.UtcNow;

var exp = (int)currentUtcTime.AddMinutes(4).Subtract(utc0).TotalSeconds;

return exp;
}

static string ToBase64UrlString(byte[] input)
{
return Convert.ToBase64String(input).TrimEnd('=').Replace('+', '-').Replace('/', '_');
}

关于c# - 如何从 .net 核心客户端生成 JWT Bearer Flow OAuth 访问 token ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61869035/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com