mirror of
https://github.com/DuendeSoftware/products
synced 2026-05-24 09:28:24 +00:00
Publish - 2026-04-01 08:20:45 UTC
This commit is contained in:
parent
1c35015337
commit
50f1a072b3
83 changed files with 267 additions and 321 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -24,6 +24,7 @@ x86/
|
|||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Tt]emp/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
|
|
@ -176,7 +177,7 @@ Logging.g.cs
|
|||
LoggerMessage.g.cs
|
||||
PublicTopLevelProgram.Generated.g.cs
|
||||
RegexGenerator.g.cs
|
||||
**/Generated/
|
||||
**/Generated/Microsoft.CodeAnalysis.Razor.Compiler/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<IsPackable>false</IsPackable>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
<!-- <Nullable>enable</Nullable> -->
|
||||
<Nullable>enable</Nullable>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@
|
|||
<PackageVersion Include="Serilog.Sinks.OpenTelemetry" Version="4.2.0" />
|
||||
<PackageVersion Include="Serilog.Sinks.TextWriter" Version="3.0.0" />
|
||||
<PackageVersion Include="Shouldly" Version="4.3.0" />
|
||||
<PackageVersion Include="SimpleExec" Version="12.0.0" />
|
||||
<PackageVersion Include="SimpleExec" Version="12.1.0" />
|
||||
<PackageVersion Include="SimpleFeedReader" Version="2.0.4" />
|
||||
<PackageVersion Include="Spectre.Console.Cli" Version="0.53.1" />
|
||||
<PackageVersion Include="Spectre.Console.Json" Version="0.54.0" />
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
#:project ../.github/build/BuildHelpers.csproj
|
||||
|
||||
using BuildHelpers;
|
||||
using static Bullseye.Targets;
|
||||
|
||||
var repoRoot = Repo.FindRoot();
|
||||
|
||||
Targets.Shared(repoRoot, "aspnetcore-authentication-jwtbearer/aspnetcore-authentication-jwtbearer.slnf");
|
||||
|
||||
const string TestsAspNetCoreAuthenticationJwtBearerTests = "tests-asp-net-core-authentication-jwt-bearer-tests";
|
||||
|
||||
Targets.Test(TestsAspNetCoreAuthenticationJwtBearerTests, "aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests", repoRoot);
|
||||
|
||||
Target(SharedTargets.Default, [
|
||||
SharedTargets.CheckSolutions,
|
||||
SharedTargets.CheckUnusedPackages,
|
||||
SharedTargets.CheckSortedRefs,
|
||||
SharedTargets.CheckSortedSlnf,
|
||||
SharedTargets.VerifyFormatting,
|
||||
SharedTargets.Clean,
|
||||
SharedTargets.VerifyNoChanges,
|
||||
SharedTargets.DotnetDevCerts,
|
||||
TestsAspNetCoreAuthenticationJwtBearerTests
|
||||
]);
|
||||
|
||||
await RunTargetsAndExitAsync(args);
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>Duende.AspNetCore.Authentication.JwtBearer</RootNamespace>
|
||||
<AssemblyName>Duende.AspNetCore.Authentication.JwtBearer</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ internal class DPoPProofValidator : IDPoPProofValidator
|
|||
|
||||
try
|
||||
{
|
||||
var tvp = context.Options.ProofTokenValidationParameters;
|
||||
var tvp = context.Options.ProofTokenValidationParameters.Clone();
|
||||
tvp.IssuerSigningKey = new JsonWebKey(result.JsonWebKey);
|
||||
|
||||
var handler = new JsonWebTokenHandler();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<AssemblyName>Duende.AspNetCore.Authentication.JwtBearer.Tests</AssemblyName>
|
||||
<RootNameSpace>Duende.AspNetCore.Authentication.JwtBearer</RootNameSpace>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,115 @@
|
|||
// Copyright (c) Duende Software. All rights reserved.
|
||||
// See LICENSE in the project root for license information.
|
||||
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text.Json;
|
||||
using Duende.IdentityModel;
|
||||
using Microsoft.IdentityModel.JsonWebTokens;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace Duende.AspNetCore.Authentication.JwtBearer.DPoP;
|
||||
|
||||
/// <summary>
|
||||
/// Regression tests for GitHub issue #1667: concurrent DPoP proof validation
|
||||
/// must not corrupt the shared TokenValidationParameters.IssuerSigningKey.
|
||||
/// </summary>
|
||||
public sealed class ConcurrentTokenValidationTests : DPoPProofValidatorTestBase
|
||||
{
|
||||
[Fact]
|
||||
public async Task ConcurrentValidationsWithDifferentKeysShouldAllSucceed()
|
||||
{
|
||||
// Arrange – generate distinct RSA key pairs to simulate different DPoP clients
|
||||
const int keyCount = 10;
|
||||
const int requestsPerKey = 20;
|
||||
|
||||
var keys = Enumerable.Range(0, keyCount)
|
||||
.Select(_ => GenerateRsaKeyPair())
|
||||
.ToList();
|
||||
|
||||
// Build (context, result) pairs – each uses a proof token signed by a different key
|
||||
var validations = keys.SelectMany(key =>
|
||||
Enumerable.Range(0, requestsPerKey).Select(_ =>
|
||||
{
|
||||
var proofToken = CreateDPoPProofTokenForKey(key.PrivateJwk, key.PublicJwkPayload);
|
||||
var result = new DPoPProofValidationResult();
|
||||
var context = Context with { ProofToken = proofToken };
|
||||
|
||||
// Pre-populate the JWK on the result, as ValidateJwk normally does
|
||||
ProofValidator.ValidateJwk(context, result);
|
||||
|
||||
return (Context: context, Result: result);
|
||||
}))
|
||||
.ToList();
|
||||
|
||||
// Act – run all validations concurrently against the shared Options.
|
||||
// Use a gate to ensure all tasks start simultaneously on the thread pool,
|
||||
// maximizing overlap to expose any race conditions.
|
||||
using var gate = new ManualResetEventSlim(false);
|
||||
|
||||
var tasks = validations.Select(v => Task.Run(async () =>
|
||||
{
|
||||
gate.Wait();
|
||||
await ProofValidator.ValidateToken(v.Context, v.Result);
|
||||
return v.Result;
|
||||
})).ToArray();
|
||||
|
||||
gate.Set();
|
||||
|
||||
var results = await Task.WhenAll(tasks);
|
||||
|
||||
// Assert – every validation must succeed; any failure indicates a race condition
|
||||
var failures = results.Where(r => r.IsError).ToList();
|
||||
failures.Count.ShouldBe(0,
|
||||
$"{failures.Count}/{results.Length} validations failed. " +
|
||||
$"First error: {failures.FirstOrDefault()?.ErrorDescription}");
|
||||
}
|
||||
|
||||
private static (string PrivateJwk, Dictionary<string, string> PublicJwkPayload) GenerateRsaKeyPair()
|
||||
{
|
||||
using var rsa = RSA.Create(2048);
|
||||
var parameters = rsa.ExportParameters(includePrivateParameters: true);
|
||||
|
||||
var privateJwkJson = JsonSerializer.Serialize(new
|
||||
{
|
||||
kty = "RSA",
|
||||
n = Base64UrlEncoder.Encode(parameters.Modulus!),
|
||||
e = Base64UrlEncoder.Encode(parameters.Exponent!),
|
||||
d = Base64UrlEncoder.Encode(parameters.D!),
|
||||
p = Base64UrlEncoder.Encode(parameters.P!),
|
||||
q = Base64UrlEncoder.Encode(parameters.Q!),
|
||||
dp = Base64UrlEncoder.Encode(parameters.DP!),
|
||||
dq = Base64UrlEncoder.Encode(parameters.DQ!),
|
||||
qi = Base64UrlEncoder.Encode(parameters.InverseQ!)
|
||||
});
|
||||
|
||||
var publicJwkPayload = new Dictionary<string, string>
|
||||
{
|
||||
["kty"] = "RSA",
|
||||
["n"] = Base64UrlEncoder.Encode(parameters.Modulus!),
|
||||
["e"] = Base64UrlEncoder.Encode(parameters.Exponent!)
|
||||
};
|
||||
|
||||
return (privateJwkJson, publicJwkPayload);
|
||||
}
|
||||
|
||||
private static string CreateDPoPProofTokenForKey(
|
||||
string privateJwkJson,
|
||||
Dictionary<string, string> publicJwkPayload)
|
||||
{
|
||||
var handler = new JsonWebTokenHandler();
|
||||
var signingKey = new JsonWebKey(privateJwkJson);
|
||||
var descriptor = new SecurityTokenDescriptor
|
||||
{
|
||||
TokenType = "dpop+jwt",
|
||||
IssuedAt = DateTime.UtcNow,
|
||||
AdditionalHeaderClaims = new Dictionary<string, object>
|
||||
{
|
||||
{ JwtClaimTypes.JsonWebKey, publicJwkPayload }
|
||||
},
|
||||
Subject = new ClaimsIdentity(),
|
||||
SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.RsaSha256)
|
||||
};
|
||||
return handler.CreateToken(descriptor);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,4 +2,16 @@
|
|||
<Project>
|
||||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)..\'))" />
|
||||
<Import Project="../../test.props" />
|
||||
<PropertyGroup>
|
||||
<!-- TODO: Fix these in test code and remove suppressions -->
|
||||
<NoWarn>$(NoWarn);CA1051</NoWarn><!-- Do not declare visible instance fields -->
|
||||
<NoWarn>$(NoWarn);CA1305</NoWarn><!-- Specify IFormatProvider -->
|
||||
<NoWarn>$(NoWarn);CA1310</NoWarn><!-- Specify StringComparison for correctness -->
|
||||
<NoWarn>$(NoWarn);CA1707</NoWarn><!-- Identifiers should not contain underscores -->
|
||||
<NoWarn>$(NoWarn);CA1805</NoWarn><!-- Do not initialize unnecessarily -->
|
||||
<NoWarn>$(NoWarn);CA1822</NoWarn><!-- Mark members as static -->
|
||||
<NoWarn>$(NoWarn);CA1852</NoWarn><!-- Seal internal types -->
|
||||
<NoWarn>$(NoWarn);CA1866</NoWarn><!-- Use char overload -->
|
||||
<NoWarn>$(NoWarn);CA2201</NoWarn><!-- Do not raise reserved exception types -->
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
|||
29
bff/build.cs
29
bff/build.cs
|
|
@ -1,29 +0,0 @@
|
|||
#:project ../.github/build/BuildHelpers.csproj
|
||||
|
||||
using BuildHelpers;
|
||||
using static Bullseye.Targets;
|
||||
|
||||
var repoRoot = Repo.FindRoot();
|
||||
|
||||
Targets.Shared(repoRoot, "bff/bff.slnf");
|
||||
|
||||
const string TestsBffTests = "tests-bff-tests";
|
||||
const string TestsHostsTests = "tests-hosts-tests";
|
||||
|
||||
Targets.Test(TestsBffTests, "bff/test/Bff.Tests", repoRoot);
|
||||
Targets.Test(TestsHostsTests, "bff/test/Hosts.Tests", repoRoot);
|
||||
|
||||
Target(SharedTargets.Default, [
|
||||
SharedTargets.CheckSolutions,
|
||||
SharedTargets.CheckUnusedPackages,
|
||||
SharedTargets.CheckSortedRefs,
|
||||
SharedTargets.CheckSortedSlnf,
|
||||
SharedTargets.VerifyFormatting,
|
||||
SharedTargets.Clean,
|
||||
SharedTargets.VerifyNoChanges,
|
||||
SharedTargets.DotnetDevCerts,
|
||||
TestsBffTests,
|
||||
TestsHostsTests
|
||||
]);
|
||||
|
||||
await RunTargetsAndExitAsync(args);
|
||||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
|
||||
<StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoDefaultLaunchSettingsFile>true</NoDefaultLaunchSettingsFile>
|
||||
<StaticWebAssetProjectMode>Default</StaticWebAssetProjectMode>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsAspireHost>true</IsAspireHost>
|
||||
<UserSecretsId>616547e2-3a28-4c9d-8685-f4ac02581162</UserSecretsId>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<RootNamespace>Bff.DPoP</RootNamespace>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<RootNamespace>Bff.EF</RootNamespace>
|
||||
<Nullable>disable</Nullable><!-- TODO: enable nullable -->
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" />
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<RootNamespace>Bff</RootNamespace>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>disable</Nullable><!-- TODO: enable nullable -->
|
||||
<NoWarn>$(NoWarn);IDE0130</NoWarn><!-- Namespace does not match folder structure --><!-- TODO: remove? -->
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsAspireSharedProject>true</IsAspireSharedProject>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<Nullable>disable</Nullable><!-- TODO: enable nullable -->
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Duende.AspNetCore.Authentication.JwtBearer" />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<Nullable>disable</Nullable><!-- TODO: enable nullable -->
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Duende.IdentityModel" />
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<Nullable>disable</Nullable><!-- TODO: enable nullable -->
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -5,5 +5,6 @@
|
|||
<RootNamespace>$(AssemblyName)</RootNamespace>
|
||||
<AssemblyName>Duende.$(MSBuildProjectName)</AssemblyName>
|
||||
<WarnOnPackingNonPackableProject>false</WarnOnPackingNonPackableProject>
|
||||
<Nullable>disable</Nullable><!-- TODO: enable nullable -->
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
<TargetFramework>net10.0</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<WarningsAsErrors>false</WarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
<TargetFramework>net10.0</TargetFramework>
|
||||
<OutputType>Exe</OutputType>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<AssemblyName>Duende.BFF.Blazor.Client</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<AssemblyName>Duende.BFF.Blazor</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
<Import Project="../../src.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<Nullable>enable</Nullable>
|
||||
<PackageTags>OAuth 2.0;OpenID Connect;Security;BFF;IdentityServer;ASP.NET Core;SPA;Blazor</PackageTags>
|
||||
<Product>Duende BFF</Product>
|
||||
<MinVerTagPrefix>bff-</MinVerTagPrefix>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>disable</Nullable><!-- TODO: enable nullable -->
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Duende.BFF.Yarp" Version="3.0.0" />
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<NoWarn>$(NoWarn);IDE0130</NoWarn><!-- Namespace does not match folder structure --><!-- TODO: remove? -->
|
||||
<Nullable>enable</Nullable>
|
||||
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -5,11 +5,33 @@
|
|||
<AssemblyName>Duende.$(MSBuildProjectName)</AssemblyName>
|
||||
<RootNamespace>$(AssemblyName)</RootNamespace>
|
||||
|
||||
<!-- RS0026: Do not add multiple overloads with optional parameters -->
|
||||
<NoWarn>$(NoWarn);RS0026</NoWarn>
|
||||
|
||||
<!-- RS0027: API with optional parameter(s) should have the most parameters amongst its public overloads -->
|
||||
<NoWarn>$(NoWarn);RS0027</NoWarn>
|
||||
<!-- TODO: Fix these in bff test code and remove suppressions -->
|
||||
<NoWarn>$(NoWarn);RS0026</NoWarn><!-- Do not add multiple overloads with optional parameters -->
|
||||
<NoWarn>$(NoWarn);RS0027</NoWarn><!-- API with optional parameter(s) should have the most parameters amongst its public overloads -->
|
||||
<NoWarn>$(NoWarn);CA1000</NoWarn><!-- Do not declare static members on generic types -->
|
||||
<NoWarn>$(NoWarn);CA1001</NoWarn><!-- Types that own disposable fields should be disposable -->
|
||||
<NoWarn>$(NoWarn);CA1051</NoWarn><!-- Do not declare visible instance fields -->
|
||||
<NoWarn>$(NoWarn);CA1304</NoWarn><!-- Specify CultureInfo -->
|
||||
<NoWarn>$(NoWarn);CA1305</NoWarn><!-- Specify IFormatProvider -->
|
||||
<NoWarn>$(NoWarn);CA1310</NoWarn><!-- Specify StringComparison for correctness -->
|
||||
<NoWarn>$(NoWarn);CA1311</NoWarn><!-- Specify a culture or use an invariant version -->
|
||||
<NoWarn>$(NoWarn);CA1707</NoWarn><!-- Identifiers should not contain underscores -->
|
||||
<NoWarn>$(NoWarn);CA1711</NoWarn><!-- Identifiers should not have incorrect suffix -->
|
||||
<NoWarn>$(NoWarn);CA1725</NoWarn><!-- Parameter names should match base declaration -->
|
||||
<NoWarn>$(NoWarn);CA1805</NoWarn><!-- Do not initialize unnecessarily -->
|
||||
<NoWarn>$(NoWarn);CA1816</NoWarn><!-- Call GC.SuppressFinalize correctly -->
|
||||
<NoWarn>$(NoWarn);CA1822</NoWarn><!-- Mark members as static -->
|
||||
<NoWarn>$(NoWarn);CA1829</NoWarn><!-- Use Length/Count property instead of Count() -->
|
||||
<NoWarn>$(NoWarn);CA1848</NoWarn><!-- Use the LoggerMessage delegates -->
|
||||
<NoWarn>$(NoWarn);CA1852</NoWarn><!-- Seal internal types -->
|
||||
<NoWarn>$(NoWarn);CA1859</NoWarn><!-- Use concrete types when possible for improved performance -->
|
||||
<NoWarn>$(NoWarn);CA1860</NoWarn><!-- Avoid using Enumerable.Any() extension method -->
|
||||
<NoWarn>$(NoWarn);CA1861</NoWarn><!-- Avoid constant arrays as arguments -->
|
||||
<NoWarn>$(NoWarn);CA1866</NoWarn><!-- Use char overload -->
|
||||
<NoWarn>$(NoWarn);CA1869</NoWarn><!-- Cache and reuse JsonSerializerOptions instances -->
|
||||
<NoWarn>$(NoWarn);CA2016</NoWarn><!-- Forward CancellationToken to methods that accept it -->
|
||||
<NoWarn>$(NoWarn);CA2201</NoWarn><!-- Do not raise reserved exception types -->
|
||||
<NoWarn>$(NoWarn);CA2254</NoWarn><!-- Template should be a static expression -->
|
||||
</PropertyGroup>
|
||||
<Import Project="../../test.props" />
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net10.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Configurations>Debug;Release;Debug_ncrunch</Configurations>
|
||||
<RootNamespace>Hosts.Tests</RootNamespace>
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
#:project ../.github/build/BuildHelpers.csproj
|
||||
|
||||
using BuildHelpers;
|
||||
using static Bullseye.Targets;
|
||||
|
||||
var repoRoot = Repo.FindRoot();
|
||||
|
||||
Targets.Shared(repoRoot, "conformance-report/conformance-report.slnf");
|
||||
|
||||
const string TestsConformanceReportTests = "tests-conformance-report-tests";
|
||||
|
||||
Targets.Test(TestsConformanceReportTests, "conformance-report/test/ConformanceReport.Tests", repoRoot);
|
||||
|
||||
Target(SharedTargets.Default, [
|
||||
SharedTargets.CheckSolutions,
|
||||
SharedTargets.CheckUnusedPackages,
|
||||
SharedTargets.CheckSortedRefs,
|
||||
SharedTargets.CheckSortedSlnf,
|
||||
SharedTargets.VerifyFormatting,
|
||||
SharedTargets.Clean,
|
||||
SharedTargets.VerifyNoChanges,
|
||||
SharedTargets.DotnetDevCerts,
|
||||
TestsConformanceReportTests
|
||||
]);
|
||||
|
||||
await RunTargetsAndExitAsync(args);
|
||||
|
|
@ -122,8 +122,6 @@ internal class OAuth21Assessor(ConformanceReportServerOptions options)
|
|||
return findings;
|
||||
}
|
||||
|
||||
#region Server-Level Assessments
|
||||
|
||||
private Finding AssessParAvailability()
|
||||
{
|
||||
var parEnabled = options.PushedAuthorizationEndpointEnabled;
|
||||
|
|
@ -240,10 +238,6 @@ internal class OAuth21Assessor(ConformanceReportServerOptions options)
|
|||
Recommendation = options.UseHttp303Redirects ? null : "Set UseHttp303Redirects = true in IdentityServerOptions."
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
#region Client-Level Assessments
|
||||
|
||||
private static Finding AssessAllowedGrantTypes(ConformanceReportClient client)
|
||||
{
|
||||
var allowedGrants = new HashSet<string>
|
||||
|
|
@ -654,5 +648,4 @@ internal class OAuth21Assessor(ConformanceReportServerOptions options)
|
|||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@
|
|||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)..\'))" />
|
||||
<Import Project="../../src.props" />
|
||||
<PropertyGroup>
|
||||
<Nullable>enable</Nullable>
|
||||
<AssemblyName>Duende.ConformanceReport.$(MSBuildProjectName)</AssemblyName>
|
||||
<PackageId>Duende.ConformanceReport.$(MSBuildProjectName)</PackageId>
|
||||
<RootNamespace>Duende.ConformanceReport</RootNamespace>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,4 @@
|
|||
<Project>
|
||||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)..\'))" />
|
||||
<Import Project="../../test.props" />
|
||||
<PropertyGroup>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,21 +0,0 @@
|
|||
#:project ../.github/build/BuildHelpers.csproj
|
||||
|
||||
using BuildHelpers;
|
||||
using static Bullseye.Targets;
|
||||
|
||||
var repoRoot = Repo.FindRoot();
|
||||
|
||||
Targets.Shared(repoRoot, "docs-mcp/docs-mcp.slnf");
|
||||
|
||||
Target(SharedTargets.Default, [
|
||||
SharedTargets.CheckSolutions,
|
||||
SharedTargets.CheckUnusedPackages,
|
||||
SharedTargets.CheckSortedRefs,
|
||||
SharedTargets.CheckSortedSlnf,
|
||||
SharedTargets.VerifyFormatting,
|
||||
SharedTargets.Clean,
|
||||
SharedTargets.VerifyNoChanges,
|
||||
SharedTargets.DotnetDevCerts
|
||||
]);
|
||||
|
||||
await RunTargetsAndExitAsync(args);
|
||||
|
|
@ -9,6 +9,5 @@
|
|||
<Product>Duende Documentation MCP Server</Product>
|
||||
<MinVerTagPrefix>dmcp-</MinVerTagPrefix>
|
||||
<MinVerMinimumMajorMinor>1.0</MinVerMinimumMajorMinor>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsAspireHost>true</IsAspireHost>
|
||||
<UserSecretsId>b86a3528-3d86-4514-b57f-9839f472ef31</UserSecretsId>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsAspireHost>true</IsAspireHost>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsAspireSharedProject>true</IsAspireSharedProject>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
#:project ../.github/build/BuildHelpers.csproj
|
||||
|
||||
using BuildHelpers;
|
||||
using static Bullseye.Targets;
|
||||
|
||||
var repoRoot = Repo.FindRoot();
|
||||
|
||||
Targets.Shared(repoRoot, "identity-server/identity-server.slnf");
|
||||
|
||||
const string TestsIdentityServerUnitTests = "tests-identity-server-unit-tests";
|
||||
const string TestsIdentityServerIntegrationTests = "tests-identity-server-integration-tests";
|
||||
const string TestsIdentityServerEndToEndTests = "tests-identity-server-end-to-end-tests";
|
||||
|
||||
Targets.Test(TestsIdentityServerUnitTests, "identity-server/test/IdentityServer.UnitTests", repoRoot);
|
||||
Targets.Test(TestsIdentityServerIntegrationTests, "identity-server/test/IdentityServer.IntegrationTests", repoRoot);
|
||||
Targets.Test(TestsIdentityServerEndToEndTests, "identity-server/test/IdentityServer.EndToEndTests", repoRoot);
|
||||
|
||||
Target(SharedTargets.Default, [
|
||||
SharedTargets.CheckSolutions,
|
||||
SharedTargets.CheckUnusedPackages,
|
||||
SharedTargets.CheckSortedRefs,
|
||||
SharedTargets.CheckSortedSlnf,
|
||||
SharedTargets.VerifyFormatting,
|
||||
SharedTargets.Clean,
|
||||
SharedTargets.VerifyNoChanges,
|
||||
SharedTargets.DotnetDevCerts,
|
||||
TestsIdentityServerUnitTests,
|
||||
TestsIdentityServerIntegrationTests,
|
||||
TestsIdentityServerEndToEndTests
|
||||
]);
|
||||
|
||||
await RunTargetsAndExitAsync(args);
|
||||
|
|
@ -4,5 +4,6 @@
|
|||
<AnalysisMode>None</AnalysisMode>
|
||||
<IsIdSrvProject>true</IsIdSrvProject>
|
||||
<WarnOnPackingNonPackableProject>false</WarnOnPackingNonPackableProject>
|
||||
<Nullable>disable</Nullable><!-- TODO: enable nullable -->
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<RootNamespace>IdentityServerHost</RootNamespace>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<RootNamespace>IdentityServerHost</RootNamespace>
|
||||
<Nullable>enable</Nullable>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
|
||||
<RootNamespace>IdentityServerHost</RootNamespace>
|
||||
<UserSecretsId>e60c119c-8b86-4016-9d44-80e25948dbba</UserSecretsId>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>Duende.IdentityServer.Hosts.Shared</RootNamespace>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
|
||||
<RootNamespace>Duende.IdentityServer.UI.AspNetIdentity</RootNamespace>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
|
||||
<RootNamespace>Duende.IdentityServer.UI.EntityFramework</RootNamespace>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
|
||||
<RootNamespace>Duende.IdentityServer.UI</RootNamespace>
|
||||
|
|
|
|||
|
|
@ -4,5 +4,6 @@
|
|||
<AnalysisMode>None</AnalysisMode>
|
||||
<IsIdSrvProject>true</IsIdSrvProject>
|
||||
<WarnOnPackingNonPackableProject>false</WarnOnPackingNonPackableProject>
|
||||
<Nullable>disable</Nullable><!-- TODO: enable nullable -->
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -2,5 +2,6 @@
|
|||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)..\'))" />
|
||||
<PropertyGroup>
|
||||
<AnalysisMode>None</AnalysisMode>
|
||||
<Nullable>disable</Nullable><!-- TODO: enable nullable -->
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
<MinVerTagPrefix>is-</MinVerTagPrefix>
|
||||
<MinVerMinimumMajorMinor>8.0</MinVerMinimumMajorMinor>
|
||||
<IsIdSrvProject>true</IsIdSrvProject>
|
||||
<Nullable>disable</Nullable><!-- TODO: enable nullable -->
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<NoWarn>$(NoWarn);CA1002;CA1008;CA1031;CA1051;CA1054;CA1055;CA1056;CA1062;CA1716;CA1724;CA1725;CA1727;CA1819;CA1848;CA1851;CA2201;CA2208;CA2227;CA2234</NoWarn>
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ public class PersistedGrantStore : Duende.IdentityServer.Stores.IPersistedGrantS
|
|||
|
||||
private static IQueryable<PersistedGrant> Filter(IQueryable<PersistedGrant> query, PersistedGrantFilter filter)
|
||||
{
|
||||
if (filter.ClientIds != null)
|
||||
if (filter.ClientIds.Count > 0)
|
||||
{
|
||||
var ids = filter.ClientIds.ToList();
|
||||
if (!string.IsNullOrWhiteSpace(filter.ClientId))
|
||||
|
|
@ -182,7 +182,7 @@ public class PersistedGrantStore : Duende.IdentityServer.Stores.IPersistedGrantS
|
|||
query = query.Where(x => x.SubjectId == filter.SubjectId);
|
||||
}
|
||||
|
||||
if (filter.Types != null)
|
||||
if (filter.Types.Count > 0)
|
||||
{
|
||||
var types = filter.Types.ToList();
|
||||
if (!string.IsNullOrWhiteSpace(filter.Type))
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ public class LocalApiAuthenticationHandler : AuthenticationHandler<LocalApiAuthe
|
|||
}
|
||||
|
||||
var proofToken = Context.Request.Headers[OidcConstants.HttpHeaders.DPoP].FirstOrDefault();
|
||||
var validationContext = new DPoPProofValidatonContext
|
||||
var validationContext = new DPoPProofValidationContext
|
||||
{
|
||||
ProofToken = proofToken,
|
||||
Method = Context.Request.Method,
|
||||
|
|
|
|||
|
|
@ -61,10 +61,7 @@ public class DefaultSessionManagementService : ISessionManagementService
|
|||
SessionId = context.SessionId,
|
||||
};
|
||||
|
||||
if (context.ClientIds != null)
|
||||
{
|
||||
grantFilter.ClientIds = context.ClientIds;
|
||||
}
|
||||
grantFilter.ClientIds = context.ClientIds ?? [];
|
||||
|
||||
if (!context.RevokeTokens || !context.RevokeConsents)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ public class InMemoryPersistedGrantStore : IPersistedGrantStore
|
|||
from item in _repository
|
||||
select item.Value;
|
||||
|
||||
if (filter.ClientIds != null)
|
||||
if (filter.ClientIds.Count > 0)
|
||||
{
|
||||
var ids = filter.ClientIds.ToList();
|
||||
if (!string.IsNullOrWhiteSpace(filter.ClientId))
|
||||
|
|
@ -106,7 +106,7 @@ public class InMemoryPersistedGrantStore : IPersistedGrantStore
|
|||
query = query.Where(x => x.SubjectId == filter.SubjectId);
|
||||
}
|
||||
|
||||
if (filter.Types != null)
|
||||
if (filter.Types.Count > 0)
|
||||
{
|
||||
var types = filter.Types.ToList();
|
||||
if (!string.IsNullOrWhiteSpace(filter.Type))
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Duende.IdentityServer.Validation;
|
|||
/// <summary>
|
||||
/// Models the context for validaing DPoP proof tokens.
|
||||
/// </summary>
|
||||
public class DPoPProofValidatonContext
|
||||
public class DPoPProofValidationContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum setting to control validation for the DPoP proof token expiration.
|
||||
|
|
@ -69,9 +69,9 @@ public class DefaultDPoPProofValidator : IDPoPProofValidator
|
|||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task<DPoPProofValidatonResult> ValidateAsync(DPoPProofValidatonContext context, Ct ct)
|
||||
public async Task<DPoPProofValidationResult> ValidateAsync(DPoPProofValidationContext context, Ct ct)
|
||||
{
|
||||
var result = new DPoPProofValidatonResult() { IsError = false };
|
||||
var result = new DPoPProofValidationResult() { IsError = false };
|
||||
|
||||
try
|
||||
{
|
||||
|
|
@ -120,7 +120,7 @@ public class DefaultDPoPProofValidator : IDPoPProofValidator
|
|||
/// <summary>
|
||||
/// Validates the header.
|
||||
/// </summary>
|
||||
protected virtual Task ValidateHeaderAsync(DPoPProofValidatonContext context, DPoPProofValidatonResult result)
|
||||
protected virtual Task ValidateHeaderAsync(DPoPProofValidationContext context, DPoPProofValidationResult result)
|
||||
{
|
||||
JsonWebToken token;
|
||||
var handler = new JsonWebTokenHandler();
|
||||
|
|
@ -242,7 +242,7 @@ public class DefaultDPoPProofValidator : IDPoPProofValidator
|
|||
/// <summary>
|
||||
/// Validates the signature.
|
||||
/// </summary>
|
||||
protected virtual async Task ValidateSignatureAsync(DPoPProofValidatonContext context, DPoPProofValidatonResult result)
|
||||
protected virtual async Task ValidateSignatureAsync(DPoPProofValidationContext context, DPoPProofValidationResult result)
|
||||
{
|
||||
Microsoft.IdentityModel.Tokens.TokenValidationResult tokenValidationResult;
|
||||
|
||||
|
|
@ -284,7 +284,7 @@ public class DefaultDPoPProofValidator : IDPoPProofValidator
|
|||
/// <summary>
|
||||
/// Validates the payload.
|
||||
/// </summary>
|
||||
protected virtual async Task ValidatePayloadAsync(DPoPProofValidatonContext context, DPoPProofValidatonResult result, Ct ct)
|
||||
protected virtual async Task ValidatePayloadAsync(DPoPProofValidationContext context, DPoPProofValidationResult result, Ct ct)
|
||||
{
|
||||
if (context.ValidateAccessToken)
|
||||
{
|
||||
|
|
@ -379,9 +379,9 @@ public class DefaultDPoPProofValidator : IDPoPProofValidator
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates is the token has been replayed.
|
||||
/// Validates if the token has been replayed.
|
||||
/// </summary>
|
||||
protected virtual async Task ValidateReplayAsync(DPoPProofValidatonContext context, DPoPProofValidatonResult result, Ct ct)
|
||||
protected virtual async Task ValidateReplayAsync(DPoPProofValidationContext context, DPoPProofValidationResult result, Ct ct)
|
||||
{
|
||||
if (await ReplayCache.ExistsAsync(ReplayCachePurpose, result.TokenId, ct))
|
||||
{
|
||||
|
|
@ -416,7 +416,7 @@ public class DefaultDPoPProofValidator : IDPoPProofValidator
|
|||
/// <summary>
|
||||
/// Validates the freshness.
|
||||
/// </summary>
|
||||
protected virtual async Task ValidateFreshnessAsync(DPoPProofValidatonContext context, DPoPProofValidatonResult result)
|
||||
protected virtual async Task ValidateFreshnessAsync(DPoPProofValidationContext context, DPoPProofValidationResult result)
|
||||
{
|
||||
var validateIat = (context.ExpirationValidationMode & DPoPTokenExpirationValidationMode.Iat) == DPoPTokenExpirationValidationMode.Iat;
|
||||
if (validateIat)
|
||||
|
|
@ -442,7 +442,7 @@ public class DefaultDPoPProofValidator : IDPoPProofValidator
|
|||
/// <summary>
|
||||
/// Validates the freshness of the iat value.
|
||||
/// </summary>
|
||||
protected virtual Task ValidateIatAsync(DPoPProofValidatonContext context, DPoPProofValidatonResult result)
|
||||
protected virtual Task ValidateIatAsync(DPoPProofValidationContext context, DPoPProofValidationResult result)
|
||||
{
|
||||
if (IsExpired(context, result, context.ClientClockSkew, result.IssuedAt.Value))
|
||||
{
|
||||
|
|
@ -457,7 +457,7 @@ public class DefaultDPoPProofValidator : IDPoPProofValidator
|
|||
/// <summary>
|
||||
/// Validates the freshness of the nonce value.
|
||||
/// </summary>
|
||||
protected virtual async Task ValidateNonceAsync(DPoPProofValidatonContext context, DPoPProofValidatonResult result)
|
||||
protected virtual async Task ValidateNonceAsync(DPoPProofValidationContext context, DPoPProofValidationResult result)
|
||||
{
|
||||
if (result.Nonce.IsMissing())
|
||||
{
|
||||
|
|
@ -496,7 +496,7 @@ public class DefaultDPoPProofValidator : IDPoPProofValidator
|
|||
/// Creates a nonce value to return to the client.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual string CreateNonce(DPoPProofValidatonContext context, DPoPProofValidatonResult result)
|
||||
protected virtual string CreateNonce(DPoPProofValidationContext context, DPoPProofValidationResult result)
|
||||
{
|
||||
var now = TimeProvider.GetUtcNow().ToUnixTimeSeconds();
|
||||
return DataProtector.Protect(now.ToString(CultureInfo.InvariantCulture));
|
||||
|
|
@ -506,7 +506,7 @@ public class DefaultDPoPProofValidator : IDPoPProofValidator
|
|||
/// Reads the time the nonce was created.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected virtual ValueTask<long> GetUnixTimeFromNonceAsync(DPoPProofValidatonContext context, DPoPProofValidatonResult result)
|
||||
protected virtual ValueTask<long> GetUnixTimeFromNonceAsync(DPoPProofValidationContext context, DPoPProofValidationResult result)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -528,7 +528,7 @@ public class DefaultDPoPProofValidator : IDPoPProofValidator
|
|||
/// Validates the expiration of the DPoP proof.
|
||||
/// Returns true if the time is beyond the allowed limits, false otherwise.
|
||||
/// </summary>
|
||||
protected virtual bool IsExpired(DPoPProofValidatonContext context, DPoPProofValidatonResult result, TimeSpan clockSkew, long issuedAtTime)
|
||||
protected virtual bool IsExpired(DPoPProofValidationContext context, DPoPProofValidationResult result, TimeSpan clockSkew, long issuedAtTime)
|
||||
{
|
||||
var now = TimeProvider.GetUtcNow().ToUnixTimeSeconds();
|
||||
var start = now + (int)clockSkew.TotalSeconds;
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ internal class PushedAuthorizationRequestValidator(
|
|||
|
||||
// validate proof token
|
||||
var parUrl = context.ClientCertificate == null ? serverUrls.BaseUrl.EnsureTrailingSlash() + ProtocolRoutePaths.PushedAuthorization : mtlsEndpointGenerator.GetMtlsEndpointPath(ProtocolRoutePaths.PushedAuthorization);
|
||||
var dpopContext = new DPoPProofValidatonContext
|
||||
var dpopContext = new DPoPProofValidationContext
|
||||
{
|
||||
ProofToken = context.DPoPProofToken,
|
||||
ExpirationValidationMode = context.Client.DPoPValidationMode,
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ internal class TokenRequestValidator : ITokenRequestValidator
|
|||
}
|
||||
|
||||
var tokenUrl = context.ClientCertificate == null ? _serverUrls.BaseUrl.EnsureTrailingSlash() + ProtocolRoutePaths.Token : _mtlsEndpointGenerator.GetMtlsEndpointPath(ProtocolRoutePaths.Token);
|
||||
var dpopContext = new DPoPProofValidatonContext
|
||||
var dpopContext = new DPoPProofValidationContext
|
||||
{
|
||||
ExpirationValidationMode = _validatedRequest.Client.DPoPValidationMode,
|
||||
ClientClockSkew = _validatedRequest.Client.DPoPClockSkew,
|
||||
|
|
|
|||
|
|
@ -16,5 +16,5 @@ public interface IDPoPProofValidator
|
|||
/// </summary>
|
||||
/// <param name="context">The validation context.</param>
|
||||
/// <param name="ct">The cancellation token.</param>
|
||||
Task<DPoPProofValidatonResult> ValidateAsync(DPoPProofValidatonContext context, Ct ct);
|
||||
Task<DPoPProofValidationResult> ValidateAsync(DPoPProofValidationContext context, Ct ct);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace Duende.IdentityServer.Validation;
|
|||
/// <summary>
|
||||
/// Models the result of DPoP proof validation.
|
||||
/// </summary>
|
||||
public class DPoPProofValidatonResult : ValidationResult
|
||||
public class DPoPProofValidationResult : ValidationResult
|
||||
{
|
||||
/// <summary>
|
||||
/// The serialized JWK from the validated DPoP proof token.
|
||||
|
|
@ -20,11 +20,11 @@ public static class PersistedGrantFilterExtensions
|
|||
ArgumentNullException.ThrowIfNull(filter);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(filter.ClientId) &&
|
||||
filter.ClientIds == null &&
|
||||
filter.ClientIds.Count == 0 &&
|
||||
string.IsNullOrWhiteSpace(filter.SessionId) &&
|
||||
string.IsNullOrWhiteSpace(filter.SubjectId) &&
|
||||
string.IsNullOrWhiteSpace(filter.Type) &&
|
||||
filter.Types == null)
|
||||
filter.Types.Count == 0)
|
||||
{
|
||||
throw new ArgumentException("No filter values set.", nameof(filter));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ public class PersistedGrantFilter
|
|||
/// <summary>
|
||||
/// Client ids the grant was issued to.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<string>? ClientIds { get; set; }
|
||||
public IReadOnlyCollection<string> ClientIds { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// The type of grant.
|
||||
|
|
@ -41,5 +41,5 @@ public class PersistedGrantFilter
|
|||
/// <summary>
|
||||
/// The types of grants.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<string>? Types { get; set; }
|
||||
public IReadOnlyCollection<string> Types { get; set; } = [];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,5 +5,39 @@
|
|||
<Import Project="../identity-server.props" />
|
||||
<PropertyGroup>
|
||||
<IsIdSrvProject>true</IsIdSrvProject>
|
||||
<Nullable>disable</Nullable><!-- TODO: enable nullable -->
|
||||
<!-- TODO: Fix these in identity-server test code and remove suppressions -->
|
||||
<NoWarn>$(NoWarn);CA1001</NoWarn><!-- Types that own disposable fields should be disposable -->
|
||||
<NoWarn>$(NoWarn);CA1041</NoWarn><!-- Provide ObsoleteAttribute message -->
|
||||
<NoWarn>$(NoWarn);CA1051</NoWarn><!-- Do not declare visible instance fields -->
|
||||
<NoWarn>$(NoWarn);CA1304</NoWarn><!-- Specify CultureInfo -->
|
||||
<NoWarn>$(NoWarn);CA1305</NoWarn><!-- Specify IFormatProvider -->
|
||||
<NoWarn>$(NoWarn);CA1309</NoWarn><!-- Use ordinal StringComparison -->
|
||||
<NoWarn>$(NoWarn);CA1310</NoWarn><!-- Specify StringComparison for correctness -->
|
||||
<NoWarn>$(NoWarn);CA1311</NoWarn><!-- Specify a culture or use an invariant version -->
|
||||
<NoWarn>$(NoWarn);CA1707</NoWarn><!-- Identifiers should not contain underscores -->
|
||||
<NoWarn>$(NoWarn);CA1708</NoWarn><!-- Identifiers should differ by more than case -->
|
||||
<NoWarn>$(NoWarn);CA1711</NoWarn><!-- Identifiers should not have incorrect suffix -->
|
||||
<NoWarn>$(NoWarn);CA1716</NoWarn><!-- Identifiers should not match keywords -->
|
||||
<NoWarn>$(NoWarn);CA1725</NoWarn><!-- Parameter names should match base declaration -->
|
||||
<NoWarn>$(NoWarn);CA1805</NoWarn><!-- Do not initialize unnecessarily -->
|
||||
<NoWarn>$(NoWarn);CA1806</NoWarn><!-- Do not ignore method results -->
|
||||
<NoWarn>$(NoWarn);CA1816</NoWarn><!-- Call GC.SuppressFinalize correctly -->
|
||||
<NoWarn>$(NoWarn);CA1822</NoWarn><!-- Mark members as static -->
|
||||
<NoWarn>$(NoWarn);CA1825</NoWarn><!-- Avoid zero-length array allocations -->
|
||||
<NoWarn>$(NoWarn);CA1829</NoWarn><!-- Use Length/Count property instead of Count() -->
|
||||
<NoWarn>$(NoWarn);CA1835</NoWarn><!-- Prefer Memory-based overloads for ReadAsync/WriteAsync -->
|
||||
<NoWarn>$(NoWarn);CA1850</NoWarn><!-- Prefer static HashData method over ComputeHash -->
|
||||
<NoWarn>$(NoWarn);CA1852</NoWarn><!-- Seal internal types -->
|
||||
<NoWarn>$(NoWarn);CA1859</NoWarn><!-- Use concrete types when possible for improved performance -->
|
||||
<NoWarn>$(NoWarn);CA1860</NoWarn><!-- Avoid using Enumerable.Any() extension method -->
|
||||
<NoWarn>$(NoWarn);CA1861</NoWarn><!-- Avoid constant arrays as arguments -->
|
||||
<NoWarn>$(NoWarn);CA1863</NoWarn><!-- Cache and reuse CompositeFormat instances -->
|
||||
<NoWarn>$(NoWarn);CA1864</NoWarn><!-- Prefer IDictionary.TryAdd(TKey, TValue) -->
|
||||
<NoWarn>$(NoWarn);CA1869</NoWarn><!-- Cache and reuse JsonSerializerOptions instances -->
|
||||
<NoWarn>$(NoWarn);CA1872</NoWarn><!-- Prefer Convert.ToHexString and Convert.ToHexStringLower -->
|
||||
<NoWarn>$(NoWarn);CA2201</NoWarn><!-- Do not raise reserved exception types -->
|
||||
<NoWarn>$(NoWarn);CA2211</NoWarn><!-- Non-constant fields should not be visible -->
|
||||
<NoWarn>$(NoWarn);CA5350</NoWarn><!-- Do not use weak cryptographic algorithms -->
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -444,7 +444,7 @@ public class DPoPTokenEndpointTests : DPoPEndpointTestBase
|
|||
|
||||
public string ServerIssuedNonce { get; set; }
|
||||
|
||||
protected override async Task ValidateFreshnessAsync(DPoPProofValidatonContext context, DPoPProofValidatonResult result)
|
||||
protected override async Task ValidateFreshnessAsync(DPoPProofValidationContext context, DPoPProofValidationResult result)
|
||||
{
|
||||
if (ServerIssuedNonce.IsPresent())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ public class DPoPProofValidatorTests
|
|||
}
|
||||
}
|
||||
|
||||
private DPoPProofValidatonContext _context = new DPoPProofValidatonContext
|
||||
private DPoPProofValidationContext _context = new DPoPProofValidationContext
|
||||
{
|
||||
ClientClockSkew = TimeSpan.Zero,
|
||||
Url = "https://identityserver/connect/token",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
<Import Project="../../src.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<Nullable>enable</Nullable>
|
||||
<Product>Duende IgnoreThis</Product>
|
||||
<MinVerTagPrefix>it-</MinVerTagPrefix>
|
||||
<MinVerMinimumMajorMinor>0.1</MinVerMinimumMajorMinor>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<PackageId>Duende.IgnoreThis</PackageId>
|
||||
<AssemblyName>$(PackageId)</AssemblyName>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,4 @@
|
|||
<Project>
|
||||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)..\'))" />
|
||||
<Import Project="../../test.props" />
|
||||
<PropertyGroup>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -11,12 +11,6 @@
|
|||
<Folder Name="/aspnetcore-authentication-jwtbearer/test/">
|
||||
<Project Path="aspnetcore-authentication-jwtbearer/test/AspNetCore.Authentication.JwtBearer.Tests/AspNetCore.Authentication.JwtBearer.Tests.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/conformance-report/src/">
|
||||
<Project Path="conformance-report/src/ConformanceReport/ConformanceReport.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/conformance-report/test/">
|
||||
<Project Path="conformance-report/test/ConformanceReport.Tests/ConformanceReport.Tests.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/bff/hosts/">
|
||||
<Project Path="bff/hosts/Hosts.AppHost/Hosts.AppHost.csproj" />
|
||||
<Project Path="bff/hosts/Hosts.Bff.DPoP/Hosts.Bff.DPoP.csproj" />
|
||||
|
|
@ -43,6 +37,10 @@
|
|||
<Folder Name="/bff/migrations/">
|
||||
<Project Path="bff/migrations/UserSessionDb/UserSessionDb.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/bff/performance/">
|
||||
<Project Path="bff/performance/Bff.Benchmarks/Bff.Benchmarks.csproj" />
|
||||
<Project Path="bff/performance/Bff.Performance/Bff.Performance.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/bff/src/">
|
||||
<Project Path="bff/src/Bff.Blazor.Client/Bff.Blazor.Client.csproj" />
|
||||
<Project Path="bff/src/Bff.Blazor/Bff.Blazor.csproj" />
|
||||
|
|
@ -50,10 +48,6 @@
|
|||
<Project Path="bff/src/Bff.Yarp/Bff.Yarp.csproj" />
|
||||
<Project Path="bff/src/Bff/Bff.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/bff/performance/">
|
||||
<Project Path="bff/performance/Bff.Benchmarks/Bff.Benchmarks.csproj" />
|
||||
<Project Path="bff/performance/Bff.Performance/Bff.Performance.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/bff/templates/src/">
|
||||
<Project Path="bff/templates/src/BffLocalApi/BffLocalApi.csproj" />
|
||||
<Project Path="bff/templates/src/BffRemoteApi/BffRemoteApi.csproj" />
|
||||
|
|
@ -66,9 +60,15 @@
|
|||
<Project Path="bff/test/Bff.Tests/Bff.Tests.csproj" />
|
||||
<Project Path="bff/test/Hosts.Tests/Hosts.Tests.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/conformance-report/src/">
|
||||
<Project Path="conformance-report/src/ConformanceReport/ConformanceReport.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/conformance-report/test/">
|
||||
<Project Path="conformance-report/test/ConformanceReport.Tests/ConformanceReport.Tests.csproj" />
|
||||
</Folder>
|
||||
<Folder Name="/docs-mcp/">
|
||||
<File Path="docs-mcp/README.md" />
|
||||
<Project Path="docs-mcp/src/Documentation.Mcp/Documentation.Mcp.csproj" />
|
||||
<File Path="docs-mcp/README.md" />
|
||||
</Folder>
|
||||
<Folder Name="/docs-mcp/.config/">
|
||||
<File Path="docs-mcp/.config/dotnet-tools.json" />
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
<PropertyGroup>
|
||||
<AnalysisMode>None</AnalysisMode>
|
||||
<ManagePackageVersionsCentrally>false</ManagePackageVersionsCentrally>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsTestProject>false</IsTestProject>
|
||||
<RootNamespace>Shouldly</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<AnalysisMode>None</AnalysisMode>
|
||||
<Nullable>enable</Nullable>
|
||||
<AssemblyName>Duende.Xunit.Playwright</AssemblyName>
|
||||
<RootNamespace>Duende.Xunit.Playwright</RootNamespace>
|
||||
<IsTestProject>false</IsTestProject>
|
||||
|
|
|
|||
42
src.props
42
src.props
|
|
@ -1,33 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<IsTestProject>false</IsTestProject>
|
||||
<IsPackable>true</IsPackable>
|
||||
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
|
||||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
|
||||
|
||||
<!--NuGet-->
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
<!-- TODO - Verify that license is included in nuget packages -->
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile>
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<PackageProjectUrl>https://github.com/duendesoftware/products</PackageProjectUrl>
|
||||
<PackageReleaseNotes>https://github.com/duendesoftware/products/releases</PackageReleaseNotes>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
|
||||
<!--Minver-->
|
||||
<BUILD_NUMBER Condition="'$(BUILD_NUMBER)' == ''">0</BUILD_NUMBER>
|
||||
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath><!-- TODO: move to Directory.Build.props -->
|
||||
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles><!-- TODO: move to Directory.Build.props -->
|
||||
<IsPackable>true</IsPackable>
|
||||
<MinVerBuildMetadata>build.$(BUILD_NUMBER)</MinVerBuildMetadata>
|
||||
<MinVerAutoIncrement>patch</MinVerAutoIncrement>
|
||||
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<PackageLicenseFile>LICENSE</PackageLicenseFile><!-- TODO: verify license is included in packages -->
|
||||
<PackageProjectUrl>https://github.com/duendesoftware/products</PackageProjectUrl>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageReadmePath>../../README.md</PackageReadmePath>
|
||||
<PackageReleaseNotes>https://github.com/duendesoftware/products/releases</PackageReleaseNotes>
|
||||
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- TODO: check which of these properties are actually required -->
|
||||
<PropertyGroup Label="SourceLink">
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<NoWarn>$(NoWarn);RS0016</NoWarn><!-- Add public types and members to the declared API -->
|
||||
|
|
@ -41,8 +34,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<None Include="../../../icon.png" Pack="true" Visible="false" PackagePath="" />
|
||||
<None Include="$(PackageReadmePath)" Pack="true" PackagePath="" />
|
||||
<None Include="../../../LICENSE" Pack="true" PackagePath="" />
|
||||
<None Include="$(PackageReadmePath)" Pack="true" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>$(NoWarn);CA1303</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
<IsTestProject>false</IsTestProject>
|
||||
<IsPackable>true</IsPackable>
|
||||
<Nullable>disable</Nullable><!-- TODO: enable nullable -->
|
||||
|
||||
<PackageId>Duende.Templates</PackageId>
|
||||
<Description>Templates for Duende Identity Server and Duende BFF </Description>
|
||||
|
|
|
|||
62
test.props
62
test.props
|
|
@ -8,66 +8,10 @@
|
|||
<OutputType>exe</OutputType>
|
||||
<!-- Enable Microsoft Testing Platform command line experience for code coverage support -->
|
||||
<UseMicrosoftTestingPlatformRunner>true</UseMicrosoftTestingPlatformRunner>
|
||||
<!-- Suppress analyzer rules inappropriate for test projects -->
|
||||
<!-- CA1000: No static members on generic types — generic test fixtures commonly use static helpers -->
|
||||
<!-- CA1001: Types owning disposable fields should be disposable — test classes rely on xunit lifecycle -->
|
||||
<!-- CA1002: Use Collection<T> instead of List<T> — test fixtures use List<T> for convenience -->
|
||||
<!-- CA1003: Use generic EventHandler — test infrastructure uses Action delegates -->
|
||||
<!-- CA1012: Abstract types should not have public constructors — test base classes need public ctors for xunit -->
|
||||
<!-- CA1024: Use properties where appropriate — test helpers use Get methods for clarity -->
|
||||
<!-- CA1031: Catch more specific exception — test infrastructure intentionally catches all exceptions -->
|
||||
<!-- CA1033: Explicit interface implementation — test mocks use explicit interface impls without sealing -->
|
||||
<!-- CA1041: Provide ObsoleteAttribute message — test methods use [Obsolete] to skip without message -->
|
||||
<!-- CA1051: Do not declare visible instance fields — test base classes expose fields for subclasses -->
|
||||
<!-- CA1052: Static holder types should be static — test classes with only static [Fact] methods are common -->
|
||||
<!-- CA1054/CA1055/CA1056: URI parameters/return/properties should not be strings — test helpers use strings -->
|
||||
<!-- CA1062: Validate public method parameters — test code relies on xunit for argument validation -->
|
||||
<!-- CA1063: Implement IDisposable correctly — test infrastructure uses simplified disposal patterns -->
|
||||
<!-- CA1304/CA1305/CA1307/CA1308/CA1309/CA1310/CA1311: Locale/culture/ordinal rules — not critical in test code -->
|
||||
<!-- CA1508: Avoid dead conditional code — tests intentionally verify always-true/false conditions -->
|
||||
<!-- CA1515: Make class internal — test classes must be public for xunit discovery -->
|
||||
<!-- CA1707: Identifiers should not contain underscores — snake_case test method names are conventional -->
|
||||
<!-- CA1708: Namespace names differ only by case — test namespaces mirror SUT folder structure (V2 vs v2) -->
|
||||
<!-- CA1711: Identifiers should not have incorrect suffix — xunit [CollectionDefinition] requires 'Collection' suffix -->
|
||||
<!-- CA1716: Reserved language keyword in namespace — test namespaces use 'Default' to mirror SUT structure -->
|
||||
<!-- CA1724: Type names should not match namespaces — test types like TestHost commonly shadow framework namespaces -->
|
||||
<!-- CA1725: Parameter names should match base — test overrides use abbreviated names (ct) -->
|
||||
<!-- CA1805: Do not initialize unnecessarily — clarity preferred in test code -->
|
||||
<!-- CA1806: Return value not used / object instantiated but not used — tests verify ctor exceptions -->
|
||||
<!-- CA1810: Initialize static fields when declared — test classes use static ctors for complex initialization -->
|
||||
<!-- CA1812: Internal class never instantiated — test classes instantiated via DI/reflection -->
|
||||
<!-- CA1816: Call GC.SuppressFinalize — test infrastructure uses simplified disposal patterns -->
|
||||
<!-- CA1820: Test for empty strings using Length — test code uses == "" for readability -->
|
||||
<!-- CA1822: Mark members as static — test helper methods may be non-static by convention -->
|
||||
<!-- CA1823: Unused fields — test fixture fields may be assigned but not directly referenced -->
|
||||
<!-- CA1825: Avoid zero-length array allocations — test code uses new T[0] for clarity -->
|
||||
<!-- CA1829: Use Count property — test code prioritizes readability over perf -->
|
||||
<!-- CA1835: Use Memory-based overloads — test code uses simpler byte[] overloads -->
|
||||
<!-- CA1848: Use LoggerMessage delegates — test infrastructure uses simple logging -->
|
||||
<!-- CA1849: Call async methods in async context — test infrastructure may use sync APIs intentionally -->
|
||||
<!-- CA1850: Prefer static hash methods — test code uses instance SHA256 for readability -->
|
||||
<!-- CA1851: Possible multiple enumerations — test assertions may enumerate multiple times intentionally -->
|
||||
<!-- CA1852: Type can be sealed — test infrastructure classes are not sealed for flexibility -->
|
||||
<!-- CA1859: Change return type for perf — test code prioritizes interface-based design over perf -->
|
||||
<!-- CA1860: Use Count > 0 instead of Any() — test code prioritizes readability -->
|
||||
<!-- CA1861: Prefer static readonly arrays — test code prioritizes inline readability -->
|
||||
<!-- CA1863: Cache CompositeFormat — test code uses string.Format with inline format strings -->
|
||||
<!-- CA1864: Use TryAdd — test code uses ContainsKey+Add for clarity -->
|
||||
<!-- CA1866: Use char overload — not critical in test code -->
|
||||
<!-- CA1869: Cache JsonSerializerOptions — test code creates options inline for clarity -->
|
||||
<!-- CA1872: Prefer Convert.ToHexString — test code uses BitConverter.ToString for readability -->
|
||||
<!-- CA2000: Dispose objects before losing scope — test code manages disposal differently -->
|
||||
<!-- CA2016: Forward CancellationToken — test infrastructure may intentionally not propagate -->
|
||||
<!-- CA2201: Do not raise reserved exception types — test infrastructure may throw Exception -->
|
||||
<!-- CA2211: Non-constant visible fields — test base classes expose mutable static fields -->
|
||||
<!-- CA2213: Dispose IDisposable fields — test classes rely on xunit lifecycle for cleanup -->
|
||||
<!-- CA2227: Collection properties should be read only — test DTOs need setters -->
|
||||
<!-- CA2234: Pass Uri instead of string — test code uses string URLs for readability -->
|
||||
<!-- CA2254: Logging template should not vary — test infrastructure builds templates dynamically -->
|
||||
<!-- CA5350: Weak cryptographic algorithm — test code uses TripleDES to validate SAML interop scenarios -->
|
||||
<NoWarn>$(NoWarn);CA1000;CA1001;CA1002;CA1003;CA1012;CA1024;CA1031;CA1033;CA1041;CA1051;CA1052;CA1054;CA1055;CA1056;CA1062;CA1063;CA1304;CA1305;CA1307;CA1308;CA1309;CA1310;CA1311;CA1508;CA1515;CA1707;CA1708;CA1711;CA1716;CA1724;CA1725;CA1805;CA1806;CA1810;CA1812;CA1816;CA1820;CA1822;CA1823;CA1825;CA1829;CA1835;CA1848;CA1849;CA1850;CA1851;CA1852;CA1859;CA1860;CA1861;CA1863;CA1864;CA1866;CA1869;CA1872;CA2000;CA2016;CA2201;CA2211;CA2213;CA2227;CA2234;CA2254;CA5350</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<NoWarn>$(NoWarn);CA1707</NoWarn><!-- Identifiers should not contain underscores -->
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" />
|
||||
<PackageReference Include="MartinCostello.Logging.XUnit.v3" />
|
||||
|
|
|
|||
Loading…
Reference in a new issue