Skip to content

Commit f63a80c

Browse files
jirutkapboling
authored andcommitted
✨ Support custom ldap attributes mapping
1 parent 345b2a2 commit f63a80c

File tree

3 files changed

+27
-5
lines changed

3 files changed

+27
-5
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ use OmniAuth::Strategies::LDAP,
6969
tls_options: {
7070
ssl_version: "TLSv1_2",
7171
ciphers: ["AES-128-CBC", "AES-128-CBC-HMAC-SHA1", "AES-128-CBC-HMAC-SHA256"],
72+
},
73+
mapping: {
74+
'name' => 'cn;lang-en',
75+
'email' => ['preferredEmail', 'mail'],
76+
'nickname' => ['uid', 'userid', 'sAMAccountName']
7277
}
7378
# Or, alternatively:
7479
# use OmniAuth::Strategies::LDAP, filter: '(&(uid=%{username})(memberOf=cn=myapp-users,ou=groups,dc=example,dc=com))'
@@ -199,6 +204,7 @@ The following options are available for configuring the OmniAuth LDAP strategy:
199204
- `adaptor.last_password_policy_response` — the matching password policy response control (implementation-specific object). This can indicate conditions such as password expired, account locked, reset required, or grace logins remaining (per the draft RFC).
200205
- `:connect_timeout` - Maximum time in seconds to wait when establishing the TCP connection to the LDAP server. Forwarded to `Net::LDAP`.
201206
- `:read_timeout` - Maximum time in seconds to wait for reads during LDAP operations (search/bind). Forwarded to `Net::LDAP`.
207+
- `:mapping` - allows you to customize mapping of LDAP attributes to the returned user info hash. The default mappings are defined in [ldap.rb](lib/omniauth/strategies/ldap.rb#L7), it will be merged with yours.
202208

203209
Example enabling password policy:
204210

lib/omniauth/strategies/ldap.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class LDAP
99

1010
InvalidCredentialsError = Class.new(StandardError)
1111

12-
CONFIG = {
12+
option :mapping, {
1313
"name" => "cn",
1414
"first_name" => "givenName",
1515
"last_name" => "sn",
@@ -23,7 +23,7 @@ class LDAP
2323
"url" => ["wwwhomepage"],
2424
"image" => "jpegPhoto",
2525
"description" => "description",
26-
}.freeze
26+
}
2727
option :title, "LDAP Authentication" # default title for authentication form
2828
# For OmniAuth >= 2.0 the default allowed request method is POST only.
2929
# Ensure the strategy follows that default so GET /auth/:provider returns 404 as expected in tests.
@@ -91,7 +91,7 @@ def callback_phase
9191
return fail!(:invalid_credentials, InvalidCredentialsError.new("User not found for header #{hu}"))
9292
end
9393
@ldap_user_info = entry
94-
@user_info = self.class.map_user(CONFIG, @ldap_user_info)
94+
@user_info = self.class.map_user(@options[:mapping], @ldap_user_info)
9595
return super
9696
rescue => e
9797
return fail!(:ldap_error, e)
@@ -111,7 +111,7 @@ def callback_phase
111111
# Optionally attach policy info even on success (e.g., timeBeforeExpiration)
112112
attach_password_policy_env(@adaptor)
113113

114-
@user_info = self.class.map_user(CONFIG, @ldap_user_info)
114+
@user_info = self.class.map_user(@options[:mapping], @ldap_user_info)
115115
super
116116
rescue => e
117117
fail!(:ldap_error, e)
@@ -205,7 +205,7 @@ def directory_lookup(adaptor, username)
205205
search_filter = filter(adaptor, username)
206206
adaptor.connection.open do |conn|
207207
rs = conn.search(filter: search_filter, size: 1)
208-
entry = rs && rs.first
208+
entry = rs&.first
209209
end
210210
entry
211211
end

spec/omniauth/strategies/ldap_spec.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,22 @@ def make_env(path = "/auth/ldap", props = {})
432432
expect(info.image).to eq "http://www.intridea.com/ping.jpg"
433433
expect(info.description).to eq "omniauth-ldap"
434434
end
435+
436+
context 'and mapping is set' do
437+
let(:app) do
438+
Rack::Builder.new {
439+
use OmniAuth::Test::PhonySession
440+
use MyLdapProvider, :name => 'ldap', :host => '192.168.1.145', :base => 'dc=score, dc=local', :mapping => { 'phone' => 'mobile' }
441+
run lambda { |env| [404, {'Content-Type' => 'text/plain'}, [env.key?('omniauth.auth').to_s]] }
442+
}.to_app
443+
end
444+
445+
it 'should map user info according to customized mapping' do
446+
post('/auth/ldap/callback', {:username => 'ping', :password => 'password'})
447+
auth_hash.info.phone.should == '444-444-4444'
448+
auth_hash.info.mobile.should == '444-444-4444'
449+
end
450+
end
435451
end
436452
end
437453

0 commit comments

Comments
 (0)