InternalLdapKit 2026.5.3.1

dotnet add package InternalLdapKit --version 2026.5.3.1
                    
NuGet\Install-Package InternalLdapKit -Version 2026.5.3.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="InternalLdapKit" Version="2026.5.3.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="InternalLdapKit" Version="2026.5.3.1" />
                    
Directory.Packages.props
<PackageReference Include="InternalLdapKit" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add InternalLdapKit --version 2026.5.3.1
                    
#r "nuget: InternalLdapKit, 2026.5.3.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package InternalLdapKit@2026.5.3.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=InternalLdapKit&version=2026.5.3.1
                    
Install as a Cake Addin
#tool nuget:?package=InternalLdapKit&version=2026.5.3.1
                    
Install as a Cake Tool

InternalLdapKit

.NET Azure DevOps

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

  1. Usar LDAPS siempre: Establece UseSsl: true y Port: 636
  2. Cuenta de servicio dedicada: Crea una cuenta con permisos mínimos (solo lectura en AD)
  3. Gestión de secretos: Nunca almacenes BindPassword en código o archivos de configuración
    • Usa Azure Key Vault, AWS Secrets Manager, o variables de entorno seguras
  4. Escape de filtros: El kit incluye LdapFilterEscaper para prevenir inyección LDAP
  5. Limitar Base DN: Configura el BaseDn más específico posible
  6. Validación de certificados: En producción, IgnoreCertificateErrors debe ser false
  7. 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

  1. Agrega el proyecto src/InternalLdapKit/InternalLdapKit.csproj a tu solución.
  2. Referencia el proyecto desde la app consumidora.
  3. Configura LdapOptions.
  4. Mueve BindPassword a un secreto gestionado.
  5. 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.dll
  • artifacts/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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.