【问题标题】:How can I sign a JWT with RSA SHA256 in an Azure API Management Policy Expression?如何在 Azure API 管理策略表达式中使用 RSA SHA256 签署 JWT?
【发布时间】:2021-10-13 16:16:59
【问题描述】:

Azure API 管理策略表达式中我需要创建一个使用私钥签名的 JWT。

当我尝试使用 RSACryptoServiceProvider - 只是为了检查这个 feedback 是否已经得到解决 - 我在尝试保存策略时收到此错误:

Usage of type 'System.Security.Cryptography.RSACryptoServiceProvider' is not supported within expressions 

根据maxim-kim 的提示,我尝试了 RSA.Create() 并从该tutorial 转换

var privateKey = "whatever";
RSA rsa = RSA.Create();
rsa.ImportRSAPrivateKey(privateKey, out _);

var signingCredentials = new SigningCredentials(new RsaSecurityKey(rsa), SecurityAlgorithms.RsaSha256)
{
    CryptoProviderFactory = new CryptoProviderFactory { CacheSignatureProviders = false }
};

var now = DateTime.Now;
var unixTimeSeconds = new DateTimeOffset(now).ToUnixTimeSeconds();

var jwt = new JwtSecurityToken(
    audience: _settings.Audience,
    issuer: _settings.Issuer,
    claims: new Claim[] {
        new Claim(JwtRegisteredClaimNames.Iat, unixTimeSeconds.ToString(), ClaimValueTypes.Integer64),
        new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
        new Claim(nameof(claims.FirstName), claims.FirstName),
        new Claim(nameof(claims.LastName), claims.LastName),
        new Claim(nameof(claims.Email), claims.Email)
    },
    notBefore: now,
    expires: now.AddMinutes(30),
    signingCredentials: signingCredentials
);

string token = new JwtSecurityTokenHandler().WriteToken(jwt);

return new JwtResponse
{
    Token = token,
    ExpiresAt = unixTimeSeconds,
};

但出现下一个错误:

'RSA' does not contain a definition for 'ImportRSAPrivateKey' and no extension method 'ImportRSAPrivateKey' accepting a first argument of type 'RSA' could be found (are you missing a using directive or an assembly reference?)

所以我的问题是:有没有办法在 Azure API 管理策略表达式中创建签名的 JWT?

【问题讨论】:

    标签: azure jwt azure-api-management


    【解决方案1】:

    目前不支持基于动态解析的私钥和公钥的 RSA 初始化。如果 RSA 参数不是特定于请求的,您可以将包含所需 RSA 参数的 x509 证书上传到 APIM 并在表达式中使用它: 使用 (var rsa = context.Deployment.Certificates["thumbprint"].GetRSAPrivateKey()) { …… }

    【讨论】:

    • 再次感谢@maxim-kim - 这给了我大约 33% 的需求。您是否有机会向我指出可用于实际创建和签署 JWT 的库/方法?
    • 不幸的是,我没有完整的食谱。 APIM 也不允许使用 JwtSecurityToken 类型,所以如果你想这样做,我想它需要相当数量的字符串/json 操作。总的来说,我认为这个用例值得单独的策略,比如“create-jwt”来隐藏所有相关的复杂性
    【解决方案2】:

    感谢这篇文章和其他文章,我成功地签署了 APIM 政策。因此,我想分享这个。

        <set-variable name="signedPayload" value="@{
            using (RSA rsa = context.Deployment.Certificates["thumbprint"].GetRSAPrivateKey())
            {
                long unixTimeStampInSeconds = DateTimeOffset.Now.ToUnixTimeSeconds();
                string header = "{\"alg\":\"RS256\",\"typ\":\"JWT\"}"; 
                string claimset = String.Format("{{ \"scope\": \"https://www.googleapis.com/auth/devstorage.read_write\", \"aud\": \"https://oauth2.googleapis.com/token\", \"iss\": \"blahblah.gserviceaccount.com\", \"iat\": {0}, \"exp\": {1} }}", unixTimeStampInSeconds, unixTimeStampInSeconds + 3599);
                string payload = System.Convert.ToBase64String(Encoding.UTF8.GetBytes(header)) + "." + System.Convert.ToBase64String(Encoding.UTF8.GetBytes(claimset));
                byte[] signature = rsa.SignData(Encoding.UTF8.GetBytes(payload), HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                return System.Net.WebUtility.UrlEncode(payload + "." + System.Convert.ToBase64String(signature));
            }
        }" />
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-11
      • 2021-10-16
      • 1970-01-01
      相关资源
      最近更新 更多