简体   繁体   中英

How can I sign a JWT with RSA SHA256 in an Azure API Management Policy Expression?

In an Azure API Management Policy Expression I need to create a JWT signed with a private key.

When I try to use RSACryptoServiceProvider - just to check whether this feedback already got resolved - I get this error when trying to save the policy:

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

Following a hint from maxim-kim , I tried RSA.Create() and to convert from this 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,
};

but got the next error:

'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?)

So my question: Is there a way to create a signed JWT in an Azure API Management Policy Expression ?

RSA initialization based on dynamically resolved private and public keys is not supported today. If RSA parameters are not request specific you can upload x509 certificate to APIM containing required RSA parameters and use it within expressions: using (var rsa = context.Deployment.Certificates["thumbprint"].GetRSAPrivateKey()) { .... }

Thanks to this and other articles, I managed to sign in an APIM policy. Therefore I would like to share this.

    <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));
        }
    }" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM