namespace ScadaLink.Security; public class SecurityOptions { public string LdapServer { get; set; } = string.Empty; public int LdapPort { get; set; } = 389; /// /// Transport security mode for the LDAP connection. Defaults to LDAPS. /// Use to connect on the plaintext port /// and upgrade the session before binding. /// public LdapTransport LdapTransport { get; set; } = LdapTransport.Ldaps; /// /// True when the configured transport provides encryption (LDAPS or StartTLS). /// Retained for backward compatibility: assigning a value maps onto /// (true => LDAPS, false => None). /// public bool LdapUseTls { get => LdapTransport != LdapTransport.None; set => LdapTransport = value ? LdapTransport.Ldaps : LdapTransport.None; } /// /// Allow insecure (non-TLS) LDAP connections. ONLY for dev/test with GLAuth. /// Must be false in production. /// public bool AllowInsecureLdap { get; set; } = false; /// /// Base DN for LDAP searches (e.g., "dc=example,dc=com"). /// public string LdapSearchBase { get; set; } = string.Empty; /// /// Service account DN for LDAP user searches (e.g., "cn=admin,dc=example,dc=com"). /// Required for search-then-bind authentication. If empty, direct bind with /// {LdapUserIdAttribute}={username},{LdapSearchBase} is attempted instead. /// public string LdapServiceAccountDn { get; set; } = string.Empty; /// /// LDAP attribute that identifies a user. Used both for the search-then-bind /// filter (({LdapUserIdAttribute}={username})) and for constructing the /// fallback bind DN when no service account is configured, so the two /// authentication modes are interchangeable. Common values: uid (OpenLDAP), /// sAMAccountName (Active Directory). /// public string LdapUserIdAttribute { get; set; } = "uid"; /// /// Service account password for LDAP user searches. /// public string LdapServiceAccountPassword { get; set; } = string.Empty; /// /// LDAP attribute that contains the user's display name. /// public string LdapDisplayNameAttribute { get; set; } = "cn"; /// /// LDAP attribute that contains group membership. /// public string LdapGroupAttribute { get; set; } = "memberOf"; /// /// Network timeout, in milliseconds, applied to the LDAP socket connect and to /// LDAP operations (bind/search). The synchronous Novell LDAP calls are wrapped /// in Task.Run, where the CancellationToken only guards work-item /// scheduling — it cannot interrupt an in-progress blocking call. This timeout is /// the real safeguard: it bounds how long a hung LDAP server can pin a thread-pool /// thread (Security-009). Default 10 seconds. /// public int LdapConnectionTimeoutMs { get; set; } = 10_000; /// /// Symmetric HMAC-SHA256 signing key for cookie-embedded JWTs. Must be at least /// 32 bytes (256 bits) — validated at construction. /// public string JwtSigningKey { get; set; } = string.Empty; /// /// Minimum signing-key length in bytes required for HMAC-SHA256 (256 bits). /// public const int MinJwtSigningKeyBytes = 32; public int JwtExpiryMinutes { get; set; } = 15; public int IdleTimeoutMinutes { get; set; } = 30; /// /// Minutes before token expiry to trigger refresh. /// public int JwtRefreshThresholdMinutes { get; set; } = 5; /// /// When true (default) the authentication cookie is always marked /// Secure (sent only over HTTPS) — the correct production setting, /// since the cookie carries the embedded JWT bearer credential. Set false /// for an HTTP-only deployment such as the local Docker dev cluster: the /// cookie then uses SameAsRequest, so it is still Secure on /// any HTTPS request but is usable over plain HTTP. /// public bool RequireHttpsCookie { get; set; } = true; }