RSA Disposed Object Error - every other test

Viewed 1302

We have several tests that that generate a jwt request to call a server to retrieve a token. We have 6 tests that make the same call to the same method using the same data. Here is the method: '''

    private static string GenerateSignedTokenRequest(
        string privateKey,
        string privateKeyPass,
        string clientID,
        string audience,
        int lifetime)
    {
        var jti = Guid.NewGuid().ToString();

        var claims = new[]
        {
            new Claim(JwtRegisteredClaimNames.Jti, jti),
            new Claim(JwtRegisteredClaimNames.Sub, clientID),
        };

        var decodedKey = DecodeRsaPrivateKeyFromPem(
            privateKey,
            privateKeyPass);

        var priDecKey = decodedKey.Private as RsaPrivateCrtKeyParameters;

        var rsaParams = DotNetUtilities.ToRSAParameters(priDecKey);

        using (var rsa = RSA.Create(rsaParams))
        {

            var token = new JwtSecurityToken(
                clientID,
                audience,
                claims,
                DateTime.Now.AddMinutes(-1),
                DateTime.Now.AddSeconds(lifetime),
                new SigningCredentials(
                    new RsaSecurityKey(rsa),
                    SecurityAlgorithms.RsaSha256));

            return new JwtSecurityTokenHandler().WriteToken(token);
        }

    }

'''

We get the following error on every other test that runs on the WriteToken(token) method: {"Cannot access a disposed object.\r\nObject name: 'RSA'."}

What is baffling is each odd number test runs through this code fine but each even number test fails. But when I rerun each test individually they are all green. It is only when I run them all together that every other test fails.

This has happened when moving from .Net Core and Test frameworks from 3.1.0 to 3.1.4

enter image description here

3 Answers

So It seems the issue was the upgrade of Windows Azure Active Directory IdentityModel Extensions for .Net. It seems there is a cache that not is affected by putting a using around the RSA.Create() method. By removing the using all the tests are green.

here are a few links that helped my diagnose: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc

And:

https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/1433

Update this

new SigningCredentials(
                new RsaSecurityKey(rsa),
                SecurityAlgorithms.RsaSha256)

To

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

reference : https://vmsdurano.com/-net-core-3-1-signing-jwt-with-rsa/

Below code works perfectly fine for me. In the below code, I am taking claims as parameter and pulling certificate from configuration. Instead of setting private key to a variable, putting directly in key fixed the issue.

using (X509Certificate2 certificate = new X509Certificate2(certPath, tokenConfig["CertSecret"], System.Security.Cryptography.X509Certificates.X509KeyStorageFlags.PersistKeySet))
{

    if (certificate.HasPrivateKey)
       {
    var signingCredentials = new SigningCredentials(
                   key: new RsaSecurityKey((RSA)certificate.PrivateKey),
                                algorithm: SecurityAlgorithms.RsaSha256 
                            );
    
                        var token = new JwtSecurityToken(
                            claims: claims,
                            expires: DateTime.Now.AddMinutes(Convert.ToInt32(configuration["TokenMinutesToExpire"])),
                            signingCredentials: signingCredentials);
                        return $"Bearer {new JwtSecurityTokenHandler().WriteToken(token)}";
                    }
       }

}
Related