diff --git a/.env.example.complete b/.env.example.complete index 77a0508dc..911d924df 100644 --- a/.env.example.complete +++ b/.env.example.complete @@ -177,6 +177,7 @@ LDAP_USER_FILTER=false LDAP_VERSION=false LDAP_TLS_INSECURE=false LDAP_EMAIL_ATTRIBUTE=mail +LDAP_DISPLAY_NAME_ATTRIBUTE=cn LDAP_FOLLOW_REFERRALS=true # LDAP group sync configuration diff --git a/app/Auth/Access/LdapService.php b/app/Auth/Access/LdapService.php index 654ea2f99..c48a72f98 100644 --- a/app/Auth/Access/LdapService.php +++ b/app/Auth/Access/LdapService.php @@ -80,7 +80,9 @@ class LdapService public function getUserDetails($userName) { $emailAttr = $this->config['email_attribute']; - $user = $this->getUserWithAttributes($userName, ['cn', 'uid', 'dn', $emailAttr]); + $displayNameAttr = $this->config['display_name_attribute']; + + $user = $this->getUserWithAttributes($userName, ['cn', 'uid', 'dn', $emailAttr, $displayNameAttr]); if ($user === null) { return null; @@ -88,7 +90,7 @@ class LdapService return [ 'uid' => (isset($user['uid'])) ? $user['uid'][0] : $user['dn'], - 'name' => $user['cn'][0], + 'name' => (isset($user[$displayNameAttr])) ? (is_array($user[$displayNameAttr]) ? $user[$displayNameAttr][0] : $user[$displayNameAttr]) : $user['cn'][0], 'dn' => $user['dn'], 'email' => (isset($user[$emailAttr])) ? (is_array($user[$emailAttr]) ? $user[$emailAttr][0] : $user[$emailAttr]) : null ]; diff --git a/config/services.php b/config/services.php index f713f9d38..97cb71ddc 100644 --- a/config/services.php +++ b/config/services.php @@ -141,6 +141,7 @@ return [ 'user_filter' => env('LDAP_USER_FILTER', '(&(uid=${user}))'), 'version' => env('LDAP_VERSION', false), 'email_attribute' => env('LDAP_EMAIL_ATTRIBUTE', 'mail'), + 'display_name_attribute' => env('LDAP_DISPLAY_NAME_ATTRIBUTE', 'cn'), 'follow_referrals' => env('LDAP_FOLLOW_REFERRALS', false), 'user_to_groups' => env('LDAP_USER_TO_GROUPS',false), 'group_attribute' => env('LDAP_GROUP_ATTRIBUTE', 'memberOf'), diff --git a/tests/Auth/LdapTest.php b/tests/Auth/LdapTest.php index 16ba11358..54cf84266 100644 --- a/tests/Auth/LdapTest.php +++ b/tests/Auth/LdapTest.php @@ -23,6 +23,7 @@ class LdapTest extends BrowserKitTest 'auth.method' => 'ldap', 'services.ldap.base_dn' => 'dc=ldap,dc=local', 'services.ldap.email_attribute' => 'mail', + 'services.ldap.display_name_attribute' => 'cn', 'services.ldap.user_to_groups' => false, 'auth.providers.users.driver' => 'ldap', ]); @@ -372,4 +373,81 @@ class LdapTest extends BrowserKitTest ]); } + public function test_login_uses_specified_display_name_attribute() + { + $originalAttribute = config('services.ldap.display_name_attribute'); + app('config')->set([ + 'services.ldap.display_name_attribute' => 'displayName' + ]); + + $this->mockLdap->shouldReceive('connect')->once()->andReturn($this->resourceId); + $this->mockLdap->shouldReceive('setVersion')->once(); + $this->mockLdap->shouldReceive('setOption')->times(4); + $this->mockLdap->shouldReceive('searchAndGetEntries')->times(4) + ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array')) + ->andReturn(['count' => 1, 0 => [ + 'uid' => [$this->mockUser->name], + 'cn' => [$this->mockUser->name], + 'dn' => ['dc=test' . config('services.ldap.base_dn')], + 'displayName' => 'displayNameAttribute' + ]]); + $this->mockLdap->shouldReceive('bind')->times(6)->andReturn(true); + $this->mockEscapes(4); + + $this->visit('/login') + ->see('Username') + ->type($this->mockUser->name, '#username') + ->type($this->mockUser->password, '#password') + ->press('Log In') + ->seePageIs('/login')->see('Please enter an email to use for this account.'); + + $this->type($this->mockUser->email, '#email') + ->press('Log In') + ->seePageIs('/') + ->see('displayNameAttribute') + ->seeInDatabase('users', ['email' => $this->mockUser->email, 'email_confirmed' => false, 'external_auth_id' => $this->mockUser->name, 'name' => 'displayNameAttribute']); + + app('config')->set([ + 'services.ldap.display_name_attribute' => $originalAttribute + ]); + } + + public function test_login_uses_default_display_name_attribute_if_specified_not_present() + { + $originalAttribute = config('services.ldap.display_name_attribute'); + app('config')->set([ + 'services.ldap.display_name_attribute' => 'displayName' + ]); + + $this->mockLdap->shouldReceive('connect')->once()->andReturn($this->resourceId); + $this->mockLdap->shouldReceive('setVersion')->once(); + $this->mockLdap->shouldReceive('setOption')->times(4); + $this->mockLdap->shouldReceive('searchAndGetEntries')->times(4) + ->with($this->resourceId, config('services.ldap.base_dn'), \Mockery::type('string'), \Mockery::type('array')) + ->andReturn(['count' => 1, 0 => [ + 'uid' => [$this->mockUser->name], + 'cn' => [$this->mockUser->name], + 'dn' => ['dc=test' . config('services.ldap.base_dn')] + ]]); + $this->mockLdap->shouldReceive('bind')->times(6)->andReturn(true); + $this->mockEscapes(4); + + $this->visit('/login') + ->see('Username') + ->type($this->mockUser->name, '#username') + ->type($this->mockUser->password, '#password') + ->press('Log In') + ->seePageIs('/login')->see('Please enter an email to use for this account.'); + + $this->type($this->mockUser->email, '#email') + ->press('Log In') + ->seePageIs('/') + ->see($this->mockUser->name) + ->seeInDatabase('users', ['email' => $this->mockUser->email, 'email_confirmed' => false, 'external_auth_id' => $this->mockUser->name, 'name' => $this->mockUser->name]); + + app('config')->set([ + 'services.ldap.display_name_attribute' => $originalAttribute + ]); + } + }