C# 如何从.net核心客户端生成JWT承载流OAuth访问令牌?
我无法让我的.NET Core客户端为salesforce端点生成OAuth访问令牌,该端点需要类型为“JWT承载流”的OAuth 似乎有有限的.NET Framework示例显示.NET客户端正在执行此操作,但是没有一个示例显示.NET核心客户端正在执行此操作 例如 因此,在我的.NET Core 3.1应用程序中,我生成了一个自签名证书,在加载证书时将私钥添加到上述示例的代码中,但在此行发生System.InvalidCastExceptionexception异常:C# 如何从.net核心客户端生成JWT承载流OAuth访问令牌?,c#,.net-core,oauth,jwt,salesforce,C#,.net Core,Oauth,Jwt,Salesforce,我无法让我的.NET Core客户端为salesforce端点生成OAuth访问令牌,该端点需要类型为“JWT承载流”的OAuth 似乎有有限的.NET Framework示例显示.NET客户端正在执行此操作,但是没有一个示例显示.NET核心客户端正在执行此操作 例如 因此,在我的.NET Core 3.1应用程序中,我生成了一个自签名证书,在加载证书时将私钥添加到上述示例的代码中,但在此行发生System.InvalidCastExceptionexception异常: var rsa =
var rsa = certificate.GetRSAPrivateKey() as RSACryptoServiceProvider;
例外情况:
System.InvalidCastException: 'Unable to cast object of type 'System.Security.Cryptography.RSACng' to type 'System.Security.Cryptography.RSACryptoServiceProvider'.'
这个私钥似乎是作为签名的一部分在JWT承载流中使用的,也许在.NET核心中没有像在.NET Framework中那样使用RSACryptoServiceProvider
我的问题是,在.NETCore中是否有一种方法可以为OAuthJWT承载流生成访问令牌
我正在使用的完整代码:
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('/', '_');
}
static void Main(字符串[]args)
{
控制台。WriteLine(“你好,世界!”);
var-token=GetAccessToken();
}
静态动态GetAccessToken()
{
//拿到证书
var证书=新的X509Certificate2(@“C:\temp\cert.pfx”);
//创建标题
var header=new{alg=“RS256”};
//创建索赔集
var expireydate=getexpireydate();
var claimset=new
{
iss=“xxxxxx”,
prn=“xxxxxx”,
澳元=”https://test.salesforce.com",
exp=到期日
};
//编码头
var headerSerialized=JsonConvert.Serialized对象(标头);
var headerBytes=Encoding.UTF8.GetBytes(headerSerialized);
var HEADERENCODE=ToBase64UrlString(头字节);
//编码索赔集
var claimsetSerialized=JsonConvert.serialized对象(claimset);
var claimsetBytes=Encoding.UTF8.GetBytes(claimsetSerialized);
var claimsetEncoded=ToBase64UrlString(claimsetBytes);
//输入
var输入=headerEncoded+“”+claimsetEncoded;
var inputBytes=Encoding.UTF8.GetBytes(输入);
//签名
var rsa=(rsacyptoserviceprovider)certificate.GetRSAPrivateKey();
var csparam=新的CSP参数
{
KeyContainerName=rsa.CspKeyContainerInfo.KeyContainerName,
KeyNumber=rsa.CspKeyContainerInfo.KeyNumber==KeyNumber.Exchange?1:2
};
var aescsp=new RSACryptoServiceProvider(csparam){PersistKeyInCsp=false};
var signatureBytes=aescsp.SignData(输入字节,“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=新的NameValueCollection();
内容[“断言”]=jwt;
内容[“授权类型”]=“urn:ietf:params:oauth:grant-type:jwt-bearer”;
字符串响应=Encoding.UTF8.GetString(client.UploadValues(uri,“POST”,content));
var result=JsonConvert.DeserializeObject(响应);
返回结果;
}
静态int getexpireydate()
{
var utc0=新的日期时间(1970年,1年,1年,0年,0年,0年,DateTimeKind.Utc);
var currentutcime=DateTime.UtcNow;
var exp=(int)currentUtcTime.AddMinutes(4).减法(utc0).TotalSeconds;
返回经验;
}
静态字符串ToBase64UrlString(字节[]输入)
{
返回Convert.ToBase64String(input.TrimEnd('=')).Replace('+','-').Replace('/',''.');
}
好吧——事实证明,向stackoverflow发帖会让大脑运转起来
答案最终是进行深入研究,在这里找到类似的问题,并使用
我最终替换了以下代码:
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('/', '_');
}
static void Main(字符串[]args)
{
控制台。WriteLine(“你好,世界!”);
var-token=GetAccessToken();
}
静态动态GetAccessToken()
{
//拿到证书
var证书=新的X509Certificate2(@“C:\temp\cert.pfx”);
//创建标题
var header=new{alg=“RS256”};
//创建索赔集
var expireydate=getexpireydate();
var claimset=new
{
iss=“xxxxx”,
prn=“xxxxx”,
澳元=”https://test.salesforce.com",
exp=到期日
};
//编码头
var headerSerialized=JsonConvert.Serialized对象(标头);
var headerBytes=Encoding.UTF8.GetBytes(headerSerialized);
var HEADERENCODE=ToBase64UrlString(头字节);
//编码索赔集
var claimsetSerialized=JsonConvert.serialized对象(claimset);
var claimsetBytes=Encoding.UTF8.GetBytes(claimsetSerialized);
var claimsetEncoded=ToBase64UrlString(claimsetBytes);
//输入
var输入=headerEncoded+“”+claimsetEncoded;
var inputBytes=Encoding.UTF8.GetBytes(输入);
var signingCredentials=新的X509SigningCredentials(证书,“RS256”);
var signature=JwtTokenUtilities.CreateEncodedSignature(输入,签名凭证);
//jwt
var jwt=头编码+“+”索赔集编码+“+”签名;
var client=new WebClient();
client.Encoding=Encoding.UTF8;
var uri=”https://test.salesforce.com/services/oauth2/token";
var content=新的NameValueCollection();
内容[“断言”]=jwt;
内容[“授权类型”]=“urn:ietf:params:oauth:grant-type:jwt-bearer”;
字符串响应=Encoding.UTF8.GetString(client.UploadValues(uri,“POST”,content));
var result=JsonConvert.D