Skip to content

use current user info as LDAP credential #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -38,6 +38,10 @@ Allowed values of :method are: :plain, :ssl, :tls.
Use them to initialize a SASL connection to server. If you are not familiar with these authentication methods,
please just avoid them.

:use_user_credential Allow you to use current login user's info as LDAP credential. true/false.
If you don't have a default credential (:bind_dn and :password) for ldap config,
You can fake it by using the current login user's name and password.

Direct users to '/auth/ldap' to have them authenticated via your company's LDAP server.


23 changes: 17 additions & 6 deletions lib/omniauth-ldap/adaptor.rb
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ class ConfigurationError < StandardError; end
class AuthenticationError < StandardError; end
class ConnectionError < StandardError; end

VALID_ADAPTER_CONFIGURATION_KEYS = [:host, :port, :method, :bind_dn, :password, :try_sasl, :sasl_mechanisms, :uid, :base, :allow_anonymous]
VALID_ADAPTER_CONFIGURATION_KEYS = [:host, :port, :method, :bind_dn, :password, :try_sasl, :sasl_mechanisms, :uid, :base, :allow_anonymous, :use_user_credential]

MUST_HAVE_KEYS = [:host, :port, :method, :uid, :base]

@@ -25,6 +25,7 @@ class ConnectionError < StandardError; end
}

attr_accessor :bind_dn, :password
attr_accessor :use_user_credential
attr_reader :connection, :uid, :base, :auth
def self.validate(configuration={})
message = []
@@ -41,26 +42,36 @@ def initialize(configuration={})
VALID_ADAPTER_CONFIGURATION_KEYS.each do |name|
instance_variable_set("@#{name}", @configuration[name])
end
@uri = construct_uri(@host, @port, @method != :plain) # seems not used anywhere.
reset_connection
end

def reset_connection
method = ensure_method(@method)
config = {
:host => @host,
:port => @port,
:encryption => method,
:base => @base
}
@uri = construct_uri(@host, @port, @method != :plain)

@bind_method = @try_sasl ? :sasl : (@allow_anonymous||!@bind_dn||!@password ? :anonymous : :simple)


@auth = sasl_auths({:username => @bind_dn, :password => @password}).first if @bind_method == :sasl
@auth ||= { :method => @bind_method,
if @bind_method == :sasl
@auth = sasl_auths({:username => @bind_dn, :password => @password}).first if @bind_method == :sasl
else
@auth = { :method => @bind_method,
:username => @bind_dn,
:password => @password
}
end
config[:auth] = @auth
@connection = Net::LDAP.new(config)
end

# convert 'dc=intridea, dc=com' to 'intridea.com'
def base_to_host(str)
str.split(',').map{|x| x.split('=').last}.join('.')
end

#:base => "dc=yourcompany, dc=com",
# :filter => "(mail=#{user})",
7 changes: 7 additions & 0 deletions lib/omniauth/strategies/ldap.rb
Original file line number Diff line number Diff line change
@@ -39,6 +39,13 @@ def callback_phase
@adaptor = OmniAuth::LDAP::Adaptor.new @options

raise MissingCredentialsError.new("Missing login credentials") if request['username'].nil? || request['password'].nil?

if @adaptor.use_user_credential
@adaptor.bind_dn = request['username'] + '@' + @adaptor.base_to_host(@adaptor.base)
@adaptor.password = request['password']
@adaptor.reset_connection
end

begin
@ldap_user_info = @adaptor.bind_as(:filter => Net::LDAP::Filter.eq(@adaptor.uid, @options[:name_proc].call(request['username'])),:size => 1, :password => request['password'])
return fail!(:invalid_credentials) if !@ldap_user_info
8 changes: 8 additions & 0 deletions spec/omniauth-ldap/adaptor_spec.rb
Original file line number Diff line number Diff line change
@@ -49,6 +49,14 @@
adaptor.connection.instance_variable_get('@auth')[:initial_credential].should =~ /^NTLMSSP/
adaptor.connection.instance_variable_get('@auth')[:challenge_response].should_not be_nil
end
it 'should reset connection' do
adaptor = OmniAuth::LDAP::Adaptor.new({host: "192.168.1.145", method: 'plain', base: 'dc=intridea, dc=com', port: 389, uid: 'sAMAccountName'})
adaptor.connection.instance_variable_get('@auth').should == {:method => :anonymous, :username => nil, :password => nil}
adaptor.bind_dn ='someone'
adaptor.password='secret'
adaptor.reset_connection
adaptor.connection.instance_variable_get('@auth').should == {:method => :simple, :username => 'someone', :password => 'secret'}
end
end

describe 'bind_as' do
20 changes: 20 additions & 0 deletions spec/omniauth/strategies/ldap_spec.rb
Original file line number Diff line number Diff line change
@@ -55,6 +55,7 @@ def session
context 'failure' do
before(:each) do
@adaptor.stub(:bind_as).and_return(false)
@adaptor.stub(:use_user_credential).and_return(false)
end
it 'should raise MissingCredentialsError' do
lambda{post('/auth/ldap/callback', {})}.should raise_error OmniAuth::Strategies::LDAP::MissingCredentialsError
@@ -75,6 +76,7 @@ def session
context 'success' do
let(:auth_hash){ last_request.env['omniauth.auth'] }
before(:each) do
@adaptor.stub(:use_user_credential).and_return(false)
@adaptor.stub(:bind_as).and_return({:dn => ['cn=ping, dc=intridea, dc=com'], :mail => ['ping@intridea.com'], :givenname => ['Ping'], :sn => ['Yu'],
:telephonenumber => ['555-555-5555'], :mobile => ['444-444-4444'], :uid => ['ping'], :title => ['dev'], :address =>[ 'k street'],
:l => ['Washington'], :st => ['DC'], :co => ["U.S.A"], :postofficebox => ['20001'], :wwwhomepage => ['www.intridea.com'],
@@ -100,5 +102,23 @@ def session
auth_hash.info.description.should == 'omniauth-ldap'
end
end

context 'use user credential' do
let(:auth_hash){ last_request.env['omniauth.auth'] }
before(:each) do
@adaptor = mock(OmniAuth::LDAP::Adaptor, {:uid => 'sAMAccountName',
:base => 'dc=intridea, dc=com',
:use_user_credential => true})
OmniAuth::LDAP::Adaptor.stub(:new).and_return(@adaptor)
end

it 'should reset connection' do
@adaptor.stub(:base_to_host).and_return('intridea.com')
@adaptor.should_receive(:bind_dn=).with('ping@intridea.com')
@adaptor.should_receive(:password=).with('password')
@adaptor.should_receive(:reset_connection)
post('/auth/ldap/callback', {:username => 'ping', :password => 'password'})
end
end
end
end