Skip to content
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

use current user info as LDAP credential #14

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
Expand Up @@ -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.


Expand Down
23 changes: 17 additions & 6 deletions lib/omniauth-ldap/adaptor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand All @@ -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 = []
Expand All @@ -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})",
Expand Down
7 changes: 7 additions & 0 deletions lib/omniauth/strategies/ldap.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions spec/omniauth-ldap/adaptor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 20 additions & 0 deletions spec/omniauth/strategies/ldap_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 => ['[email protected]'], :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'],
Expand All @@ -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('[email protected]')
@adaptor.should_receive(:password=).with('password')
@adaptor.should_receive(:reset_connection)
post('/auth/ldap/callback', {:username => 'ping', :password => 'password'})
end
end
end
end