Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public void ShouldRegisterAuthorizationHandler()
});

// Create a mock for ILogger to simulate logging functionality.
var mockLogger = new Mock<ILogger>();
var mockLogger = new Mock<ILogger<IKcRealmAdminTokenHandler>>();
_ = mockLogger.Setup(logger => logger.IsEnabled(It.IsAny<LogLevel>())).Returns(true);

// Add Keycloak services, the token handler, and the logger to the service collection.
Expand Down Expand Up @@ -112,7 +112,7 @@ public void ShouldRegisterKeycloakProtectedResourcesPoliciesServices()
var mockAuthorizationOptions = new Mock<IOptions<AuthorizationOptions>>();

// Create a mock for ILogger to simulate logging functionality.
var mockLogger = new Mock<ILogger>();
var mockLogger = new Mock<ILogger<IKcRealmAdminTokenHandler>>();
_ = mockLogger.Setup(logger => logger.IsEnabled(It.IsAny<LogLevel>())).Returns(true);

// Add mocked services to the service collection.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,14 @@ public void SetUp()
.Returns(mockScope.Object);

// Set up a mock logger to simulate logging functionality
var mockLogger = new Mock<ILogger>();
var mockLogger = new Mock<ILogger<IKcRealmAdminTokenHandler>>();
_ = mockLogger.Setup(logger => logger.IsEnabled(It.IsAny<LogLevel>())).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<IKcRealmAdminTokenHandler>)))
.Returns(mockLogger.Object);

// Mock resolution of IHttpContextAccessor from the service provider
Expand Down Expand Up @@ -772,14 +772,14 @@ private KcRealmAdminTokenHandler SetUpMockRealmAdminTokenHandler()
.Returns(mockScope.Object);

// Set up a mock logger to simulate logging functionality
var mockLogger = new Mock<ILogger>();
var mockLogger = new Mock<ILogger<IKcRealmAdminTokenHandler>>();
_ = mockLogger.Setup(logger => logger.IsEnabled(It.IsAny<LogLevel>())).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<IKcRealmAdminTokenHandler>)))
.Returns(mockLogger.Object);

// Define a test-specific configuration for the Keycloak realm
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ public void SetUp()
.Returns(mockScope.Object);

// Mock the logger.
var mockLogger = new Mock<ILogger>();
var mockLogger = new Mock<ILogger<IKcRealmAdminTokenHandler>>();
_ = mockLogger.Setup(logger => logger.IsEnabled(It.IsAny<LogLevel>())).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<IKcRealmAdminTokenHandler>)))
.Returns(mockLogger.Object);

// Define test configuration for the Keycloak realm.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,19 @@ namespace NETCore.Keycloak.Client.Authentication.Claims;
/// </remarks>
public class KcRolesClaimsTransformer : IClaimsTransformation
{
/// <summary>
/// Represents the claim type used to identify user roles within the application.
/// </summary>
private readonly string _roleClaimType;

/// <summary>
/// Defines the source of the role claims, used to identify how roles are sourced.
/// </summary>
private readonly KcRolesClaimSource _roleSource;

/// <summary>
/// Represents the audience for the token, used to validate the intended recipient of the token.
/// </summary>
private readonly string _audience;

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public class KcAuthenticationConfiguration
/// <summary>
/// List of valid audiences
/// </summary>
public IEnumerable<string> ValidAudiences { get; set; } = new List<string>();
public IEnumerable<string> ValidAudiences { get; set; } = [];

/// <summary>
/// Get valid issuer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public KcBearerAuthorizationHandler(IServiceProvider serviceProvider)
using var scope = serviceProvider.CreateScope();

// Resolve the logger instance.
_logger = scope.ServiceProvider.GetService<ILogger>();
_logger = scope.ServiceProvider.GetService<ILogger<KcBearerAuthorizationHandler>>();

// Resolve the HTTP context accessor for accessing request data.
_httpContextAccessor = scope.ServiceProvider.GetRequiredService<IHttpContextAccessor>();
Expand All @@ -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 )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<ILogger>(); // Get the logger from the scoped provider.
_logger = scope.ServiceProvider
.GetRequiredService<ILogger<IKcRealmAdminTokenHandler>>();

// Initialize the token cache to store access and refresh tokens for different realms.
_tokensCache = new ConcurrentDictionary<string, KcCachedToken>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ public static class KcAuthorizationExtension
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddKeycloakAuthorization(this IServiceCollection services) =>
services
.AddSingleton<IAuthorizationHandler, KcBearerAuthorizationHandler>().AddHttpContextAccessor();
services.AddSingleton<IAuthorizationHandler, KcBearerAuthorizationHandler>()
.AddHttpContextAccessor()
.AddLogging();

/// <summary>
/// Add keycloak policy provider
Expand All @@ -35,9 +36,8 @@ public static IServiceCollection AddKeycloakProtectedResourcesPolicies<T, TV>(
.AddSingleton<KcRealmAdminConfigurationStore, TV>()
.AddSingleton<IKcRealmAdminTokenHandler, KcRealmAdminTokenHandler>()
.AddSingleton<IAuthorizationPolicyProvider, KcProtectedResourcePolicyProvider>(
provider =>
new KcProtectedResourcePolicyProvider(provider,
provider.GetRequiredService<IOptions<AuthorizationOptions>>()));
provider => new KcProtectedResourcePolicyProvider(provider,
provider.GetRequiredService<IOptions<AuthorizationOptions>>()));
return services;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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) )
Expand Down
1 change: 0 additions & 1 deletion NETCore.Keycloak.Client/Exceptions/KcException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ namespace NETCore.Keycloak.Client.Exceptions;
/// <summary>
/// Represents an exception specific to Keycloak operations.
/// </summary>
[Serializable]
public class KcException : Exception
{
/// <summary>
Expand Down
5 changes: 1 addition & 4 deletions NETCore.Keycloak.Client/HttpClients/KcHttpClientBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,6 @@ private static StringContent GetBody(object o) =>
{
NullValueHandling = NullValueHandling.Ignore,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
Converters = new List<JsonConverter>
{
new StringEnumConverter()
}
Converters = [new StringEnumConverter()]
}));
}
3 changes: 1 addition & 2 deletions NETCore.Keycloak.Client/Models/KcOperationResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,5 @@ public class KcOperationResponse<T> : KcBaseResponse<T>
/// or <c>null</c> if no metrics are available.
/// </value>
[JsonProperty("monitoringMetrics")]
public ICollection<KcHttpApiMonitoringMetrics> MonitoringMetrics { get; } =
new List<KcHttpApiMonitoringMetrics>();
public ICollection<KcHttpApiMonitoringMetrics> MonitoringMetrics { get; } = [];
}
2 changes: 1 addition & 1 deletion NETCore.Keycloak.Client/NETCore.Keycloak.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -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).
</Description>
<PackageVersion>1.0.1</PackageVersion>
<PackageVersion>1.0.2</PackageVersion>
<PackageId>Keycloak.NETCore.Client</PackageId>
<PackageTags>keycloak;oauth2;authentication;authorization;openid-connect;oidc;oidc-provider;fapi;fapi-client;user-managed-access;financial-security</PackageTags>
<PackageIcon>black_cockpit.png</PackageIcon>
Expand Down
40 changes: 32 additions & 8 deletions NETCore.Keycloak.Client/Utils/KcLoggerMessages.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,48 @@
/// <summary>
/// Defines a debug-level log message.
/// </summary>
public static readonly Action<ILogger, string, Exception> Debug = LoggerMessage.Define<string>(
LogLevel.Debug, new EventId(1000, "Debug"), "{Message}");
public static readonly Action<ILogger, string, Exception> Debug = (logger, message, exception) =>
{
if ( logger != null )
{
LoggerMessage.Define<string>(LogLevel.Debug, new EventId(1000, "Debug"), "{Message}")(logger, message,

Check warning on line 17 in NETCore.Keycloak.Client/Utils/KcLoggerMessages.cs

View workflow job for this annotation

GitHub Actions / build_test_analyze (21)

Define a constant instead of using this literal '{Message}' 4 times. (https://rules.sonarsource.com/csharp/RSPEC-1192)
exception);
}
};

/// <summary>
/// Defines an error-level log message.
/// </summary>
public static readonly Action<ILogger, string, Exception> Error = LoggerMessage.Define<string>(
LogLevel.Error, new EventId(1000, "Error"), "{Message}");
public static readonly Action<ILogger, string, Exception> Error = (logger, message, exception) =>
{
if ( logger != null )
{
LoggerMessage.Define<string>(LogLevel.Error, new EventId(1000, "Error"), "{Message}")(logger, message,
exception);
}
};

/// <summary>
/// Defines a critical-level log message, indicating a severe failure in the application.
/// </summary>
public static readonly Action<ILogger, string, Exception> Critical = LoggerMessage.Define<string>(
LogLevel.Critical, new EventId(1000, "Critical"), "{Message}");
public static readonly Action<ILogger, string, Exception> Critical = (logger, message, exception) =>
{
if ( logger != null )
{
LoggerMessage.Define<string>(LogLevel.Critical, new EventId(1000, "Critical"), "{Message}")(logger, message,
exception);
}
};

/// <summary>
/// Defines an informational log message.
/// </summary>
public static readonly Action<ILogger, string, Exception> Information = LoggerMessage.Define<string>(
LogLevel.Information, new EventId(1000, "Information"), "{Message}");
public static readonly Action<ILogger, string, Exception> Information = (logger, message, exception) =>
{
if ( logger != null )
{
LoggerMessage.Define<string>(LogLevel.Information, new EventId(1000, "Information"), "{Message}")(logger,
message, exception);
}
};
}
Loading