From 11ce971444c20c9976abf0d5ad92a11d772878e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9rald=20Barr=C3=A9?= Date: Mon, 5 Aug 2024 15:50:47 -0400 Subject: [PATCH] Add coding standard (#90) --- Build.ps1 | 5 ++++ src/Directory.Build.props | 19 ++------------ .../AuthenticationBuilderExtensions.cs | 2 +- .../AuthorizationExtensions.cs | 6 ++--- .../ClientCredentialsDefaults.cs | 2 +- .../SecurityDefinitionDocumentFilter.cs | 10 ++++---- .../SecurityRequirementOperationFilter.cs | 16 ++++++------ .../OpenAPI/SwaggerUtils.cs | 6 ++--- .../RequireClientCredentialsAttribute.cs | 4 +-- ...uireClientCredentialsRequirementHandler.cs | 12 ++++----- ...thentication.ClientCredentialsGrant.csproj | 3 +-- .../AuthorizationExtensionsTest.cs | 8 +++--- .../IntegrationTests.cs | 4 +-- .../OpenApiSecurityDescriptionTests.cs | 8 +++--- .../RequireClientCredentialsAttributeTests.cs | 4 +-- ...lientCredentialsRequirementHandlerTests.cs | 18 ++++++------- ...cation.ClientCredentialsGrant.Tests.csproj | 7 +++--- .../XunitLoggerProvider.cs | 4 ++- .../IsExternalInit.cs | 25 +++++++++---------- .../OnStartupTokenCacheBackgroundService.cs | 2 +- .../Endpoints/ClientCredentialsController.cs | 2 +- 21 files changed, 77 insertions(+), 90 deletions(-) diff --git a/Build.ps1 b/Build.ps1 index ef44e97..2568102 100644 --- a/Build.ps1 +++ b/Build.ps1 @@ -20,6 +20,11 @@ Process { Push-Location $workingDir Remove-Item $outputDir -Force -Recurse -ErrorAction SilentlyContinue + # Duende.IdentityServer fails signature validation + # https://github.com/DuendeSoftware/Support/issues/1352 + # Note that the new certificate should be included in the next version of the .NET SDK (release on 2024/08/13) + $env:DOTNET_NUGET_SIGNATURE_VERIFICATION="false" + Exec { & dotnet clean -c Release } Exec { & dotnet build -c Release } Exec { & dotnet test -c Release --no-build --results-directory "$outputDir" --no-restore -l "trx" -l "console;verbosity=detailed" } diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 8914483..51b89ab 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -3,23 +3,17 @@ Copyright © Workleap $([System.DateTime]::UtcNow.ToString(yyyy)) Workleap Workleap - https://github.com/gsoft-inc/wl-authentication-clientcredentialsgrant Apache-2.0 - true latest enable latest-All enable - - true - - - + all - runtime; build; native; contentfiles; analyzers; buildtransitive + runtime; build; native; contentfiles; analyzers all @@ -27,15 +21,6 @@ - - - true - true - - - - - diff --git a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/AuthenticationBuilderExtensions.cs b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/AuthenticationBuilderExtensions.cs index 6a66a92..ac9de65 100644 --- a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/AuthenticationBuilderExtensions.cs +++ b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/AuthenticationBuilderExtensions.cs @@ -54,7 +54,7 @@ public static AuthenticationBuilder AddClientCredentials(this AuthenticationBuil { options.OperationFilter(); } - + if (options.DocumentFilterDescriptors.All(x => x.Type != typeof(SecurityDefinitionDocumentFilter))) { options.DocumentFilter(); diff --git a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/AuthorizationExtensions.cs b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/AuthorizationExtensions.cs index 0ca26cb..3ae695b 100644 --- a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/AuthorizationExtensions.cs +++ b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/AuthorizationExtensions.cs @@ -1,4 +1,4 @@ -using Workleap.AspNetCore.Authentication.ClientCredentialsGrant; +using Workleap.AspNetCore.Authentication.ClientCredentialsGrant; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.DependencyInjection.Extensions; @@ -49,7 +49,7 @@ public static IServiceCollection AddClientCredentialsAuthorization(this IService .AddAuthenticationSchemes(ClientCredentialsDefaults.AuthenticationScheme) .RequireAuthenticatedUser() .RequireClaim("scope", $"{jwtOptions.Audience}:{ScopeClaimMapping[ClientCredentialsScope.Admin]}")); - + authorizationOptions.AddPolicy( ClientCredentialsDefaults.RequireClientCredentialsPolicyName, policy => policy @@ -57,7 +57,7 @@ public static IServiceCollection AddClientCredentialsAuthorization(this IService .RequireAuthenticatedUser() .AddRequirements(new RequireClientCredentialsRequirement())); }); - + services.TryAddEnumerable(ServiceDescriptor.Singleton()); return services; diff --git a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/ClientCredentialsDefaults.cs b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/ClientCredentialsDefaults.cs index f45393b..587a414 100644 --- a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/ClientCredentialsDefaults.cs +++ b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/ClientCredentialsDefaults.cs @@ -5,7 +5,7 @@ public static class ClientCredentialsDefaults public const string AuthenticationScheme = "ClientCredentials"; internal const string AuthenticationType = "ClientCredentials"; - + internal const string RequireClientCredentialsPolicyName = "ClientCredentialsPolicy"; internal const string AuthorizationReadPolicy = "ClientCredentialsRead"; diff --git a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/OpenAPI/SecurityDefinitionDocumentFilter.cs b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/OpenAPI/SecurityDefinitionDocumentFilter.cs index 010f718..20203e4 100644 --- a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/OpenAPI/SecurityDefinitionDocumentFilter.cs +++ b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/OpenAPI/SecurityDefinitionDocumentFilter.cs @@ -1,4 +1,4 @@ -using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Extensions.Options; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; @@ -15,7 +15,7 @@ internal sealed class SecurityDefinitionDocumentFilter(IOptionsMonitor ExtractScopes(IEnumerable permissions) { // Audience has already been validated as non-empty var audience = this._jwtOptions.Audience!; - + var scopes = new Dictionary { [SwaggerUtils.GetScopeForAnyPermission(audience)] = "Request all permissions for specified client ID", diff --git a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/OpenAPI/SecurityRequirementOperationFilter.cs b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/OpenAPI/SecurityRequirementOperationFilter.cs index 67ff428..ec5cbd5 100644 --- a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/OpenAPI/SecurityRequirementOperationFilter.cs +++ b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/OpenAPI/SecurityRequirementOperationFilter.cs @@ -1,4 +1,4 @@ -using System.Globalization; +using System.Globalization; using System.Text; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Http; @@ -29,13 +29,13 @@ public void Apply(OpenApiOperation operation, OperationFilterContext context) this.AddOperationSecurityReference(operation, attributes); AppendScopeToOperationSummary(operation, attributes); } - + private static void AddAuthenticationAndAuthorizationErrorResponse(OpenApiOperation operation) { operation.Responses.TryAdd(StatusCodes.Status401Unauthorized.ToString(CultureInfo.InvariantCulture), new OpenApiResponse { Description = ReasonPhrases.GetReasonPhrase(StatusCodes.Status401Unauthorized) }); operation.Responses.TryAdd(StatusCodes.Status403Forbidden.ToString(CultureInfo.InvariantCulture), new OpenApiResponse { Description = ReasonPhrases.GetReasonPhrase(StatusCodes.Status403Forbidden) }); } - + private void AddOperationSecurityReference(OpenApiOperation operation, HashSet permissions) { var isAlreadyReferencingSecurityDefinition = operation.Security.Any(requirement => requirement.Keys.Any(key => key.Reference?.Id == ClientCredentialsDefaults.OpenApiSecurityDefinitionId)); @@ -43,7 +43,7 @@ private void AddOperationSecurityReference(OpenApiOperation operation, HashSet 0) { summary.Append(". "); } - + summary.Append(requireScopeSummary); operation.Summary = summary.ToString(); } - + private IEnumerable ExtractScopes(HashSet permissions) { foreach (var permission in permissions) diff --git a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/OpenAPI/SwaggerUtils.cs b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/OpenAPI/SwaggerUtils.cs index 2d7a6ed..bdab464 100644 --- a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/OpenAPI/SwaggerUtils.cs +++ b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/OpenAPI/SwaggerUtils.cs @@ -1,4 +1,4 @@ -using System.Reflection; +using System.Reflection; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc.ApiExplorer; using Swashbuckle.AspNetCore.SwaggerGen; @@ -18,7 +18,7 @@ public static IEnumerable GetRequiredPermissions(ApiDescription apiDescr { return []; } - + // Controllers - Attributes on the action method (empty for minimal APIs) attributes.AddRange(methodInfo.GetCustomAttributes(inherit: true)); } @@ -34,7 +34,7 @@ public static string FormatScopeForSpecificPermission(string audience, string pe { return $"target-entity:{audience}:{permission}"; } - + public static string GetScopeForAnyPermission(string audience) { return $"target-entity:{audience}"; diff --git a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/RequireClientCredentialsAttribute.cs b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/RequireClientCredentialsAttribute.cs index 51bee30..0f623f9 100644 --- a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/RequireClientCredentialsAttribute.cs +++ b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/RequireClientCredentialsAttribute.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Builder; @@ -32,7 +32,7 @@ public RequireClientCredentialsAttribute(ClientCredentialsScope scope) : this(EnumScopeNameMapping.GetValueOrDefault(scope) ?? throw new ArgumentOutOfRangeException(nameof(scope), scope, $"'{scope}' is not an valid scope value")) { } - + /// /// Verifies that the endpoint is called with the right granular permissions.
/// - It will check in those claims type: scope, scp or http://schemas.microsoft.com/identity/claims/scope
diff --git a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/RequireClientCredentialsRequirementHandler.cs b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/RequireClientCredentialsRequirementHandler.cs index 8bb8512..2ab26a8 100644 --- a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/RequireClientCredentialsRequirementHandler.cs +++ b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/RequireClientCredentialsRequirementHandler.cs @@ -1,4 +1,4 @@ -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Security.Claims; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; @@ -29,14 +29,14 @@ public RequireClientCredentialsRequirementHandler(IOptionsMonitor httpContext.GetEndpoint(), @@ -71,7 +71,7 @@ private string[] FormatScopes(string requiredPermission) { return [requiredPermission, $"{this._jwtOptions.Audience}:{requiredPermission}"]; } - + private static bool HasRequiredScope(ClaimsPrincipal claimsPrincipal, string[] requiredScopes) { return claimsPrincipal.Claims diff --git a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/Workleap.AspNetCore.Authentication.ClientCredentialsGrant.csproj b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/Workleap.AspNetCore.Authentication.ClientCredentialsGrant.csproj index 0f9f9b8..c4d28f5 100644 --- a/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/Workleap.AspNetCore.Authentication.ClientCredentialsGrant.csproj +++ b/src/Workleap.AspNetCore.Authentication.ClientCredentialsGrant/Workleap.AspNetCore.Authentication.ClientCredentialsGrant.csproj @@ -1,6 +1,6 @@ - net6.0;net7.0;net8.0 + net6.0;net8.0 true true snupkg @@ -16,7 +16,6 @@ - diff --git a/src/Workleap.Authentication.ClientCredentialsGrant.Tests/AuthorizationExtensionsTest.cs b/src/Workleap.Authentication.ClientCredentialsGrant.Tests/AuthorizationExtensionsTest.cs index 35aebc2..20e3370 100644 --- a/src/Workleap.Authentication.ClientCredentialsGrant.Tests/AuthorizationExtensionsTest.cs +++ b/src/Workleap.Authentication.ClientCredentialsGrant.Tests/AuthorizationExtensionsTest.cs @@ -1,4 +1,4 @@ -using Workleap.AspNetCore.Authentication.ClientCredentialsGrant; +using Workleap.AspNetCore.Authentication.ClientCredentialsGrant; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization.Infrastructure; @@ -50,11 +50,11 @@ public async Task GivenIServiceCollection_WhenAddClientCredentialsAuthorization_ var adminPolicy = authorizationValues.GetPolicy(ClientCredentialsDefaults.AuthorizationAdminPolicy); ValidateClassicPolicy(adminPolicy, ClientCredentialsScope.Admin); - + var requireClientCredentialsPolicy = authorizationValues.GetPolicy(ClientCredentialsDefaults.RequireClientCredentialsPolicyName); ValidateRequireClientCredentialsPolicy(requireClientCredentialsPolicy); } - + [Fact] public async Task GivenIServiceCollection_WhenAddClientCredentialsAuthorization_ThenRequirementHandlerRegistered() { @@ -91,7 +91,7 @@ private static void ValidateClassicPolicy(AuthorizationPolicy? policy, ClientCre Assert.Equal($"{DefaultAudience}:{AuthorizationExtensions.ScopeClaimMapping[scope]}", allowedScope); }); } - + private static void ValidateRequireClientCredentialsPolicy(AuthorizationPolicy? policy) { Assert.NotNull(policy); diff --git a/src/Workleap.Authentication.ClientCredentialsGrant.Tests/IntegrationTests.cs b/src/Workleap.Authentication.ClientCredentialsGrant.Tests/IntegrationTests.cs index c769522..bae511c 100644 --- a/src/Workleap.Authentication.ClientCredentialsGrant.Tests/IntegrationTests.cs +++ b/src/Workleap.Authentication.ClientCredentialsGrant.Tests/IntegrationTests.cs @@ -1,4 +1,4 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; using System.Net; using Duende.IdentityServer.Models; using Duende.IdentityServer.Stores; @@ -152,7 +152,7 @@ public async Task Real_Client_Server_Communication() // Using the classic policy, reading invoices should be successful because we're authenticated with a JWT that has the "invoices" audience and "invoices.read" scope var readInvoicesResponse = await invoicesReadHttpClient.GetStringAsync("https://invoice-app.local/read-invoices", cts.Token); Assert.Equal("This protected endpoint is for reading invoices", readInvoicesResponse); - + // Using the granular policy, reading invoices should be successful because we're authenticated with a JWT that has the "invoices" audience and "invoices.read" scope var readInvoicesGranularResponse = await invoicesReadHttpClient.GetStringAsync("https://invoice-app.local/read-invoices-granular", cts.Token); Assert.Equal("This protected endpoint is for reading invoices", readInvoicesGranularResponse); diff --git a/src/Workleap.Authentication.ClientCredentialsGrant.Tests/OpenAPI/OpenApiSecurityDescriptionTests.cs b/src/Workleap.Authentication.ClientCredentialsGrant.Tests/OpenAPI/OpenApiSecurityDescriptionTests.cs index 45738d0..3cceb3e 100644 --- a/src/Workleap.Authentication.ClientCredentialsGrant.Tests/OpenAPI/OpenApiSecurityDescriptionTests.cs +++ b/src/Workleap.Authentication.ClientCredentialsGrant.Tests/OpenAPI/OpenApiSecurityDescriptionTests.cs @@ -1,4 +1,4 @@ -using CliWrap; +using CliWrap; using Meziantou.Framework; namespace Workleap.Authentication.ClientCredentialsGrant.Tests.OpenAPI; @@ -9,7 +9,7 @@ public class OpenApiSecurityDescriptionTests public async Task Given_API_With_Client_Credentials_Attribute_When_Generating_OpenAPI_Then_Equal_Expected_Document() { var solutionPath = GetSolutionPath(); - + var testsFolder = Path.Combine(solutionPath, "tests"); var projectFolder = Path.Combine(testsFolder, "WebApi.OpenAPI.SystemTest"); var generatedFilePath = Path.Combine(projectFolder, "openapi-v1.yaml"); @@ -31,12 +31,12 @@ public async Task Given_API_With_Client_Credentials_Attribute_When_Generating_Op Assert.Equal(expectedFileContent, generatedFileContent, ignoreLineEndingDifferences: true); } - + private static string GetSolutionPath() { return GetGitRoot() / "src"; } - + private static FullPath GetGitRoot() { if (FullPath.CurrentDirectory().TryFindFirstAncestorOrSelf(current => Directory.Exists(current / ".git"), out var root)) diff --git a/src/Workleap.Authentication.ClientCredentialsGrant.Tests/RequireClientCredentialsAttributeTests.cs b/src/Workleap.Authentication.ClientCredentialsGrant.Tests/RequireClientCredentialsAttributeTests.cs index 3a8d626..8f91f45 100644 --- a/src/Workleap.Authentication.ClientCredentialsGrant.Tests/RequireClientCredentialsAttributeTests.cs +++ b/src/Workleap.Authentication.ClientCredentialsGrant.Tests/RequireClientCredentialsAttributeTests.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; using Microsoft.AspNetCore.Authorization; using Workleap.AspNetCore.Authentication.ClientCredentialsGrant; @@ -20,7 +20,7 @@ public void GivenInvalidClassicScope_WhenCreate_ThenThrowArgumentException() var scope = (ClientCredentialsScope)999; Assert.Throws(() => new RequireClientCredentialsAttribute(scope)); } - + [Fact] public void GivenSinglePermission_WhenCreate_ThenSamePermission() { diff --git a/src/Workleap.Authentication.ClientCredentialsGrant.Tests/RequireClientCredentialsRequirementHandlerTests.cs b/src/Workleap.Authentication.ClientCredentialsGrant.Tests/RequireClientCredentialsRequirementHandlerTests.cs index bed3881..70b6c34 100644 --- a/src/Workleap.Authentication.ClientCredentialsGrant.Tests/RequireClientCredentialsRequirementHandlerTests.cs +++ b/src/Workleap.Authentication.ClientCredentialsGrant.Tests/RequireClientCredentialsRequirementHandlerTests.cs @@ -1,4 +1,4 @@ -using System.Security.Claims; +using System.Security.Claims; using FakeItEasy; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; @@ -35,7 +35,7 @@ public async Task GivenUserHaveTheRequiredScopesInOneOfClaimType_WhenHandleRequi // Then Assert.True(context.HasSucceeded); } - + [Theory] [InlineData(true)] [InlineData(false)] @@ -43,13 +43,13 @@ public async Task GivenUserHaveOneOfTheRequiredScopes_WhenHandleRequirement_Then { // Given var expectedAudience = "invoices"; - + var userClaims = new List { new("scope", usePrefixAudienceFormat ? $"{expectedAudience}:requiredPermission" : "requiredPermission"), new("scope", "otherPermission"), }; - + var requiredPermission = "requiredPermission"; var context = ConfigureHandlerContext(userClaims, requiredPermission); @@ -64,7 +64,7 @@ public async Task GivenUserHaveOneOfTheRequiredScopes_WhenHandleRequirement_Then // Then Assert.True(context.HasSucceeded); } - + [Fact] public async Task GivenUserDoNotHaveTheRequiredScopes_WhenHandleRequirement_ThenNotSucceeded() { @@ -75,8 +75,6 @@ public async Task GivenUserDoNotHaveTheRequiredScopes_WhenHandleRequirement_Then new("scope", "otherPermission"), }; - var requiredPermission = "randomPermission"; - var context = ConfigureHandlerContext(userClaims, "randomPermission"); var handler = ConfigureHandler(new JwtBearerOptions()); @@ -86,12 +84,12 @@ public async Task GivenUserDoNotHaveTheRequiredScopes_WhenHandleRequirement_Then // Then Assert.False(context.HasSucceeded); } - + private static RequireClientCredentialsRequirementHandler ConfigureHandler(JwtBearerOptions jwtOptions) { var jwtOptionsMonitor = A.Fake>(); A.CallTo(() => jwtOptionsMonitor.Get(ClientCredentialsDefaults.AuthenticationScheme)).Returns(jwtOptions); - + return new RequireClientCredentialsRequirementHandler(jwtOptionsMonitor); } @@ -108,7 +106,7 @@ private static AuthorizationHandlerContext ConfigureHandlerContext(List c return new AuthorizationHandlerContext(new[] { new RequireClientCredentialsRequirement() }, user, httpContext); } - + private sealed class EndpointFeature : IEndpointFeature { public Endpoint? Endpoint { get; set; } diff --git a/src/Workleap.Authentication.ClientCredentialsGrant.Tests/Workleap.Authentication.ClientCredentialsGrant.Tests.csproj b/src/Workleap.Authentication.ClientCredentialsGrant.Tests/Workleap.Authentication.ClientCredentialsGrant.Tests.csproj index d7f9818..6b743eb 100644 --- a/src/Workleap.Authentication.ClientCredentialsGrant.Tests/Workleap.Authentication.ClientCredentialsGrant.Tests.csproj +++ b/src/Workleap.Authentication.ClientCredentialsGrant.Tests/Workleap.Authentication.ClientCredentialsGrant.Tests.csproj @@ -15,12 +15,11 @@ - + - - - + + diff --git a/src/Workleap.Authentication.ClientCredentialsGrant.Tests/XunitLoggerProvider.cs b/src/Workleap.Authentication.ClientCredentialsGrant.Tests/XunitLoggerProvider.cs index 9671b20..a511d74 100644 --- a/src/Workleap.Authentication.ClientCredentialsGrant.Tests/XunitLoggerProvider.cs +++ b/src/Workleap.Authentication.ClientCredentialsGrant.Tests/XunitLoggerProvider.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.Logging; +using System.Diagnostics.CodeAnalysis; +using Microsoft.Extensions.Logging; namespace Workleap.Authentication.ClientCredentialsGrant.Tests; @@ -27,6 +28,7 @@ public ILogger CreateLogger(string categoryName) return this; } + [SuppressMessage("ApiDesign", "RS0030:Do not use banned APIs")] public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { var message = formatter(state, exception); diff --git a/src/Workleap.Extensions.Http.Authentication.ClientCredentialsGrant/IsExternalInit.cs b/src/Workleap.Extensions.Http.Authentication.ClientCredentialsGrant/IsExternalInit.cs index 62cf578..35f71ac 100644 --- a/src/Workleap.Extensions.Http.Authentication.ClientCredentialsGrant/IsExternalInit.cs +++ b/src/Workleap.Extensions.Http.Authentication.ClientCredentialsGrant/IsExternalInit.cs @@ -1,17 +1,16 @@ -#if !NET5_0_OR_GREATER +#if !NET5_0_OR_GREATER + +using System.ComponentModel; + // ReSharper disable once CheckNamespace -namespace System.Runtime.CompilerServices -{ - // ReSharper disable once RedundantNameQualifier - using System.ComponentModel; +namespace System.Runtime.CompilerServices; - // Compiler helper class that allows using "init" keyword in .NET Standard 2.0: - // https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/init - // The same thing is also done in ASP.NET Core: - // https://github.com/dotnet/aspnetcore/blob/v6.0.0/src/Shared/IsExternalInit.cs - [EditorBrowsable(EditorBrowsableState.Never)] - internal static class IsExternalInit - { - } +// Compiler helper class that allows using "init" keyword in .NET Standard 2.0: +// https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/init +// The same thing is also done in ASP.NET Core: +// https://github.com/dotnet/aspnetcore/blob/v6.0.0/src/Shared/IsExternalInit.cs +[EditorBrowsable(EditorBrowsableState.Never)] +internal static class IsExternalInit +{ } #endif \ No newline at end of file diff --git a/src/Workleap.Extensions.Http.Authentication.ClientCredentialsGrant/OnStartupTokenCacheBackgroundService.cs b/src/Workleap.Extensions.Http.Authentication.ClientCredentialsGrant/OnStartupTokenCacheBackgroundService.cs index 6890a97..8d7f584 100644 --- a/src/Workleap.Extensions.Http.Authentication.ClientCredentialsGrant/OnStartupTokenCacheBackgroundService.cs +++ b/src/Workleap.Extensions.Http.Authentication.ClientCredentialsGrant/OnStartupTokenCacheBackgroundService.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; namespace Workleap.Extensions.Http.Authentication.ClientCredentialsGrant; diff --git a/src/tests/WebApi.OpenAPI.SystemTest/Endpoints/ClientCredentialsController.cs b/src/tests/WebApi.OpenAPI.SystemTest/Endpoints/ClientCredentialsController.cs index 0f1fa84..f36e2da 100644 --- a/src/tests/WebApi.OpenAPI.SystemTest/Endpoints/ClientCredentialsController.cs +++ b/src/tests/WebApi.OpenAPI.SystemTest/Endpoints/ClientCredentialsController.cs @@ -17,7 +17,7 @@ public IActionResult SeeCocktail(int id) { return this.Ok("Hello World!"); } - + [HttpPost] [Route("/controller-requires-permission")] [SwaggerOperation(Summary = "This controller method should require the cocktail.buy permission.")]