From c1a02561dfca43bab8595b5e9bb2b6f93ae49fcc Mon Sep 17 00:00:00 2001 From: Ryan Bone Date: Fri, 12 May 2017 10:01:32 -0400 Subject: [PATCH] Include all common names when common_names is in extra attributes The current implementation will only return the first group the user is in when memberof is supplied in extra_attributes. This will allow all group common names to be returned. Returning all full group names led to ActionDispatch::Cookies::CookieOverflow errors. --- lib/casino/ldap_authenticator.rb | 19 +++++----- spec/casino/ldap_authenticator_spec.rb | 51 +++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/lib/casino/ldap_authenticator.rb b/lib/casino/ldap_authenticator.rb index 5af2ed8..a8aca9d 100644 --- a/lib/casino/ldap_authenticator.rb +++ b/lib/casino/ldap_authenticator.rb @@ -77,17 +77,16 @@ def user_filter(username) end def extra_attributes(user_plain) - if @options[:extra_attributes] - result = {} - @options[:extra_attributes].each do |index_result, index_ldap| - value = user_plain[index_ldap] - if value - result[index_result] = "#{value.first}" - end + @options[:extra_attributes].each_with_object({}) do |(index_result, index_ldap), result| + result.merge!(index_result => user_plain[index_ldap].first.to_s) + end.tap do |results| + if @options[:extra_attributes].keys.include?(:common_names) + results[:common_names] = common_name_list(user_plain[:memberof]) end - result - else - nil end end + + def common_name_list(memberof_list) + memberof_list.map { |memberof| memberof.match(/^CN=(\w*),/)[1] } + end end diff --git a/spec/casino/ldap_authenticator_spec.rb b/spec/casino/ldap_authenticator_spec.rb index ad15444..3b5798b 100644 --- a/spec/casino/ldap_authenticator_spec.rb +++ b/spec/casino/ldap_authenticator_spec.rb @@ -8,8 +8,9 @@ :base => 'dc=users,dc=example.com', :encryption => 'simple_tls', :username_attribute => 'uid', - :extra_attributes => { :email => 'mail', :fullname => :displayname, :memberof => 'memberof'} + :extra_attributes => extra_attributes_options } } + let(:extra_attributes_options) { Hash :email => 'mail', :fullname => :displayname, :memberof => 'memberof' } let(:subject) { described_class.new(options) } let(:connection) { Object.new } @@ -164,6 +165,54 @@ } } end + + context 'when supplied the common_names option' do + let(:extra_attributes_options) { super().merge(common_names: 'common_names') } + let(:group_1) { 'CN=group1,OU=Organization,OU=Unit,DC=Domain,DC=Component' } + let(:ldap_entry) do + Net::LDAP::Entry.new.tap do |entry| + entry[:uid] = [username] + entry[:displayname] = [fullname] + entry[:mail] = [email] + end + end + + context 'when the user belongs to no groups' do + it 'returns the user data with an empty list of common names' do + subject.validate(username, password).should == { + username: username, + extra_attributes: { + :email => email, + :fullname => fullname, + :memberof => '', + :common_names => [] + } + } + end + end + + context 'when the user belongs to many groups' do + let(:membership) do + [ + group_1, + 'CN=group2,OU=Organization,OU=Unit,DC=Domain,DC=Component', + 'CN=group3,OU=Organization,OU=Unit,DC=Domain,DC=Component', + ] + end + let(:ldap_entry) { super().tap { |entry| entry[:memberof] = membership } } + it 'returns the user data with a list of common names of the groups' do + subject.validate(username, password).should == { + username: username, + extra_attributes: { + :email => email, + :fullname => fullname, + :memberof => group_1, + :common_names => ['group1', 'group2', 'group3'] + } + } + end + end + end end context 'when validation fails' do