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:
parent
61eb50782b
commit
0ed8037344
3 changed files with 84 additions and 76 deletions
|
@ -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
|
||||||
|
|
|
@ -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!
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue