InternalLdapKit 2026.5.3.1
dotnet add package InternalLdapKit --version 2026.5.3.1
NuGet\Install-Package InternalLdapKit -Version 2026.5.3.1
<PackageReference Include="InternalLdapKit" Version="2026.5.3.1" />
<PackageVersion Include="InternalLdapKit" Version="2026.5.3.1" />
<PackageReference Include="InternalLdapKit" />
paket add InternalLdapKit --version 2026.5.3.1
#r "nuget: InternalLdapKit, 2026.5.3.1"
#:package InternalLdapKit@2026.5.3.1
#addin nuget:?package=InternalLdapKit&version=2026.5.3.1
#tool nuget:?package=InternalLdapKit&version=2026.5.3.1
InternalLdapKit
InternalLdapKit es una biblioteca .NET reutilizable para integración segura con servidores LDAP/Active Directory en aplicaciones internas. Proporciona un wrapper simplificado y seguro sobre System.DirectoryServices.Protocols con soporte completo para inyección de dependencias.
🎯 Características Principales
- ✅ Multi-targeting: Soporta .NET 8, .NET 10, .NET Framework 4.7.2 y 4.8
- 🔒 Seguridad integrada: LDAPS (SSL/TLS) configurado por defecto
- 🧪 Escape automático: Prevención de inyección LDAP con
LdapFilterEscaper - 🏗️ Inyección de dependencias: Integración nativa con
Microsoft.Extensions.DependencyInjection - 📊 Logging estructurado: Compatible con
Microsoft.Extensions.Logging - ⚡ Async/await: API completamente asíncrona con soporte para
CancellationToken - 🔄 Alta disponibilidad: Failover automático entre múltiples servidores LDAP
📦 Instalación
Azure DevOps Artifacts
dotnet add package InternalLdapKit --source "internal-shared"
Configurar el feed en NuGet.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="internal-shared" value="https://pkgs.dev.azure.com/MICM-TIC/_packaging/internal-shared/nuget/v3/index.json" />
</packageSources>
</configuration>
🚀 Inicio Rápido
ASP.NET Core / .NET Moderno
1. Configurar appsettings.json
{
"Ldap": {
"Servers": [ "dc01.empresa.local", "dc02.empresa.local" ],
"Port": 636,
"UseSsl": true,
"BindDn": "CN=svc_ldap_app,OU=Service Accounts,DC=empresa,DC=local",
"BindPassword": "secret-from-vault",
"BaseDn": "DC=empresa,DC=local",
"UserSearchFilterTemplate": "(&(objectClass=user)(sAMAccountName={0}))",
"GroupAttribute": "memberOf",
"ConnectTimeoutSeconds": 5,
"OperationTimeoutSeconds": 10,
"IgnoreCertificateErrors": false
}
}
2. Registrar en Program.cs o Startup.cs
using InternalLdapKit.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Registrar cliente LDAP
builder.Services.AddInternalLdap(builder.Configuration.GetSection("Ldap"));
var app = builder.Build();
3. Usar en tus servicios
using InternalLdapKit.Abstractions;
public class AuthenticationService
{
private readonly ILdapClient _ldapClient;
private readonly ILogger<AuthenticationService> _logger;
public AuthenticationService(ILdapClient ldapClient, ILogger<AuthenticationService> logger)
{
_ldapClient = ldapClient;
_logger = logger;
}
public async Task<bool> AuthenticateUserAsync(string username, string password, CancellationToken ct)
{
try
{
// Validar credenciales contra LDAP
var isValid = await _ldapClient.ValidateCredentialsAsync(username, password, ct);
if (!isValid)
{
_logger.LogWarning("Autenticación fallida para usuario {Username}", username);
return false;
}
// Obtener información del usuario
var user = await _ldapClient.FindUserAsync(username, ct);
if (user == null)
{
_logger.LogWarning("Usuario {Username} no encontrado en LDAP", username);
return false;
}
_logger.LogInformation("Usuario {Username} autenticado exitosamente. Email: {Email}",
username, user.Email);
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error durante autenticación LDAP para usuario {Username}", username);
return false;
}
}
public async Task<string[]> GetUserGroupsAsync(string username, CancellationToken ct)
{
var groups = await _ldapClient.GetUserGroupsAsync(username, ct);
return groups;
}
}
📋 API Reference
ILdapClient Interface
public interface ILdapClient : IDisposable
{
// Valida las credenciales de un usuario contra LDAP
Task<bool> ValidateCredentialsAsync(string username, string password, CancellationToken cancellationToken = default);
// Busca un usuario por su nombre de usuario
Task<LdapUser?> FindUserAsync(string username, CancellationToken cancellationToken = default);
// Obtiene los grupos de un usuario
Task<string[]> GetUserGroupsAsync(string username, CancellationToken cancellationToken = default);
}
LdapUser Model
public sealed class LdapUser
{
public string DistinguishedName { get; init; }
public string Username { get; init; }
public string? UserPrincipalName { get; init; }
public string? DisplayName { get; init; }
public string? Email { get; init; }
public string[] Groups { get; init; }
}
LdapOptions Configuration
| Propiedad | Tipo | Requerido | Predeterminado | Descripción |
|---|---|---|---|---|
Servers |
string[] |
✅ Sí | - | Lista de servidores LDAP (failover automático) |
Port |
int |
No | 636 |
Puerto LDAP (389 sin SSL, 636 con SSL) |
UseSsl |
bool |
No | true |
Usar LDAPS (SSL/TLS) |
BindDn |
string |
✅ Sí | - | DN de la cuenta de servicio para bind |
BindPassword |
string |
✅ Sí | - | Contraseña de la cuenta de servicio |
BaseDn |
string |
✅ Sí | - | Base DN para búsquedas |
UserSearchFilterTemplate |
string |
No | (&(objectClass=user)(sAMAccountName={0})) |
Template del filtro de búsqueda |
GroupAttribute |
string |
No | memberOf |
Atributo LDAP para grupos |
ConnectTimeoutSeconds |
int |
No | 5 |
Timeout de conexión |
OperationTimeoutSeconds |
int |
No | 10 |
Timeout de operaciones |
IgnoreCertificateErrors |
bool |
No | false |
Ignorar errores de certificado SSL (solo desarrollo) |
🔐 Seguridad y Mejores Prácticas
✅ Recomendaciones
- Usar LDAPS siempre: Establece
UseSsl: trueyPort: 636 - Cuenta de servicio dedicada: Crea una cuenta con permisos mínimos (solo lectura en AD)
- Gestión de secretos: Nunca almacenes
BindPassworden código o archivos de configuración- Usa Azure Key Vault, AWS Secrets Manager, o variables de entorno seguras
- Escape de filtros: El kit incluye
LdapFilterEscaperpara prevenir inyección LDAP - Limitar Base DN: Configura el
BaseDnmás específico posible - Validación de certificados: En producción,
IgnoreCertificateErrorsdebe serfalse - Logging apropiado: No registres contraseñas o información sensible
⚠️ Limitaciones
- ❌ No implementa autenticación multi-factor (MFA)
- ❌ No sustituye soluciones modernas de SSO (OAuth2/OIDC)
- ❌ No está diseñado para aplicaciones públicas orientadas a internet
- ℹ️ Recomendado solo para aplicaciones internas de intranet
💡 Ejemplos Adicionales
Verificar grupos de usuario
public async Task<bool> IsUserInGroupAsync(string username, string requiredGroup, CancellationToken ct)
{
var groups = await _ldapClient.GetUserGroupsAsync(username, ct);
return groups.Any(g => g.Contains(requiredGroup, StringComparison.OrdinalIgnoreCase));
}
Implementación con caché
using Microsoft.Extensions.Caching.Memory;
public class CachedLdapService
{
private readonly ILdapClient _ldapClient;
private readonly IMemoryCache _cache;
public async Task<LdapUser?> GetUserAsync(string username, CancellationToken ct)
{
var cacheKey = $"ldap_user_{username}";
if (_cache.TryGetValue<LdapUser>(cacheKey, out var cachedUser))
return cachedUser;
var user = await _ldapClient.FindUserAsync(username, ct);
if (user != null)
{
_cache.Set(cacheKey, user, TimeSpan.FromMinutes(5));
}
return user;
}
}
.NET Framework (sin DI)
Instanciación manual:
var options = new LdapOptions
{
Servers = new[] { "dc01.empresa.local", "dc02.empresa.local" },
Port = 636,
UseSsl = true,
BindDn = "CN=svc_ldap_app,OU=Service Accounts,DC=empresa,DC=local",
BindPassword = secretProvider.Get("ldap-password"),
BaseDn = "DC=empresa,DC=local",
UserSearchFilterTemplate = "(&(objectClass=user)(sAMAccountName={0}))"
};
using (var client = new LdapClient(options, new NullLogger()))
{
var ok = client.ValidateCredentialsAsync("jdoe", "P@ssw0rd!", CancellationToken.None)
.GetAwaiter()
.GetResult();
}
Importación a una solución
- Agrega el proyecto
src/InternalLdapKit/InternalLdapKit.csproja tu solución. - Referencia el proyecto desde la app consumidora.
- Configura
LdapOptions. - Mueve
BindPassworda un secreto gestionado. - Mapea grupos AD a roles internos en tu capa de autorización.
Construcción local del DLL
En una máquina con SDK .NET instalado:
pwsh .\build\build-local.ps1
Salida esperada:
artifacts/InternalLdapKit/bin/Release/.../InternalLdapKit.dllartifacts/InternalLdapKit.nupkg
Recomendaciones de uso
- usa LDAPS
- usa cuenta de servicio dedicada
- no concatenes filtros LDAP
- limita Base DN y atributos
- registra solo telemetría útil
- cachea grupos con TTL corto si la carga lo requiere
Limitaciones del kit
- no implementa MFA
- no sustituye SSO moderno
- no debe exponerse como autenticación principal de apps públicas
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Framework | net472 is compatible. net48 is compatible. net481 was computed. |
-
.NETFramework 4.7.2
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.5)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.5)
- Microsoft.Extensions.Options.DataAnnotations (>= 10.0.5)
- System.DirectoryServices.Protocols (>= 10.0.5)
-
.NETFramework 4.8
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.5)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.5)
- Microsoft.Extensions.Options.DataAnnotations (>= 10.0.5)
- System.DirectoryServices.Protocols (>= 10.0.5)
-
net10.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.5)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.5)
- Microsoft.Extensions.Options.DataAnnotations (>= 10.0.5)
- System.DirectoryServices.Protocols (>= 10.0.5)
-
net8.0
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.5)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.5)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.5)
- Microsoft.Extensions.Options.DataAnnotations (>= 10.0.5)
- System.DirectoryServices.Protocols (>= 10.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2026.5.3.1 | 136 | 5/3/2026 |
Características principales:
• Validación de credenciales contra LDAP/Active Directory
• Búsqueda de usuarios con FindUserAsync()
• Obtención de grupos con GetUserGroupsAsync()
• Failover automático entre múltiples servidores
• Prevención de inyección LDAP con LdapFilterEscaper
• API asíncrona completa con CancellationToken
• Integración con Microsoft.Extensions.DependencyInjection
• Soporte para LDAPS (SSL/TLS) configurado por defecto
• Multi-targeting: .NET 8, .NET 10, .NET Framework 4.7.2, .NET Framework 4.8
Instalación: dotnet add package InternalLdapKit --source "internal-shared"
Uso rápido:
builder.Services.AddInternalLdap(builder.Configuration.GetSection("Ldap"));
Ver README.md para documentación completa y ejemplos de código.