Installation
composer require chill-project/ldap
Add the service provider to config/app.php under providers:
Chill\Ldap\LdapServiceProvider::class,
Configuration Publish the config file:
php artisan vendor:publish --provider="Chill\Ldap\LdapServiceProvider" --tag="ldap-config"
Update config/ldap.php with your LDAP server details (host, base DN, bind credentials, etc.).
First Use Case: Sync a User Trigger a one-time sync for a specific user:
use Chill\Ldap\Facades\Ldap;
$user = User::find(1); // Replace with your user model
$ldapUser = Ldap::syncUser($user);
Verify Connection Test LDAP connectivity via Tinker:
php artisan tinker
\Chill\Ldap\Facades\Ldap::connect();
// Should return true if connection succeeds
Periodic Sync (Cron Job)
Schedule a daily sync for all users via artisan command:
php artisan ldap:sync:users --dry-run # Test without changes
php artisan ldap:sync:users # Run full sync
Customize the command in app/Console/Commands/SyncUsersCommand.php to filter users (e.g., only active ones).
Event-Based Sync Listen for user creation/update events and trigger LDAP sync:
use Chill\Ldap\Events\UserSynced;
use Illuminate\Support\Facades\Event;
Event::listen(UserSynced::class, function ($event) {
// Post-sync logic (e.g., log, notify)
});
Sync Laravel groups to LDAP groups (if supported by your LDAP schema):
Ldap::syncGroup($laravelGroup, $ldapGroupDn);
Extend app/Models/LdapGroup.php to map Laravel groups to LDAP group DNs.
Override Laravel’s default auth to use LDAP for login:
// In AuthController or similar
public function login(Request $request) {
if (config('ldap.auth_enabled')) {
return Ldap::authenticate($request->email, $request->password);
}
// Fallback to default auth
}
Customize attribute mapping in config/ldap.php:
'attribute_mappings' => [
'email' => 'mail',
'username' => 'sAMAccountName',
'name' => 'cn',
],
Override dynamically in a service:
Ldap::setAttributeMapping(['custom_field' => 'extensionAttribute3']);
Extend User Model
Add LDAP-specific methods to your User model:
public function syncWithLdap() {
return Ldap::syncUser($this);
}
Accessors for LDAP Data Fetch LDAP attributes without syncing:
public function getLdapAttribute($attribute) {
return Ldap::getUserAttribute($this->email, $attribute);
}
Restrict LDAP-dependent routes:
Route::middleware(['ldap.connected'])->group(function () {
// Routes requiring LDAP
});
Register middleware in app/Http/Kernel.php:
protected $routeMiddleware = [
'ldap.connected' => \Chill\Ldap\Http\Middleware\CheckLdapConnection::class,
];
Mock LDAP responses in tests:
$this->partialMock(\Chill\Ldap\LdapManager::class, function ($mock) {
$mock->shouldReceive('search')
->andReturn([/* mock LDAP entry */]);
});
Connection Issues
Connection refused.config/ldap.php settings (host, port, TLS/SSL). Test with:
Ldap::connect()->isConnected(); // Should return true
config/ldap.php:
'debug' => env('LDAP_DEBUG', false),
Attribute Mismatches
uid vs. sAMAccountName). Use:
Ldap::getSchema(); // Inspect available attributes
Performance with Large Directories
paginate in config/ldap.php:
'sync' => [
'batch_size' => 50, // Process 50 users at a time
],
Case Sensitivity
config/ldap.php:
'options' => [
'case_insensitive' => true,
],
Password Sync Risks
config/ldap.php:
'sync_passwords' => false,
Or implement a confirmation step before syncing passwords.Enable Verbose Logging
Add to config/ldap.php:
'log_level' => \Monolog\Logger::DEBUG,
Check logs at storage/logs/ldap.log.
LDAP Server-Side Debugging
Enable LDAP server logging (e.g., OpenLDAP’s slapd):
slapd -d -1 # Debug level 1 (adjust as needed)
Test with a Single User
Use ldap:test command to validate a specific user:
php artisan ldap:test --email=user@example.com
Check for Circular Dependencies
Ensure your User model doesn’t trigger infinite loops during sync (e.g., avoid calling syncWithLdap() in observers or accessors).
Custom Sync Logic
Override the sync behavior by extending Chill\Ldap\Syncers\UserSyncer:
namespace App\Ldap;
use Chill\Ldap\Syncers\UserSyncer as BaseSyncer;
class CustomUserSyncer extends BaseSyncer {
protected function mapAttributes($ldapEntry) {
// Custom mapping logic
return parent::mapAttributes($ldapEntry);
}
}
Bind it in AppServiceProvider:
Ldap::extend(function ($app) {
$app->bind('syncers.user', function () {
return new CustomUserSyncer();
});
});
Add Custom LDAP Filters
Extend the LdapManager to support custom search filters:
Ldap::addFilter('active_users', function ($query) {
return $query->where('objectClass', '=', 'person')
->where('userAccountControl:1.2.840.113556.1.4.803:=2'); // Active flag
});
Use in sync commands:
Ldap::search('active_users');
Support for Multiple LDAP Servers Dynamically switch LDAP configurations:
Ldap::setConfig('secondary_ldap');
Define configs in config/ldap.php:
'configs' => [
'primary' => [...],
'secondary' => [...],
],
Webhooks for Sync Events Dispatch events for pre/post-sync actions:
// In your sync command
event(new \Chill\Ldap\Events\PreUserSync($user));
$result = Ldap::syncUser($user);
event(new \Chill\Ldap\Events\PostUserSync($user, $result));
How can I help you explore Laravel packages today?