1
0

feat: add LDAP authentication as per-tenant login method

Add LDAP as a third authentication option alongside local password and
Microsoft Entra ID SSO. Per-tenant configuration supports Active Directory,
OpenLDAP, and FreeIPA with configurable attribute mapping, search-then-bind
and direct-bind methods, encrypted bind credentials (AES-256-GCM),
profile sync on login, and user auto-provisioning via external identity
linking.

Includes admin UI for connection settings with test-connection button,
login page LDAP form, 25 new PHPUnit tests, and de/en translations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-25 07:26:04 +01:00
parent a0d816caaa
commit d1eeac6692
22 changed files with 2325 additions and 18 deletions

View File

@@ -0,0 +1,30 @@
-- Idempotent: tenant_auth_ldap table for LDAP authentication per tenant
CREATE TABLE IF NOT EXISTS `tenant_auth_ldap` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`tenant_id` INT UNSIGNED NOT NULL,
`enabled` TINYINT(1) NOT NULL DEFAULT 0,
`enforce_ldap_login` TINYINT(1) NOT NULL DEFAULT 0,
`host` VARCHAR(255) NOT NULL DEFAULT '',
`port` INT UNSIGNED NOT NULL DEFAULT 389,
`encryption_mode` ENUM('none','starttls','ldaps') NOT NULL DEFAULT 'starttls',
`verify_tls_certificate` TINYINT(1) NOT NULL DEFAULT 1,
`base_dn` VARCHAR(500) NOT NULL DEFAULT '',
`bind_dn_enc` TEXT NULL,
`bind_password_enc` TEXT NULL,
`user_search_filter` VARCHAR(500) NOT NULL DEFAULT '(&(objectClass=user)(sAMAccountName=%s))',
`user_search_scope` ENUM('sub','one') NOT NULL DEFAULT 'sub',
`bind_method` ENUM('search_then_bind','direct_bind') NOT NULL DEFAULT 'search_then_bind',
`bind_username_format` VARCHAR(255) NULL,
`unique_id_attribute` VARCHAR(64) NOT NULL DEFAULT 'objectGUID',
`attribute_map` JSON NOT NULL DEFAULT '{"first_name":"givenName","last_name":"sn","email":"mail","phone":"telephoneNumber","mobile":"mobile"}',
`sync_profile_on_login` TINYINT(1) NOT NULL DEFAULT 0,
`sync_profile_fields` TEXT NULL,
`allowed_domains` TEXT NULL,
`auto_remember_mode` TINYINT(1) NULL DEFAULT NULL,
`network_timeout` INT UNSIGNED NOT NULL DEFAULT 5,
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`modified` DATETIME NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_tenant_auth_ldap_tenant` (`tenant_id`),
CONSTRAINT `fk_tenant_auth_ldap_tenant` FOREIGN KEY (`tenant_id`) REFERENCES `tenants` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;