diff --git a/Directory.Build.props b/Directory.Build.props
index 47ab3d0e..2f31401b 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -7,11 +7,12 @@
$(NoWarn);CS1591;NU5128
true
true
+ $(MSBuildThisFileDirectory)eng\CodeAnalysis.ruleset
OpenIddict
- $(MSBuildThisFileDirectory)\eng\key.snk
+ $(MSBuildThisFileDirectory)eng\key.snk
true
false
false
@@ -64,8 +65,10 @@
$([System.DateTime]::Now.ToString(yyyyMMdd)).$(_AppVeyorBuildRevision)
-
-
+
+
+
diff --git a/OpenIddict.sln b/OpenIddict.sln
index 974ad7dd..c491c42c 100644
--- a/OpenIddict.sln
+++ b/OpenIddict.sln
@@ -59,6 +59,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenIddict.Owin", "src\Open
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "eng", "eng", "{6E8E862C-3F26-47D9-9C20-E3E87FD7CDFC}"
ProjectSection(SolutionItems) = preProject
+ eng\CodeAnalysis.ruleset = eng\CodeAnalysis.ruleset
eng\key.snk = eng\key.snk
eng\Signing.props = eng\Signing.props
eng\Version.Details.xml = eng\Version.Details.xml
diff --git a/eng/CodeAnalysis.ruleset b/eng/CodeAnalysis.ruleset
new file mode 100644
index 00000000..443912d2
--- /dev/null
+++ b/eng/CodeAnalysis.ruleset
@@ -0,0 +1,343 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/eng/Versions.props b/eng/Versions.props
index 2c2dc38d..6e7db7a4 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -35,6 +35,7 @@
1.8.6.7
4.7.0
6.4.0
+ 3.0.0
2019.1.3
6.6.0
1.7.0
@@ -42,6 +43,7 @@
2.9.0
4.13.1
4.1.0
+ 1.0.0
3.2.0
4.7.1
4.5.4
diff --git a/src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs b/src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs
index f4f11f5a..f633e493 100644
--- a/src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs
+++ b/src/OpenIddict.Core/Caches/OpenIddictApplicationCache.cs
@@ -385,6 +385,7 @@ namespace OpenIddict.Core
if (_signals.TryRemove(identifier, out CancellationTokenSource signal))
{
signal.Cancel();
+ signal.Dispose();
}
}
diff --git a/src/OpenIddict.Core/Caches/OpenIddictAuthorizationCache.cs b/src/OpenIddict.Core/Caches/OpenIddictAuthorizationCache.cs
index a8c68e19..5268f22a 100644
--- a/src/OpenIddict.Core/Caches/OpenIddictAuthorizationCache.cs
+++ b/src/OpenIddict.Core/Caches/OpenIddictAuthorizationCache.cs
@@ -609,6 +609,7 @@ namespace OpenIddict.Core
if (_signals.TryRemove(identifier, out CancellationTokenSource signal))
{
signal.Cancel();
+ signal.Dispose();
}
}
diff --git a/src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs b/src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs
index 56d205f2..3dab926b 100644
--- a/src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs
+++ b/src/OpenIddict.Core/Caches/OpenIddictScopeCache.cs
@@ -347,6 +347,7 @@ namespace OpenIddict.Core
if (_signals.TryRemove(identifier, out CancellationTokenSource signal))
{
signal.Cancel();
+ signal.Dispose();
}
}
diff --git a/src/OpenIddict.Core/Caches/OpenIddictTokenCache.cs b/src/OpenIddict.Core/Caches/OpenIddictTokenCache.cs
index dfffc62a..b8c98056 100644
--- a/src/OpenIddict.Core/Caches/OpenIddictTokenCache.cs
+++ b/src/OpenIddict.Core/Caches/OpenIddictTokenCache.cs
@@ -698,6 +698,7 @@ namespace OpenIddict.Core
if (_signals.TryRemove(identifier, out CancellationTokenSource signal))
{
signal.Cancel();
+ signal.Dispose();
}
}
diff --git a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
index 80de65bd..a880ba88 100644
--- a/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
+++ b/src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
@@ -20,6 +20,7 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OpenIddict.Abstractions;
using static OpenIddict.Abstractions.OpenIddictConstants;
+using SuppressMessageAttribute = System.Diagnostics.CodeAnalysis.SuppressMessageAttribute;
#if !SUPPORTS_KEY_DERIVATION_WITH_SPECIFIED_HASH_ALGORITHM
using Org.BouncyCastle.Crypto;
@@ -1329,6 +1330,8 @@ namespace OpenIddict.Core
}
}
+ [SuppressMessage("Security", "CA5379:Do not use weak key derivation function algorithm",
+ Justification = "The SHA-1 digest algorithm is still supported for backward compatibility.")]
private static byte[] DeriveKey(string secret, ReadOnlySpan salt,
HashAlgorithmName algorithm, int iterations, int length)
{
diff --git a/src/OpenIddict.Server/OpenIddictServerBuilder.cs b/src/OpenIddict.Server/OpenIddictServerBuilder.cs
index b16031eb..3884a285 100644
--- a/src/OpenIddict.Server/OpenIddictServerBuilder.cs
+++ b/src/OpenIddict.Server/OpenIddictServerBuilder.cs
@@ -18,6 +18,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.IdentityModel.Tokens;
using OpenIddict.Server;
using static OpenIddict.Abstractions.OpenIddictConstants;
+using SuppressMessageAttribute = System.Diagnostics.CodeAnalysis.SuppressMessageAttribute;
namespace Microsoft.Extensions.DependencyInjection
{
@@ -213,6 +214,8 @@ namespace Microsoft.Extensions.DependencyInjection
///
/// The subject name associated with the certificate.
/// The .
+ [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
+ Justification = "The X.509 certificate is attached to the server options.")]
public OpenIddictServerBuilder AddDevelopmentEncryptionCertificate([NotNull] X500DistinguishedName subject)
{
if (subject == null)
@@ -341,6 +344,8 @@ namespace Microsoft.Extensions.DependencyInjection
return new SymmetricSecurityKey(data);
}
+ [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
+ Justification = "The generated RSA key is attached to the server options.")]
static RsaSecurityKey CreateRsaSecurityKey(int size)
{
#if SUPPORTS_DIRECT_KEY_CREATION_WITH_SPECIFIED_SIZE
@@ -486,6 +491,8 @@ namespace Microsoft.Extensions.DependencyInjection
/// to store the private key of the certificate.
///
/// The .
+ [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
+ Justification = "The X.509 certificate is attached to the server options.")]
public OpenIddictServerBuilder AddEncryptionCertificate(
[NotNull] Stream stream, [NotNull] string password, X509KeyStorageFlags flags)
{
@@ -662,6 +669,8 @@ namespace Microsoft.Extensions.DependencyInjection
///
/// The subject name associated with the certificate.
/// The .
+ [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
+ Justification = "The X.509 certificate is attached to the server options.")]
public OpenIddictServerBuilder AddDevelopmentSigningCertificate([NotNull] X500DistinguishedName subject)
{
if (subject == null)
@@ -755,6 +764,8 @@ namespace Microsoft.Extensions.DependencyInjection
///
/// The algorithm associated with the signing key.
/// The .
+ [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
+ Justification = "The X.509 certificate is attached to the server options.")]
public OpenIddictServerBuilder AddEphemeralSigningKey([NotNull] string algorithm)
{
if (string.IsNullOrEmpty(algorithm))
@@ -807,6 +818,8 @@ namespace Microsoft.Extensions.DependencyInjection
default: throw new InvalidOperationException("The specified algorithm is not supported.");
}
+ [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
+ Justification = "The generated RSA key is attached to the server options.")]
static RsaSecurityKey CreateRsaSecurityKey(int size)
{
#if SUPPORTS_DIRECT_KEY_CREATION_WITH_SPECIFIED_SIZE
@@ -952,6 +965,8 @@ namespace Microsoft.Extensions.DependencyInjection
/// to store the private key of the certificate.
///
/// The .
+ [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
+ Justification = "The X.509 certificate is attached to the server options.")]
public OpenIddictServerBuilder AddSigningCertificate(
[NotNull] Stream stream, [NotNull] string password, X509KeyStorageFlags flags)
{
diff --git a/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs b/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs
index e4fe851e..c7289835 100644
--- a/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs
+++ b/src/OpenIddict.Validation/OpenIddictValidationBuilder.cs
@@ -17,6 +17,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using OpenIddict.Validation;
+using SuppressMessageAttribute = System.Diagnostics.CodeAnalysis.SuppressMessageAttribute;
namespace Microsoft.Extensions.DependencyInjection
{
@@ -303,6 +304,8 @@ namespace Microsoft.Extensions.DependencyInjection
/// to store the private key of the certificate.
///
/// The .
+ [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
+ Justification = "The X.509 certificate is attached to the server options.")]
public OpenIddictValidationBuilder AddEncryptionCertificate(
[NotNull] Stream stream, [NotNull] string password, X509KeyStorageFlags flags)
{
diff --git a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs
index 44e6cac7..d6b0a115 100644
--- a/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs
+++ b/test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictParameterTests.cs
@@ -499,7 +499,7 @@ namespace OpenIddict.Abstractions.Tests.Primitives
{
// Arrange, act and assert
Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(string.Empty)));
- Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(new string[0])));
+ Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(Array.Empty())));
Assert.True(OpenIddictParameter.IsNullOrEmpty(new OpenIddictParameter(
JsonSerializer.Deserialize("[]"))));
diff --git a/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs b/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs
index ad1bcd56..82e5ac48 100644
--- a/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs
+++ b/test/OpenIddict.MongoDb.Tests/OpenIddictMongoDbContextTests.cs
@@ -30,7 +30,7 @@ namespace OpenIddict.MongoDb.Tests
var options = Mock.Of>();
var token = new CancellationToken(canceled: true);
- var context = new OpenIddictMongoDbContext(options, provider);
+ using var context = new OpenIddictMongoDbContext(options, provider);
// Act and assert
var exception = await Assert.ThrowsAsync(async delegate
@@ -51,7 +51,7 @@ namespace OpenIddict.MongoDb.Tests
var database = GetDatabase();
var options = Mock.Of>();
- var context = new OpenIddictMongoDbContext(options, provider);
+ using var context = new OpenIddictMongoDbContext(options, provider);
// Act and assert
var exception = await Assert.ThrowsAsync(async delegate
@@ -92,7 +92,7 @@ namespace OpenIddict.MongoDb.Tests
InitializationTimeout = TimeSpan.FromMilliseconds(50)
});
- var context = new OpenIddictMongoDbContext(options, provider);
+ using var context = new OpenIddictMongoDbContext(options, provider);
// Act and assert
var exception = await Assert.ThrowsAsync(delegate
@@ -127,7 +127,7 @@ namespace OpenIddict.MongoDb.Tests
Database = database.Object
});
- var context = new OpenIddictMongoDbContext(options, provider);
+ using var context = new OpenIddictMongoDbContext(options, provider);
// Act and assert
Assert.Same(database.Object, await context.GetDatabaseAsync(CancellationToken.None));
@@ -147,7 +147,7 @@ namespace OpenIddict.MongoDb.Tests
Database = null
});
- var context = new OpenIddictMongoDbContext(options, provider);
+ using var context = new OpenIddictMongoDbContext(options, provider);
// Act and assert
var exception = await Assert.ThrowsAsync(async delegate
@@ -181,7 +181,7 @@ namespace OpenIddict.MongoDb.Tests
Database = null
});
- var context = new OpenIddictMongoDbContext(options, provider);
+ using var context = new OpenIddictMongoDbContext(options, provider);
// Act and assert
Assert.Same(database.Object, await context.GetDatabaseAsync(CancellationToken.None));
@@ -202,7 +202,7 @@ namespace OpenIddict.MongoDb.Tests
DisableInitialization = true
});
- var context = new OpenIddictMongoDbContext(options, provider);
+ using var context = new OpenIddictMongoDbContext(options, provider);
// Act
await context.GetDatabaseAsync(CancellationToken.None);
@@ -228,7 +228,7 @@ namespace OpenIddict.MongoDb.Tests
Database = database.Object
});
- var context = new OpenIddictMongoDbContext(options, provider);
+ using var context = new OpenIddictMongoDbContext(options, provider);
// Act and assert
Assert.Same(database.Object, await context.GetDatabaseAsync(CancellationToken.None));
@@ -272,7 +272,7 @@ namespace OpenIddict.MongoDb.Tests
Database = database.Object
});
- var context = new OpenIddictMongoDbContext(options, provider);
+ using var context = new OpenIddictMongoDbContext(options, provider);
// Act and assert
await Assert.ThrowsAsync(async () => await context.GetDatabaseAsync(CancellationToken.None));
diff --git a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTestServer.cs b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTestServer.cs
index 3a8d8705..586ac727 100644
--- a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTestServer.cs
+++ b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTestServer.cs
@@ -4,6 +4,7 @@
* the license and the contributors participating to this project.
*/
+using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Hosting;
@@ -39,6 +40,8 @@ namespace OpenIddict.Server.AspNetCore.FunctionalTests
public IHost Host { get; }
#endif
+ [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
+ Justification = "The caller is responsible of disposing the test client.")]
public override ValueTask CreateClientAsync()
=> new ValueTask(
new OpenIddictServerIntegrationTestClient(Server.CreateClient()));
diff --git a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs
index 08d4902e..f8af0d0f 100644
--- a/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs
+++ b/test/OpenIddict.Server.AspNetCore.IntegrationTests/OpenIddictServerAspNetCoreIntegrationTests.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Security.Claims;
using System.Text.Json;
@@ -415,6 +416,8 @@ namespace OpenIddict.Server.AspNetCore.FunctionalTests
Assert.Equal("Bob l'Eponge", (string) response["string_parameter"]);
}
+ [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
+ Justification = "The caller is responsible of disposing the test server.")]
protected override
#if SUPPORTS_GENERIC_HOST
async
diff --git a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTestClient.cs b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTestClient.cs
index e1798de4..710cb12a 100644
--- a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTestClient.cs
+++ b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTestClient.cs
@@ -244,7 +244,10 @@ namespace OpenIddict.Server.FunctionalTests
"is associated with the HTTP client.", nameof(uri));
}
- return await GetResponseAsync(await HttpClient.SendAsync(CreateRequestMessage(request, method, uri)));
+ using var message = CreateRequestMessage(request, method, uri);
+ using var response = await HttpClient.SendAsync(message);
+
+ return await GetResponseAsync(response);
}
private HttpRequestMessage CreateRequestMessage(OpenIddictRequest request, HttpMethod method, Uri uri)
diff --git a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs
index f5026dd1..3a220d85 100644
--- a/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs
+++ b/test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Discovery.cs
@@ -1306,7 +1306,7 @@ namespace OpenIddict.Server.FunctionalTests
}
};
- var algorithm = ECDsa.Create(parameters);
+ using var algorithm = ECDsa.Create(parameters);
await using var server = await CreateServerAsync(options =>
{
diff --git a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTestServer.cs b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTestServer.cs
index 9aae2a54..49d7f993 100644
--- a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTestServer.cs
+++ b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTestServer.cs
@@ -4,6 +4,7 @@
* the license and the contributors participating to this project.
*/
+using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using Microsoft.Owin.Testing;
using OpenIddict.Server.FunctionalTests;
@@ -23,6 +24,8 @@ namespace OpenIddict.Server.Owin.FunctionalTests
///
public TestServer Server { get; }
+ [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
+ Justification = "The caller is responsible of disposing the test client.")]
public override ValueTask CreateClientAsync()
=> new ValueTask(
new OpenIddictServerIntegrationTestClient(Server.HttpClient));
diff --git a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs
index 6d1714c6..2b6de1be 100644
--- a/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs
+++ b/test/OpenIddict.Server.Owin.IntegrationTests/OpenIddictServerOwinIntegrationTests.cs
@@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Security.Claims;
using System.Text.Json;
@@ -298,6 +299,8 @@ namespace OpenIddict.Server.Owin.FunctionalTests
Assert.Equal("Bob le Magnifique", (string) response["name"]);
}
+ [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
+ Justification = "The caller is responsible of disposing the test server.")]
protected override ValueTask CreateServerAsync(Action configuration = null)
{
var services = new ServiceCollection();