diff --git a/.editorconfig b/.editorconfig index cc55aca..523f92b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -54,6 +54,9 @@ csharp_space_between_square_brackets = false csharp_preserve_single_line_statements = true csharp_preserve_single_line_blocks = true +# Ensure source code is documented +dotnet_diagnostic.CS1591.severity = error + # Ensure names and members access are simplified dotnet_diagnostic.ide0001.severity = error dotnet_diagnostic.ide0002.severity = error diff --git a/NETCore.Keycloak.Client.Tests/Modules/KcAuthorizationTests/KcAuthorizationExtensionTests.cs b/NETCore.Keycloak.Client.Tests/Modules/KcAuthorizationTests/KcAuthorizationExtensionTests.cs index b808935..e0b57a6 100644 --- a/NETCore.Keycloak.Client.Tests/Modules/KcAuthorizationTests/KcAuthorizationExtensionTests.cs +++ b/NETCore.Keycloak.Client.Tests/Modules/KcAuthorizationTests/KcAuthorizationExtensionTests.cs @@ -68,7 +68,7 @@ public void ShouldRegisterAuthorizationHandler() }); // Create a mock for ILogger to simulate logging functionality. - var mockLogger = new Mock(); + var mockLogger = new Mock>(); _ = mockLogger.Setup(logger => logger.IsEnabled(It.IsAny())).Returns(true); // Add Keycloak services, the token handler, and the logger to the service collection. @@ -112,7 +112,7 @@ public void ShouldRegisterKeycloakProtectedResourcesPoliciesServices() var mockAuthorizationOptions = new Mock>(); // Create a mock for ILogger to simulate logging functionality. - var mockLogger = new Mock(); + var mockLogger = new Mock>(); _ = mockLogger.Setup(logger => logger.IsEnabled(It.IsAny())).Returns(true); // Add mocked services to the service collection. diff --git a/NETCore.Keycloak.Client.Tests/Modules/KcAuthorizationTests/KcBearerAuthorizationHandlerTests.cs b/NETCore.Keycloak.Client.Tests/Modules/KcAuthorizationTests/KcBearerAuthorizationHandlerTests.cs index b2e7c3a..82ac042 100644 --- a/NETCore.Keycloak.Client.Tests/Modules/KcAuthorizationTests/KcBearerAuthorizationHandlerTests.cs +++ b/NETCore.Keycloak.Client.Tests/Modules/KcAuthorizationTests/KcBearerAuthorizationHandlerTests.cs @@ -139,14 +139,14 @@ public void SetUp() .Returns(mockScope.Object); // Set up a mock logger to simulate logging functionality - var mockLogger = new Mock(); + var mockLogger = new Mock>(); _ = mockLogger.Setup(logger => logger.IsEnabled(It.IsAny())).Returns(true); // Configure the mock scope to resolve services _ = mockScope.Setup(x => x.ServiceProvider).Returns(_mockProvider.Object); // Mock resolution of ILogger from the service provider - _ = _mockProvider.Setup(x => x.GetService(typeof(ILogger))) + _ = _mockProvider.Setup(x => x.GetService(typeof(ILogger))) .Returns(mockLogger.Object); // Mock resolution of IHttpContextAccessor from the service provider @@ -772,14 +772,14 @@ private KcRealmAdminTokenHandler SetUpMockRealmAdminTokenHandler() .Returns(mockScope.Object); // Set up a mock logger to simulate logging functionality - var mockLogger = new Mock(); + var mockLogger = new Mock>(); _ = mockLogger.Setup(logger => logger.IsEnabled(It.IsAny())).Returns(true); // Configure the mock scope to resolve services _ = mockScope.Setup(x => x.ServiceProvider).Returns(mockProvider.Object); // Mock resolution of ILogger from the service provider - _ = mockProvider.Setup(x => x.GetService(typeof(ILogger))) + _ = mockProvider.Setup(x => x.GetService(typeof(ILogger))) .Returns(mockLogger.Object); // Define a test-specific configuration for the Keycloak realm diff --git a/NETCore.Keycloak.Client.Tests/Modules/KcAuthorizationTests/KcRealmAdminTokenHandlerTests.cs b/NETCore.Keycloak.Client.Tests/Modules/KcAuthorizationTests/KcRealmAdminTokenHandlerTests.cs index 411d22f..4ddbb30 100644 --- a/NETCore.Keycloak.Client.Tests/Modules/KcAuthorizationTests/KcRealmAdminTokenHandlerTests.cs +++ b/NETCore.Keycloak.Client.Tests/Modules/KcAuthorizationTests/KcRealmAdminTokenHandlerTests.cs @@ -58,12 +58,12 @@ public void SetUp() .Returns(mockScope.Object); // Mock the logger. - var mockLogger = new Mock(); + var mockLogger = new Mock>(); _ = mockLogger.Setup(logger => logger.IsEnabled(It.IsAny())).Returns(true); // Mock the service provider to return the logger when requested. _ = mockScope.Setup(x => x.ServiceProvider).Returns(_mockProvider.Object); - _ = _mockProvider.Setup(x => x.GetService(typeof(ILogger))) + _ = _mockProvider.Setup(x => x.GetService(typeof(ILogger))) .Returns(mockLogger.Object); // Define test configuration for the Keycloak realm. diff --git a/NETCore.Keycloak.Client/Authentication/Claims/KcRolesClaimsTransformer.cs b/NETCore.Keycloak.Client/Authentication/Claims/KcRolesClaimsTransformer.cs index 45b348a..8abd79f 100644 --- a/NETCore.Keycloak.Client/Authentication/Claims/KcRolesClaimsTransformer.cs +++ b/NETCore.Keycloak.Client/Authentication/Claims/KcRolesClaimsTransformer.cs @@ -31,8 +31,19 @@ namespace NETCore.Keycloak.Client.Authentication.Claims; /// public class KcRolesClaimsTransformer : IClaimsTransformation { + /// + /// Represents the claim type used to identify user roles within the application. + /// private readonly string _roleClaimType; + + /// + /// Defines the source of the role claims, used to identify how roles are sourced. + /// private readonly KcRolesClaimSource _roleSource; + + /// + /// Represents the audience for the token, used to validate the intended recipient of the token. + /// private readonly string _audience; /// diff --git a/NETCore.Keycloak.Client/Authentication/KcAuthenticationConfiguration.cs b/NETCore.Keycloak.Client/Authentication/KcAuthenticationConfiguration.cs index 92df07a..dcd56b3 100644 --- a/NETCore.Keycloak.Client/Authentication/KcAuthenticationConfiguration.cs +++ b/NETCore.Keycloak.Client/Authentication/KcAuthenticationConfiguration.cs @@ -80,7 +80,7 @@ public class KcAuthenticationConfiguration /// /// List of valid audiences /// - public IEnumerable ValidAudiences { get; set; } = new List(); + public IEnumerable ValidAudiences { get; set; } = []; /// /// Get valid issuer diff --git a/NETCore.Keycloak.Client/Authorization/Handlers/KcBearerAuthorizationHandler.cs b/NETCore.Keycloak.Client/Authorization/Handlers/KcBearerAuthorizationHandler.cs index 1a7c8a7..14e7091 100644 --- a/NETCore.Keycloak.Client/Authorization/Handlers/KcBearerAuthorizationHandler.cs +++ b/NETCore.Keycloak.Client/Authorization/Handlers/KcBearerAuthorizationHandler.cs @@ -42,7 +42,7 @@ public KcBearerAuthorizationHandler(IServiceProvider serviceProvider) using var scope = serviceProvider.CreateScope(); // Resolve the logger instance. - _logger = scope.ServiceProvider.GetService(); + _logger = scope.ServiceProvider.GetService>(); // Resolve the HTTP context accessor for accessing request data. _httpContextAccessor = scope.ServiceProvider.GetRequiredService(); @@ -61,10 +61,10 @@ protected override async Task HandleRequirementAsync(AuthorizationHandlerContext KcAuthorizationRequirement requirement) { // Ensure that authorization context is not null - ArgumentNullException.ThrowIfNull(context, "Authorization context is required."); + ArgumentNullException.ThrowIfNull(context); // Ensure that authorization requirement is not null. - ArgumentNullException.ThrowIfNull(requirement, "Authorization requirement is required."); + ArgumentNullException.ThrowIfNull(requirement); // Check if the user is authenticated if ( context.User.Identity?.IsAuthenticated ?? false ) diff --git a/NETCore.Keycloak.Client/Authorization/Handlers/KcRealmAdminTokenHandler.cs b/NETCore.Keycloak.Client/Authorization/Handlers/KcRealmAdminTokenHandler.cs index c40cf89..fcb2a9a 100644 --- a/NETCore.Keycloak.Client/Authorization/Handlers/KcRealmAdminTokenHandler.cs +++ b/NETCore.Keycloak.Client/Authorization/Handlers/KcRealmAdminTokenHandler.cs @@ -62,7 +62,8 @@ public KcRealmAdminTokenHandler(KcRealmAdminConfigurationStore realmAdminConfigu // Create a scoped service provider to resolve the logger service. using var scope = provider.CreateScope(); - _logger = scope.ServiceProvider.GetRequiredService(); // Get the logger from the scoped provider. + _logger = scope.ServiceProvider + .GetRequiredService>(); // Initialize the token cache to store access and refresh tokens for different realms. _tokensCache = new ConcurrentDictionary(); diff --git a/NETCore.Keycloak.Client/Authorization/KcAuthorizationExtension.cs b/NETCore.Keycloak.Client/Authorization/KcAuthorizationExtension.cs index 484c542..6e5bd2b 100644 --- a/NETCore.Keycloak.Client/Authorization/KcAuthorizationExtension.cs +++ b/NETCore.Keycloak.Client/Authorization/KcAuthorizationExtension.cs @@ -18,8 +18,9 @@ public static class KcAuthorizationExtension /// /// public static IServiceCollection AddKeycloakAuthorization(this IServiceCollection services) => - services - .AddSingleton().AddHttpContextAccessor(); + services.AddSingleton() + .AddHttpContextAccessor() + .AddLogging(); /// /// Add keycloak policy provider @@ -35,9 +36,8 @@ public static IServiceCollection AddKeycloakProtectedResourcesPolicies( .AddSingleton() .AddSingleton() .AddSingleton( - provider => - new KcProtectedResourcePolicyProvider(provider, - provider.GetRequiredService>())); + provider => new KcProtectedResourcePolicyProvider(provider, + provider.GetRequiredService>())); return services; } } diff --git a/NETCore.Keycloak.Client/Authorization/Requirements/KcAuthorizationRequirement.cs b/NETCore.Keycloak.Client/Authorization/Requirements/KcAuthorizationRequirement.cs index 8c3af34..2bc067c 100644 --- a/NETCore.Keycloak.Client/Authorization/Requirements/KcAuthorizationRequirement.cs +++ b/NETCore.Keycloak.Client/Authorization/Requirements/KcAuthorizationRequirement.cs @@ -51,7 +51,7 @@ public class KcAuthorizationRequirement : IAuthorizationRequirement public KcAuthorizationRequirement(KcProtectedResourceStore protectedResourceStore, string resource, string scope) { // Ensure protected resources is not null - ArgumentNullException.ThrowIfNull(protectedResourceStore, $"{nameof(protectedResourceStore)} cannot be null."); + ArgumentNullException.ThrowIfNull(protectedResourceStore); // Ensure resource is not null or empty if ( string.IsNullOrWhiteSpace(resource) ) diff --git a/NETCore.Keycloak.Client/Exceptions/KcException.cs b/NETCore.Keycloak.Client/Exceptions/KcException.cs index b5d73ec..84d34cf 100644 --- a/NETCore.Keycloak.Client/Exceptions/KcException.cs +++ b/NETCore.Keycloak.Client/Exceptions/KcException.cs @@ -3,7 +3,6 @@ namespace NETCore.Keycloak.Client.Exceptions; /// /// Represents an exception specific to Keycloak operations. /// -[Serializable] public class KcException : Exception { /// diff --git a/NETCore.Keycloak.Client/HttpClients/KcHttpClientBase.cs b/NETCore.Keycloak.Client/HttpClients/KcHttpClientBase.cs index e90533b..2335ec5 100644 --- a/NETCore.Keycloak.Client/HttpClients/KcHttpClientBase.cs +++ b/NETCore.Keycloak.Client/HttpClients/KcHttpClientBase.cs @@ -329,9 +329,6 @@ private static StringContent GetBody(object o) => { NullValueHandling = NullValueHandling.Ignore, ReferenceLoopHandling = ReferenceLoopHandling.Ignore, - Converters = new List - { - new StringEnumConverter() - } + Converters = [new StringEnumConverter()] })); } diff --git a/NETCore.Keycloak.Client/Models/KcOperationResponse.cs b/NETCore.Keycloak.Client/Models/KcOperationResponse.cs index 74384d5..ddf2822 100644 --- a/NETCore.Keycloak.Client/Models/KcOperationResponse.cs +++ b/NETCore.Keycloak.Client/Models/KcOperationResponse.cs @@ -19,6 +19,5 @@ public class KcOperationResponse : KcBaseResponse /// or null if no metrics are available. /// [JsonProperty("monitoringMetrics")] - public ICollection MonitoringMetrics { get; } = - new List(); + public ICollection MonitoringMetrics { get; } = []; } diff --git a/NETCore.Keycloak.Client/NETCore.Keycloak.Client.csproj b/NETCore.Keycloak.Client/NETCore.Keycloak.Client.csproj index c3bf7cb..2cbe2e8 100644 --- a/NETCore.Keycloak.Client/NETCore.Keycloak.Client.csproj +++ b/NETCore.Keycloak.Client/NETCore.Keycloak.Client.csproj @@ -5,7 +5,7 @@ A comprehensive .NET Core client library for Keycloak that provides seamless integration with Keycloak's authentication and authorization services. This library offers a robust implementation of Keycloak's REST API, including support for OpenID Connect, OAuth 2.0, and User-Managed Access (UMA 2.0). - 1.0.1 + 1.0.2 Keycloak.NETCore.Client keycloak;oauth2;authentication;authorization;openid-connect;oidc;oidc-provider;fapi;fapi-client;user-managed-access;financial-security black_cockpit.png diff --git a/NETCore.Keycloak.Client/Utils/KcLoggerMessages.cs b/NETCore.Keycloak.Client/Utils/KcLoggerMessages.cs index d19ab3b..399295b 100644 --- a/NETCore.Keycloak.Client/Utils/KcLoggerMessages.cs +++ b/NETCore.Keycloak.Client/Utils/KcLoggerMessages.cs @@ -10,24 +10,48 @@ public static class KcLoggerMessages /// /// Defines a debug-level log message. /// - public static readonly Action Debug = LoggerMessage.Define( - LogLevel.Debug, new EventId(1000, "Debug"), "{Message}"); + public static readonly Action Debug = (logger, message, exception) => + { + if ( logger != null ) + { + LoggerMessage.Define(LogLevel.Debug, new EventId(1000, "Debug"), "{Message}")(logger, message, + exception); + } + }; /// /// Defines an error-level log message. /// - public static readonly Action Error = LoggerMessage.Define( - LogLevel.Error, new EventId(1000, "Error"), "{Message}"); + public static readonly Action Error = (logger, message, exception) => + { + if ( logger != null ) + { + LoggerMessage.Define(LogLevel.Error, new EventId(1000, "Error"), "{Message}")(logger, message, + exception); + } + }; /// /// Defines a critical-level log message, indicating a severe failure in the application. /// - public static readonly Action Critical = LoggerMessage.Define( - LogLevel.Critical, new EventId(1000, "Critical"), "{Message}"); + public static readonly Action Critical = (logger, message, exception) => + { + if ( logger != null ) + { + LoggerMessage.Define(LogLevel.Critical, new EventId(1000, "Critical"), "{Message}")(logger, message, + exception); + } + }; /// /// Defines an informational log message. /// - public static readonly Action Information = LoggerMessage.Define( - LogLevel.Information, new EventId(1000, "Information"), "{Message}"); + public static readonly Action Information = (logger, message, exception) => + { + if ( logger != null ) + { + LoggerMessage.Define(LogLevel.Information, new EventId(1000, "Information"), "{Message}")(logger, + message, exception); + } + }; }