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:
67
lib/Service/Auth/LdapConnectionGateway.php
Normal file
67
lib/Service/Auth/LdapConnectionGateway.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
namespace MintyPHP\Service\Auth;
|
||||
|
||||
/**
|
||||
* Thin wrapper around PHP ldap_* functions for testability.
|
||||
*
|
||||
* Every public method maps 1:1 to a native ldap_* call.
|
||||
* In tests, this gateway is replaced with a mock.
|
||||
*/
|
||||
class LdapConnectionGateway
|
||||
{
|
||||
/** @return \LDAP\Connection|false */
|
||||
public function connect(string $uri): \LDAP\Connection|false
|
||||
{
|
||||
return ldap_connect($uri);
|
||||
}
|
||||
|
||||
public function setOption(\LDAP\Connection $conn, int $option, mixed $value): bool
|
||||
{
|
||||
return ldap_set_option($conn, $option, $value);
|
||||
}
|
||||
|
||||
public function startTls(\LDAP\Connection $conn): bool
|
||||
{
|
||||
return ldap_start_tls($conn);
|
||||
}
|
||||
|
||||
public function bind(\LDAP\Connection $conn, ?string $dn = null, ?string $password = null): bool
|
||||
{
|
||||
return @ldap_bind($conn, $dn, $password);
|
||||
}
|
||||
|
||||
/** @return \LDAP\Result|false */
|
||||
public function search(\LDAP\Connection $conn, string $baseDn, string $filter, array $attributes = [], int $scope = 0): \LDAP\Result|false
|
||||
{
|
||||
if ($scope === 1) {
|
||||
return @ldap_list($conn, $baseDn, $filter, $attributes);
|
||||
}
|
||||
return @ldap_search($conn, $baseDn, $filter, $attributes);
|
||||
}
|
||||
|
||||
public function getEntries(\LDAP\Connection $conn, \LDAP\Result $result): array|false
|
||||
{
|
||||
return ldap_get_entries($conn, $result);
|
||||
}
|
||||
|
||||
public function escape(string $value, string $ignore = '', int $flags = 0): string
|
||||
{
|
||||
return ldap_escape($value, $ignore, $flags);
|
||||
}
|
||||
|
||||
public function errno(\LDAP\Connection $conn): int
|
||||
{
|
||||
return ldap_errno($conn);
|
||||
}
|
||||
|
||||
public function error(\LDAP\Connection $conn): string
|
||||
{
|
||||
return ldap_error($conn);
|
||||
}
|
||||
|
||||
public function unbind(\LDAP\Connection $conn): bool
|
||||
{
|
||||
return @ldap_unbind($conn);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user