问题描述
我正在遵循此处列出的稀疏说明:https://metamind.readme.io/docs/generate-an-oauth-token-using-your-key
我需要能够生成Bearer令牌,以便能够直接从.net(特别是.net 4.5)访问爱因斯坦服务。
由于对RSACryptoServiceProvider.ImportRSAPrivateKey的支持在.net 5之前不可用,因此我已将我的pem文件(从salesforce下载)转换为xml格式(使用https://superdry.apphb.com/tools/online-rsa-key-converter),并使用该文件进行签名JWT断言。我得到了一个编码的断言,但是当我将其发布到https://api.einstein.ai/v2/oauth2/token服务时,我总是收到“无效令牌”消息。
这是我的代码:
Claim[] claims = new[] {
new Claim(JwtRegisteredClaimNames.Sub,this.Username),new Claim(JwtRegisteredClaimNames.Aud,this.Endpoint.ToString()),new Claim(JwtRegisteredClaimNames.Exp,((int)expiryUnixTimeStamp).ToString())
};
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.FromXmlString(this.RsaXmlString);
RsaSecurityKey rsaSecurityKey = new RsaSecurityKey(provider);
SigningCredentials signingCredentials = new SigningCredentials(rsaSecurityKey,SecurityAlgorithms.RsaSha256);
JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(
new JwtHeader(signingCredentials),new JwtPayload(claims)
);
string jwtToken = new JwtSecurityTokenHandler().Writetoken(jwtSecurityToken);
我已经检查了所有参数。我可以使用相同的pem密钥和用户名,通过浏览器界面成功创建Bearer令牌,那么为什么代码失败?
解决方法
此问题的答案是不要从Claims数组生成JwtPayload。它可以编译,但是Claim构造函数只接受字符串值。有一个valueType参数,但这也是一个字符串,其内容未记录。我找不到valueType的值,该值使我无法将'exp'值指定为整数。所以问题是我的unixtimestamp被序列化为字符串,这使断言无效。
解决方案:JwtPayload.Add方法采用对象而不是字符串...
JwtPayload jwtPayload = new JwtPayload();
jwtPayload.Add(JwtRegisteredClaimNames.Sub,this.Username);
jwtPayload.Add(JwtRegisteredClaimNames.Aud,this.Endpoint.ToString());
jwtPayload.Add(JwtRegisteredClaimNames.Exp,(int)expiryUnixTimeStamp);
JwtSecurityToken jwtSecurityToken = new JwtSecurityToken(
new JwtHeader(signingCredentials),new JwtPayload(jwtPayload)
);