1
0
Fork 0
mirror of https://github.com/omniauth/omniauth.git synced 2022-11-09 12:31:49 -05:00

adding user lookup before the first, and use the DN from

the lookup result in the final binding.
This commit is contained in:
Ping Yu 2011-01-02 11:55:11 -06:00
parent 61eb50782b
commit 0ed8037344
3 changed files with 84 additions and 76 deletions

View file

@ -36,10 +36,18 @@ Use the LDAP strategy as a middleware in your applicaiton:
:base => 'dc=intridea, dc=com', :base => 'dc=intridea, dc=com',
:uid => 'sAMAccountName', :uid => 'sAMAccountName',
:name_proc => Proc.new {|name| name.gsub(/@.*$/,'')} :name_proc => Proc.new {|name| name.gsub(/@.*$/,'')}
:bind_dn => 'default_bind_dn'
:password => 'password'
All of the listed options are required, with the exception of :name_proc. All of the listed options are required, with the exception of :name_proc, :bind_dn, and :password
Allowed values of :method are: :plain, :ssl, :tls. Allowed values of :method are: :plain, :ssl, :tls.
:bind_dn and :password are used to perform the initial binding if user lookup is
needed. If the user lookup returns result, the DN attribute from the result set is used
to perform the final binding. This is needed only when the LDAP server requires
DN to be used for binding and you may only want user to using email or username
in the login form.
:uid is the LDAP attribute name for the user name in the login form. typically :uid is the LDAP attribute name for the user name in the login form. typically
AD would be 'sAMAccountName' or 'UserPrincipalName', while OpenLDAP is 'uid'. AD would be 'sAMAccountName' or 'UserPrincipalName', while OpenLDAP is 'uid'.
You can also use 'dn', if your user choose the put in the dn in the login form You can also use 'dn', if your user choose the put in the dn in the login form

View file

@ -52,15 +52,16 @@ module OmniAuth
def perform def perform
begin begin
bind_dn = "#{@adaptor.uid}=#{request.POST['username']}" @ldap_user_info = {}
bind_dn << ",#{@adaptor.base}" unless @adaptor.base == '' (@adaptor.bind unless @adaptor.bound?) rescue puts "failed to bind with the default credentials"
@ldap_user_info = @adaptor.search(:filter => Net::LDAP::Filter.eq(@adaptor.uid, @name_proc.call(request.POST['username'])),:limit => 1) if @adaptor.bound?
bind_dn = request.POST['username']
bind_dn = @ldap_user_info[:dn].to_a.first if @ldap_user_info[:dn]
@adaptor.bind(:bind_dn => bind_dn, :password => request.POST['password'])
@ldap_user_info = @adaptor.search(:filter => Net::LDAP::Filter.eq(@adaptor.uid, @name_proc.call(request.POST['username'])),:limit => 1) if @ldap_user_info.empty?
@user_info = self.class.map_user(@@config, @ldap_user_info)
@adaptor.bind(:bind_dn => bind_dn, :password => request.POST['password']) @env['omniauth.auth'] = auth_hash
@ldap_user_info = @adaptor.search(:filter => Net::LDAP::Filter.eq(@adaptor.uid, @name_proc.call(request.POST['username'])),:limit => 1)
@user_info = self.class.map_user(@@config, @ldap_user_info)
@env['omniauth.auth'] = auth_hash
#@env['REQUEST_METHOD'] = 'GET'
@env['PATH_INFO'] = "#{OmniAuth.config.path_prefix}/#{name}/callback" @env['PATH_INFO'] = "#{OmniAuth.config.path_prefix}/#{name}/callback"
call_app! call_app!

View file

@ -25,7 +25,7 @@ module OmniAuth
:plain => nil :plain => nil
} }
attr_accessor :bind_dn, :password attr_accessor :bind_dn, :password
attr_reader :connection, :uid, :base attr_reader :connection, :uid, :base
def initialize(configuration={}) def initialize(configuration={})
@ -46,9 +46,8 @@ module OmniAuth
def connect(options={}) def connect(options={})
host = options[:host] || @host host = options[:host] || @host
method = options[:method] || @method || :plain method = ensure_method(options[:method] || @method || :plain)
port = options[:port] || @port || ensure_port(method) port = options[:port] || @port || ensure_port(method)
method = ensure_method(method)
@disconnected = false @disconnected = false
@bound = false @bound = false
@bind_tried = false @bind_tried = false
@ -179,65 +178,65 @@ module OmniAuth
available_methods = METHOD.keys.collect {|m| m.inspect}.join(", ") available_methods = METHOD.keys.collect {|m| m.inspect}.join(", ")
format = "%s is not one of the available connect methods: %s" format = "%s is not one of the available connect methods: %s"
raise ConfigurationError, format % [method.inspect, available_methods] raise ConfigurationError, format % [method.inspect, available_methods]
end end
def sasl_bind(bind_dn, options={}) def sasl_bind(bind_dn, options={})
sasl_mechanisms = options[:sasl_mechanisms] || @sasl_mechanisms sasl_mechanisms = options[:sasl_mechanisms] || @sasl_mechanisms
sasl_mechanisms.each do |mechanism| sasl_mechanisms.each do |mechanism|
begin begin
normalized_mechanism = mechanism.downcase.gsub(/-/, '_') normalized_mechanism = mechanism.downcase.gsub(/-/, '_')
sasl_bind_setup = "sasl_bind_setup_#{normalized_mechanism}" sasl_bind_setup = "sasl_bind_setup_#{normalized_mechanism}"
next unless respond_to?(sasl_bind_setup, true) next unless respond_to?(sasl_bind_setup, true)
initial_credential, challenge_response = send(sasl_bind_setup, bind_dn, options) initial_credential, challenge_response = send(sasl_bind_setup, bind_dn, options)
args = { args = {
:method => :sasl, :method => :sasl,
:initial_credential => initial_credential, :initial_credential => initial_credential,
:mechanism => mechanism, :mechanism => mechanism,
:challenge_response => challenge_response, :challenge_response => challenge_response,
} }
info = { info = {
:name => "bind: SASL", :dn => bind_dn, :mechanism => mechanism, :name => "bind: SASL", :dn => bind_dn, :mechanism => mechanism,
} }
puts info.inspect puts info.inspect
execute(:bind, args) execute(:bind, args)
return true return true
rescue Exception => e rescue Exception => e
puts e.message puts e.message
end
end end
false
end
def sasl_bind_setup_digest_md5(bind_dn, options)
initial_credential = ""
challenge_response = Proc.new do |cred|
pref = SASL::Preferences.new :digest_uri => "ldap/#{@host}", :username => bind_dn, :has_password? => true, :password => options[:password]||@password
sasl = SASL.new("DIGEST-MD5", pref)
response = sasl.receive("challenge", cred)
response[1]
end end
[initial_credential, challenge_response]
end
def sasl_bind_setup_gss_spnego(bind_dn, options) false
puts options.inspect end
user,psw = [bind_dn, options[:password]||@password]
raise LdapError.new( "invalid binding information" ) unless (user && psw)
nego = proc {|challenge| def sasl_bind_setup_digest_md5(bind_dn, options)
t2_msg = Net::NTLM::Message.parse( challenge ) initial_credential = ""
user, domain = user.split('\\').reverse challenge_response = Proc.new do |cred|
t2_msg.target_name = Net::NTLM::encode_utf16le(domain) if domain pref = SASL::Preferences.new :digest_uri => "ldap/#{@host}", :username => bind_dn, :has_password? => true, :password => options[:password]||@password
t3_msg = t2_msg.response( {:user => user, :password => psw}, {:ntlmv2 => true} ) sasl = SASL.new("DIGEST-MD5", pref)
t3_msg.serialize response = sasl.receive("challenge", cred)
} response[1]
[Net::NTLM::Message::Type1.new.serialize, nego]
end end
[initial_credential, challenge_response]
end
def sasl_bind_setup_gss_spnego(bind_dn, options)
puts options.inspect
user,psw = [bind_dn, options[:password]||@password]
raise LdapError.new( "invalid binding information" ) unless (user && psw)
nego = proc {|challenge|
t2_msg = Net::NTLM::Message.parse( challenge )
user, domain = user.split('\\').reverse
t2_msg.target_name = Net::NTLM::encode_utf16le(domain) if domain
t3_msg = t2_msg.response( {:user => user, :password => psw}, {:ntlmv2 => true} )
t3_msg.serialize
}
[Net::NTLM::Message::Type1.new.serialize, nego]
end
def simple_bind(bind_dn, options={}) def simple_bind(bind_dn, options={})
args = { args = {
@ -249,19 +248,19 @@ module OmniAuth
true true
end end
def construct_uri(host, port, ssl) def construct_uri(host, port, ssl)
protocol = ssl ? "ldaps" : "ldap" protocol = ssl ? "ldaps" : "ldap"
URI.parse("#{protocol}://#{host}:#{port}").to_s URI.parse("#{protocol}://#{host}:#{port}").to_s
end
def target
return nil if @uri.nil?
if @with_start_tls
"#{@uri}(StartTLS)"
else
@uri
end end
end
def target
return nil if @uri.nil?
if @with_start_tls
"#{@uri}(StartTLS)"
else
@uri
end
end
end end
end end
end end