using System.Net.Security; namespace ZB.MOM.WW.Auth.Abstractions.Ldap; public enum LdapTransport { Ldaps, StartTls, None } public sealed record LdapOptions { public bool Enabled { get; init; } = true; public string Server { get; init; } = "localhost"; public int Port { get; init; } = 3893; public LdapTransport Transport { get; init; } = LdapTransport.Ldaps; public bool AllowInsecure { get; init; } public string SearchBase { get; init; } = ""; public string ServiceAccountDn { get; init; } = ""; public string ServiceAccountPassword { get; init; } = ""; public string UserNameAttribute { get; init; } = "cn"; public string DisplayNameAttribute { get; init; } = "cn"; public string GroupAttribute { get; init; } = "memberOf"; public int ConnectionTimeoutMs { get; init; } = 10_000; /// /// Optional hook to harden (or, in dev, relax) TLS server-certificate validation for the /// / transports. When /// (the default) the LDAP client validates the server certificate against /// the OS trust store — it does not blind-accept. Supply a callback to pin a CA, validate /// the SAN against , or otherwise tighten validation. This is a code-only seam /// (not bound from configuration) and takes precedence over . /// public RemoteCertificateValidationCallback? ServerCertificateValidationCallback { get; init; } } public enum LdapAuthFailure { BadCredentials, UserNotFound, AmbiguousUser, GroupLookupFailed, ServiceAccountBindFailed, Disabled } public sealed record LdapAuthResult(bool Succeeded, string Username, string DisplayName, IReadOnlyList Groups, LdapAuthFailure? Failure) { public static LdapAuthResult Success(string username, string displayName, IReadOnlyList groups) => new(true, username, displayName, groups, null); public static LdapAuthResult Fail(LdapAuthFailure failure) => new(false, "", "", Array.Empty(), failure); } public interface ILdapAuthService { /// /// Authenticates against the directory by bind-then-search and /// returns the outcome, including the resolved display name and group memberships on success. /// /// The login name to authenticate. /// The credential to bind with. /// A token to request cancellation of the operation. /// The authentication result. /// /// The cancellation token is observed at entry only. Implementations backed by synchronous /// LDAP clients cannot abort an in-flight bind or search once it has been dispatched, so full /// cooperative cancellation is not guaranteed mid-call: a request that has already reached the /// directory will run to completion (subject to the configured connection timeout) even if the /// token is cancelled. /// Task AuthenticateAsync(string username, string password, CancellationToken ct); }