DirectoryTree / LdapRecord-Laravel

Multi-domain LDAP Authentication & Management for Laravel.
https://ldaprecord.com/docs/laravel/v3
MIT License
492 stars 51 forks source link

[Bug] Sync get's called on existing records #562

Closed HepplerDotNet closed 1 year ago

HepplerDotNet commented 1 year ago

Environment:

I have an AttributeHandler to fill some values when a user logs in for the first time. However, the values get also updated if an existing user logs in.

For example: I login with a user that is in developer_group, the isDeveloper gets set to true. But if I remove the group from active directory user and login again, the isDeveloper get's updated to false. Although sync_existing only contains mail attribute.

AttributeHandler.php

<?php

namespace App\Ldap;

use App\Models\LdapUser;
use App\Models\User;

class AttributeHandler
{
    public function handle(LdapUser $ldap, User $database): void
    {
        $database->name = $ldap->getFirstAttribute('givenName').' '.$ldap->getFirstAttribute('sn');
        $database->firstname = $ldap->getFirstAttribute('givenName');
        $database->lastname = $ldap->getFirstAttribute('sn');
        $database->email = $ldap->getFirstAttribute('mail');
        $database->username = $ldap->getFirstAttribute('samaccountname');
        $database->isDeveloper = (bool) $ldap->inGroup(config('ldap.developer_group'));
    }
}

auth.php

 'providers' => [
        'ldap' => [
            'driver' => 'ldap',
            'model' => App\Models\LdapUser::class,
            'rules' => [],
            'database' => [
                'model' => App\Models\User::class,
                'sync_passwords' => true,
                'sync_attributes' => [
                    App\Ldap\AttributeHandler::class,
                ],
                'sync_existing' => [
                    'email' => 'mail',
                ],
            ],
        ],
stevebauman commented 1 year ago

Hi @HepplerDotNet,

I think there's a misunderstanding on how sync_existing works. sync_existing is for defining an attribute map for locating existing users inside of your database to update during the sync process or authentication that do not have a guid or domain set in their Eloquent model:

https://ldaprecord.com/docs/laravel/v3/auth/database/configuration/#sync-attributes https://ldaprecord.com/docs/laravel/v3/auth/database/configuration/#sync-existing-records

sync_attributes and attribute handlers are used to keep attributes in sync, regardless of whether the user is new or existing. If you would like to prevent syncing certain attributes when the user exists or doesn't exist, check for the existence of the user inside your AttributeHandler before setting the attribute:

<?php

namespace App\Ldap;

use App\Models\LdapUser;
use App\Models\User;

class AttributeHandler
{
    public function handle(LdapUser $ldap, User $database): void
    {
        // ...

        if (! $database->exists) {
            $database->isDeveloper = (bool) $ldap->inGroup(config('ldap.developer_group'));
        }
    }
}

Let me know if you have any further questions 👍