directorytree/ldaprecord-laravel
Integrate LDAP authentication and directory management into Laravel with LdapRecord. Configure connections, sync users and groups, run queries, and handle logins against Active Directory/OpenLDAP with clean, Laravel-friendly APIs and tooling.
## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require directorytree/ldaprecord-laravel
Publish the config and migrations:
php artisan vendor:publish --provider="DirectoryTree\LdapRecordLaravel\LdapRecordLaravelServiceProvider" --tag="config"
php artisan vendor:publish --provider="DirectoryTree\LdapRecordLaravel\LdapRecordLaravelServiceProvider" --tag="migrations"
php artisan migrate
Configure LDAP Connection:
Edit config/ldap.php with your LDAP server details (e.g., host, base DN, bind DN, password). Example:
'connections' => [
'ad' => [
'host' => 'ldap.example.com',
'port' => 389,
'use_ssl' => true,
'base_dn' => 'dc=example,dc=com',
'username' => 'cn=admin,dc=example,dc=com',
'password' => 'password',
'account_prefix' => 'uid=',
'account_suffix' => '',
'user_model' => \App\Models\User::class,
],
],
First Use Case: LDAP Authentication
Add an LDAP guard to config/auth.php:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'ldap',
],
],
'providers' => [
'ldap' => [
'driver' => 'ldap',
'connection' => 'ad',
'model' => \App\Models\User::class,
],
],
Test login with:
Auth::guard('web')->attempt(['username' => 'jdoe', 'password' => 'password']);
Query LDAP Users: Use Eloquent-like syntax to query LDAP:
use DirectoryTree\LdapRecordLaravel\Models\LdapUser;
$users = LdapUser::where('mail', 'like', '%@example.com')
->where('department', 'Marketing')
->get();
Auth::guard('ldap')->attempt() with username/password.DirectoryTree\LdapRecordLaravel\Auth\LdapAuthenticator to add pre-auth rules (e.g., account expiry checks).password_column in config to map LDAP attributes to Laravel’s password field or disable password storage in DB.Example custom authenticator:
use DirectoryTree\LdapRecordLaravel\Auth\LdapAuthenticator;
class CustomLdapAuthenticator extends LdapAuthenticator
{
protected function validateCredentials($username, $password, $guard)
{
// Add custom logic (e.g., check for suspended accounts)
if ($this->isAccountSuspended($username)) {
return false;
}
return parent::validateCredentials($username, $password, $guard);
}
}
LdapImporter or ldap:import Artisan command:
php artisan ldap:import --connection=ad --resolve=merge
--resolve flag (merge, skip, delete).$schedule->command('ldap:import --connection=ad --resolve=merge')->daily();
Example importer with scopes:
use DirectoryTree\LdapRecordLaravel\LdapImporter;
$importer = new LdapImporter('ad');
$importer->addScope(function ($query) {
return $query->where('department', 'Engineering');
});
$importer->import();
$activeUsers = LdapUser::where('userAccountControl', '<>', 2)
->where('mail', 'like', '%@company.com')
->orderBy('sn', 'asc')
->get();
accessors for computed fields:
public function getFullNameAttribute()
{
return "{$this->givenName} {$this->sn}";
}
$this->actingAs(new LdapUser(), 'ldap');
protected $ldapAttributes = [
'username' => 'sAMAccountName',
'email' => 'mail',
'first_name' => 'givenName',
'last_name' => 'sn',
'department' => 'department',
];
protected $ldapAttributes = [
'display_name' => function ($record) {
return "{$record->givenName} {$record->sn}";
},
];
use DirectoryTree\LdapRecordLaravel\Events\LdapUserAuthenticated;
LdapUserAuthenticated::listen(function ($event) {
// Log authentication or trigger additional actions
Log::info("LDAP user authenticated: {$event->user->username}");
});
class LdapUserObserver
{
public function saving(LdapUser $user)
{
// Pre-save logic (e.g., normalize attributes)
$user->username = strtolower($user->username);
}
}
Auth::guard('ldap')->user() to fetch LDAP user, then sync to database:
$ldapUser = Auth::guard('ldap')->user();
$dbUser = User::updateOrCreate(
['email' => $ldapUser->mail],
[
'name' => $ldapUser->displayName,
'department' => $ldapUser->department,
]
);
use DirectoryTree\LdapRecordLaravel\Models\LdapGroup;
$adminGroup = LdapGroup::where('cn', 'Admins')
->where('member', '=*', $ldapUser->distinguishedName)
->first();
if ($adminGroup) {
$user->assignRole('admin');
}
DirectoryTree\LdapRecordLaravel\Auth\LdapAuthenticator to enforce custom rules:
protected function validatePassword($password, $record)
{
if (strlen($password) < 8) {
throw new \DirectoryTree\LdapRecord\Exception\AuthenticationException(
'Password must be at least 8 characters.'
);
}
return parent::validatePassword($password, $record);
}
$connection = config("ldap.connections.{$tenant->ldap_connection}");
LdapRecord::setConnection($connection);
use DirectoryTree\LdapRecordLaravel\Testing\DirectoryEmulator;
public function testLdapLogin()
{
DirectoryEmulator::fake([
'users' => [
'jdoe' => [
'dn' => 'uid=jdoe,ou=users,dc=example,dc=com',
'givenName' => 'John',
'sn' => 'Doe',
'mail' => 'jdoe@example.com',
],
],
]);
$this->assertAuthenticated();
}
config/ldap.php:
'logging' => [
'enabled'
How can I help you explore Laravel packages today?