omniauth-ldap 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ .project
2
+ coverage
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development, :test do
6
+ gem 'guard'
7
+ gem 'guard-rspec'
8
+ gem 'guard-bundler'
9
+ gem 'growl'
10
+ gem 'rb-fsevent'
11
+ end
@@ -0,0 +1,79 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ omniauth-ldap (1.0.1)
5
+ net-ldap (~> 0.2.2)
6
+ omniauth (~> 1.0)
7
+ pyu-ruby-sasl (~> 0.0.3.1)
8
+ rubyntlm (~> 0.1.1)
9
+
10
+ GEM
11
+ remote: http://rubygems.org/
12
+ specs:
13
+ archive-tar-minitar (0.5.2)
14
+ columnize (0.3.4)
15
+ diff-lcs (1.1.3)
16
+ ffi (1.0.9)
17
+ growl (1.0.3)
18
+ guard (0.8.8)
19
+ thor (~> 0.14.6)
20
+ guard-bundler (0.1.3)
21
+ bundler (>= 1.0.0)
22
+ guard (>= 0.2.2)
23
+ guard-rspec (0.5.0)
24
+ guard (>= 0.8.4)
25
+ hashie (1.2.0)
26
+ libnotify (0.5.7)
27
+ ffi (= 1.0.9)
28
+ linecache19 (0.5.12)
29
+ ruby_core_source (>= 0.1.4)
30
+ multi_json (1.0.3)
31
+ net-ldap (0.2.2)
32
+ omniauth (1.0.0)
33
+ hashie (~> 1.2)
34
+ rack
35
+ pyu-ruby-sasl (0.0.3.3)
36
+ rack (1.3.5)
37
+ rack-test (0.6.1)
38
+ rack (>= 1.0)
39
+ rb-fsevent (0.4.3.1)
40
+ rspec (2.7.0)
41
+ rspec-core (~> 2.7.0)
42
+ rspec-expectations (~> 2.7.0)
43
+ rspec-mocks (~> 2.7.0)
44
+ rspec-core (2.7.1)
45
+ rspec-expectations (2.7.0)
46
+ diff-lcs (~> 1.1.2)
47
+ rspec-mocks (2.7.0)
48
+ ruby-debug-base19 (0.11.25)
49
+ columnize (>= 0.3.1)
50
+ linecache19 (>= 0.5.11)
51
+ ruby_core_source (>= 0.1.4)
52
+ ruby-debug19 (0.11.6)
53
+ columnize (>= 0.3.1)
54
+ linecache19 (>= 0.5.11)
55
+ ruby-debug-base19 (>= 0.11.19)
56
+ ruby_core_source (0.1.5)
57
+ archive-tar-minitar (>= 0.5.2)
58
+ rubyntlm (0.1.1)
59
+ simplecov (0.5.4)
60
+ multi_json (~> 1.0.3)
61
+ simplecov-html (~> 0.5.3)
62
+ simplecov-html (0.5.3)
63
+ thor (0.14.6)
64
+
65
+ PLATFORMS
66
+ ruby
67
+
68
+ DEPENDENCIES
69
+ growl
70
+ guard
71
+ guard-bundler
72
+ guard-rspec
73
+ libnotify
74
+ omniauth-ldap!
75
+ rack-test
76
+ rb-fsevent
77
+ rspec (~> 2.7)
78
+ ruby-debug19
79
+ simplecov
@@ -0,0 +1,11 @@
1
+ guard 'rspec', :version => 2 do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
6
+
7
+
8
+ guard 'bundler' do
9
+ watch('Gemfile')
10
+ watch(/^.+\.gemspec/)
11
+ end
@@ -0,0 +1,64 @@
1
+ # OmniAuth LDAP
2
+
3
+ == LDAP
4
+
5
+ Use the LDAP strategy as a middleware in your application:
6
+
7
+ use OmniAuth::Strategies::LDAP,
8
+ :title => "My LDAP",
9
+ :host => '10.101.10.1',
10
+ :port => 389,
11
+ :method => :plain,
12
+ :base => 'dc=intridea, dc=com',
13
+ :uid => 'sAMAccountName',
14
+ :name_proc => Proc.new {|name| name.gsub(/@.*$/,'')}
15
+ :bind_dn => 'default_bind_dn'
16
+ :password => 'password'
17
+
18
+ All of the listed options are required, with the exception of :title, :name_proc, :bind_dn, and :password.
19
+ Allowed values of :method are: :plain, :ssl, :tls.
20
+
21
+ :bind_dn and :password is the default credentials to perform user lookup.
22
+ most LDAP servers require that you supply a complete DN as a binding-credential, along with an authenticator
23
+ such as a password. But for many applications, you often don’t have a full DN to identify the user.
24
+ You usually get a simple identifier like a username or an email address, along with a password.
25
+ Since many LDAP servers don't allow anonymous access, search function will require a bound connection,
26
+ :bind_dn and :password will be required for searching on the username or email to retrieve the DN attribute
27
+ for the user. If the LDAP server allows anonymous access, you don't need to provide these two parameters.
28
+
29
+ :uid is the LDAP attribute name for the user name in the login form.
30
+ typically AD would be 'sAMAccountName' or 'UserPrincipalName', while OpenLDAP is 'uid'.
31
+
32
+ :name_proc allows you to match the user name entered with the format of the :uid attributes.
33
+ For example, value of 'sAMAccountName' in AD contains only the windows user name. If your user prefers using
34
+ email to login, a name_proc as above will trim the email string down to just the windows login name.
35
+ In summary, use :name_proc to fill the gap between the submitted username and LDAP uid attribute value.
36
+
37
+ :try_sasl and :sasl_mechanisms are optional. :try_sasl [true | false], :sasl_mechanisms ['DIGEST-MD5' | 'GSS-SPNEGO']
38
+ Use them to initialize a SASL connection to server. If you are not familiar with these authentication methods,
39
+ please just avoid them.
40
+
41
+ Direct users to '/auth/ldap' to have them authenticated via your company's LDAP server.
42
+
43
+
44
+ ## License
45
+
46
+ Copyright (C) 2011 by Ping Yu and Intridea, Inc.
47
+
48
+ Permission is hereby granted, free of charge, to any person obtaining a copy
49
+ of this software and associated documentation files (the "Software"), to deal
50
+ in the Software without restriction, including without limitation the rights
51
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
52
+ copies of the Software, and to permit persons to whom the Software is
53
+ furnished to do so, subject to the following conditions:
54
+
55
+ The above copyright notice and this permission notice shall be included in
56
+ all copies or substantial portions of the Software.
57
+
58
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
61
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
64
+ THE SOFTWARE.
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc 'Default: run specs.'
6
+ task :default => :spec
7
+
8
+ desc "Run specs"
9
+ RSpec::Core::RakeTask.new
@@ -0,0 +1,4 @@
1
+ require "omniauth-ldap/version"
2
+ require "omniauth-ldap/adaptor"
3
+ require 'omniauth/strategies/ldap'
4
+
@@ -0,0 +1,147 @@
1
+ #this code borrowed pieces from activeldap and net-ldap
2
+
3
+ require 'rack'
4
+ require 'net/ldap'
5
+ require 'net/ntlm'
6
+ require 'uri'
7
+ require 'sasl'
8
+ require 'kconv'
9
+ module OmniAuth
10
+ module LDAP
11
+ class Adaptor
12
+ class LdapError < StandardError; end
13
+ class ConfigurationError < StandardError; end
14
+ class AuthenticationError < StandardError; end
15
+ class ConnectionError < StandardError; end
16
+
17
+ VALID_ADAPTER_CONFIGURATION_KEYS = [:host, :port, :method, :bind_dn, :password, :try_sasl, :sasl_mechanisms, :uid, :base, :allow_anonymous]
18
+
19
+ MUST_HAVE_KEYS = [:host, :port, :method, :uid, :base]
20
+
21
+ METHOD = {
22
+ :ssl => :simple_tls,
23
+ :tls => :start_tls,
24
+ :plain => nil,
25
+ }
26
+
27
+ attr_accessor :bind_dn, :password
28
+ attr_reader :connection, :uid, :base, :auth
29
+
30
+ def initialize(configuration={})
31
+ @configuration = configuration.dup
32
+ @configuration[:allow_anonymous] ||= false
33
+ @logger = @configuration.delete(:logger)
34
+ message = []
35
+ MUST_HAVE_KEYS.each do |name|
36
+ message << name if configuration[name].nil?
37
+ end
38
+ raise ArgumentError.new(message.join(",") +" MUST be provided") unless message.empty?
39
+ VALID_ADAPTER_CONFIGURATION_KEYS.each do |name|
40
+ instance_variable_set("@#{name}", configuration[name])
41
+ end
42
+ method = ensure_method(@method)
43
+ config = {
44
+ :host => @host,
45
+ :port => @port,
46
+ :encryption => method,
47
+ :base => @base
48
+ }
49
+ @uri = construct_uri(@host, @port, @method != :plain)
50
+
51
+ @bind_method = @try_sasl ? :sasl : (@allow_anonymous||!@bind_dn||!@password ? :anonymous : :simple)
52
+
53
+
54
+ @auth = sasl_auths({:username => @bind_dn, :password => @password}).first if @bind_method == :sasl
55
+ @auth ||= { :method => @bind_method,
56
+ :username => @bind_dn,
57
+ :password => @password
58
+ }
59
+ config[:auth] = @auth
60
+ @connection = Net::LDAP.new(config)
61
+ end
62
+
63
+ #:base => "dc=yourcompany, dc=com",
64
+ # :filter => "(mail=#{user})",
65
+ # :password => psw
66
+ def bind_as(args = {})
67
+ result = false
68
+ @connection.open do |me|
69
+ rs = me.search args
70
+ if rs and rs.first and dn = rs.first.dn
71
+ password = args[:password]
72
+ method = args[:method] || @method
73
+ password = password.call if password.respond_to?(:call)
74
+ if method == 'sasl'
75
+ result = rs.first if me.bind(sasl_auths({:username => dn, :password => password}).first)
76
+ else
77
+ result = rs.first if me.bind(:method => :simple, :username => dn,
78
+ :password => password)
79
+ end
80
+ end
81
+ end
82
+ result
83
+ end
84
+
85
+ private
86
+ def ensure_method(method)
87
+ method ||= "plain"
88
+ normalized_method = method.to_s.downcase.to_sym
89
+ return METHOD[normalized_method] if METHOD.has_key?(normalized_method)
90
+
91
+ available_methods = METHOD.keys.collect {|m| m.inspect}.join(", ")
92
+ format = "%s is not one of the available connect methods: %s"
93
+ raise ConfigurationError, format % [method.inspect, available_methods]
94
+ end
95
+
96
+ def sasl_auths(options={})
97
+ auths = []
98
+ sasl_mechanisms = options[:sasl_mechanisms] || @sasl_mechanisms
99
+ sasl_mechanisms.each do |mechanism|
100
+ normalized_mechanism = mechanism.downcase.gsub(/-/, '_')
101
+ sasl_bind_setup = "sasl_bind_setup_#{normalized_mechanism}"
102
+ next unless respond_to?(sasl_bind_setup, true)
103
+ initial_credential, challenge_response = send(sasl_bind_setup, options)
104
+ auths << {
105
+ :method => :sasl,
106
+ :initial_credential => initial_credential,
107
+ :mechanism => mechanism,
108
+ :challenge_response => challenge_response
109
+ }
110
+ end
111
+ auths
112
+ end
113
+
114
+ def sasl_bind_setup_digest_md5(options)
115
+ bind_dn = options[:username]
116
+ initial_credential = ""
117
+ challenge_response = Proc.new do |cred|
118
+ pref = SASL::Preferences.new :digest_uri => "ldap/#{@host}", :username => bind_dn, :has_password? => true, :password => options[:password]
119
+ sasl = SASL.new("DIGEST-MD5", pref)
120
+ response = sasl.receive("challenge", cred)
121
+ response[1]
122
+ end
123
+ [initial_credential, challenge_response]
124
+ end
125
+
126
+ def sasl_bind_setup_gss_spnego(options)
127
+ bind_dn = options[:username]
128
+ psw = options[:password]
129
+ raise LdapError.new( "invalid binding information" ) unless (bind_dn && psw)
130
+
131
+ nego = proc {|challenge|
132
+ t2_msg = Net::NTLM::Message.parse( challenge )
133
+ bind_dn, domain = bind_dn.split('\\').reverse
134
+ t2_msg.target_name = Net::NTLM::encode_utf16le(domain) if domain
135
+ t3_msg = t2_msg.response( {:user => bind_dn, :password => psw}, {:ntlmv2 => true} )
136
+ t3_msg.serialize
137
+ }
138
+ [Net::NTLM::Message::Type1.new.serialize, nego]
139
+ end
140
+
141
+ def construct_uri(host, port, ssl)
142
+ protocol = ssl ? "ldaps" : "ldap"
143
+ URI.parse("#{protocol}://#{host}:#{port}").to_s
144
+ end
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,5 @@
1
+ module OmniAuth
2
+ module LDAP
3
+ VERSION = "1.0.2"
4
+ end
5
+ end
@@ -0,0 +1,88 @@
1
+ require 'omniauth'
2
+
3
+ module OmniAuth
4
+ module Strategies
5
+ class LDAP
6
+ class MissingCredentialsError < StandardError; end
7
+ include OmniAuth::Strategy
8
+ @@config = {
9
+ 'name' => 'cn',
10
+ 'first_name' => 'givenName',
11
+ 'last_name' => 'sn',
12
+ 'email' => ['mail', "email", 'userPrincipalName'],
13
+ 'phone' => ['telephoneNumber', 'homePhone', 'facsimileTelephoneNumber'],
14
+ 'mobile' => ['mobile', 'mobileTelephoneNumber'],
15
+ 'nickname' => ['uid', 'userid', 'sAMAccountName'],
16
+ 'title' => 'title',
17
+ 'location' => {"%0, %1, %2, %3 %4" => [['address', 'postalAddress', 'homePostalAddress', 'street', 'streetAddress'], ['l'], ['st'],['co'],['postOfficeBox']]},
18
+ 'uid' => 'dn',
19
+ 'url' => ['wwwhomepage'],
20
+ 'image' => 'jpegPhoto',
21
+ 'description' => 'description'
22
+ }
23
+ option :title, "LDAP Authentication" #default title for authentication form
24
+ option :port, 389
25
+ option :method, :plain
26
+ option :uid, 'sAMAccountName'
27
+ option :name_proc, lambda {|n| n}
28
+ def initialize(app, *args, &block)
29
+ super
30
+ @adaptor = OmniAuth::LDAP::Adaptor.new @options
31
+ end
32
+ def request_phase
33
+ f = OmniAuth::Form.new(:title => (options[:title] || "LDAP Authentication"), :url => callback_path)
34
+ f.text_field 'Login', 'username'
35
+ f.password_field 'Password', 'password'
36
+ f.button "Sign In"
37
+ f.to_response
38
+ end
39
+
40
+ def callback_phase
41
+ raise MissingCredentialsError.new("Missing login credentials") if request['username'].nil? || request['password'].nil?
42
+ begin
43
+ @ldap_user_info = @adaptor.bind_as(:filter => Net::LDAP::Filter.eq(@adaptor.uid, @options[:name_proc].call(request['username'])),:size => 1, :password => request['password'])
44
+ return fail!(:invalid_credentials) if !@ldap_user_info
45
+
46
+ @user_info = self.class.map_user(@@config, @ldap_user_info)
47
+ super
48
+ rescue Exception => e
49
+ return fail!(:ldap_error, e)
50
+ end
51
+ end
52
+
53
+ uid {
54
+ @user_info["uid"]
55
+ }
56
+ info {
57
+ @user_info
58
+ }
59
+ extra {
60
+ { :raw_info => @ldap_user_info }
61
+ }
62
+
63
+ def self.map_user(mapper, object)
64
+ user = {}
65
+ mapper.each do |key, value|
66
+ case value
67
+ when String
68
+ user[key] = object[value.downcase.to_sym].first if object[value.downcase.to_sym]
69
+ when Array
70
+ value.each {|v| (user[key] = object[v.downcase.to_sym].first; break;) if object[v.downcase.to_sym]}
71
+ when Hash
72
+ value.map do |key1, value1|
73
+ pattern = key1.dup
74
+ value1.each_with_index do |v,i|
75
+ part = ''; v.collect(&:downcase).collect(&:to_sym).each {|v1| (part = object[v1].first; break;) if object[v1]}
76
+ pattern.gsub!("%#{i}",part||'')
77
+ end
78
+ user[key] = pattern
79
+ end
80
+ end
81
+ end
82
+ user
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ OmniAuth.config.add_camelization 'ldap', 'LDAP'
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/omniauth-ldap/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Ping Yu"]
6
+ gem.email = ["ping@intridea.com"]
7
+ gem.description = %q{A LDAP strategy for OmniAuth.}
8
+ gem.summary = %q{A LDAP strategy for OmniAuth.}
9
+ gem.homepage = "https://github.com/intridea/omniauth-ldap"
10
+
11
+ gem.add_runtime_dependency 'omniauth', '~> 1.0'
12
+ gem.add_runtime_dependency 'net-ldap', '~> 0.2.2'
13
+ gem.add_runtime_dependency 'pyu-ruby-sasl', '~> 0.0.3.1'
14
+ gem.add_runtime_dependency 'rubyntlm', '~> 0.1.1'
15
+ gem.add_development_dependency 'rspec', '~> 2.7'
16
+ gem.add_development_dependency 'simplecov'
17
+ gem.add_development_dependency 'rack-test'
18
+ gem.add_development_dependency 'libnotify'
19
+ gem.add_development_dependency 'ruby-debug19'
20
+
21
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ gem.files = `git ls-files`.split("\n")
23
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ gem.name = "omniauth-ldap"
25
+ gem.require_paths = ["lib"]
26
+ gem.version = OmniAuth::LDAP::VERSION
27
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+ describe "OmniAuth::LDAP::Adaptor" do
3
+
4
+ describe 'initialize' do
5
+
6
+ it 'should throw exception when must have field is not set' do
7
+ #[:host, :port, :method, :bind_dn]
8
+ lambda { OmniAuth::LDAP::Adaptor.new({host: "192.168.1.145", method: 'plain'})}.should raise_error(ArgumentError)
9
+ end
10
+ it 'should throw exception when method is not supported' do
11
+ lambda { OmniAuth::LDAP::Adaptor.new({host: "192.168.1.145", method: 'myplain', uid: 'uid', port: 389, base: 'dc=com'})}.should raise_error(OmniAuth::LDAP::Adaptor::ConfigurationError)
12
+ end
13
+
14
+ it 'should setup ldap connection with anonymous' do
15
+ adaptor = OmniAuth::LDAP::Adaptor.new({host: "192.168.1.145", method: 'plain', base: 'dc=intridea, dc=com', port: 389, uid: 'sAMAccountName'})
16
+ adaptor.connection.should_not == nil
17
+ adaptor.connection.host.should == '192.168.1.145'
18
+ adaptor.connection.port.should == 389
19
+ adaptor.connection.base.should == 'dc=intridea, dc=com'
20
+ adaptor.connection.instance_variable_get('@auth').should == {:method => :anonymous, :username => nil, :password => nil}
21
+ end
22
+ it 'should setup ldap connection with simple' do
23
+ adaptor = OmniAuth::LDAP::Adaptor.new({host: "192.168.1.145", method: 'plain', base: 'dc=intridea, dc=com', port: 389, uid: 'sAMAccountName', bind_dn: 'bind_dn', password: 'password'})
24
+ adaptor.connection.should_not == nil
25
+ adaptor.connection.host.should == '192.168.1.145'
26
+ adaptor.connection.port.should == 389
27
+ adaptor.connection.base.should == 'dc=intridea, dc=com'
28
+ adaptor.connection.instance_variable_get('@auth').should == {:method => :simple, :username => 'bind_dn', :password => 'password'}
29
+ end
30
+ it 'should setup ldap connection with sasl-md5' do
31
+ adaptor = OmniAuth::LDAP::Adaptor.new({host: "192.168.1.145", method: 'plain', base: 'dc=intridea, dc=com', port: 389, uid: 'sAMAccountName', try_sasl: true, sasl_mechanisms: ["DIGEST-MD5"], bind_dn: 'bind_dn', password: 'password'})
32
+ adaptor.connection.should_not == nil
33
+ adaptor.connection.host.should == '192.168.1.145'
34
+ adaptor.connection.port.should == 389
35
+ adaptor.connection.base.should == 'dc=intridea, dc=com'
36
+ adaptor.connection.instance_variable_get('@auth')[:method].should == :sasl
37
+ adaptor.connection.instance_variable_get('@auth')[:mechanism].should == 'DIGEST-MD5'
38
+ adaptor.connection.instance_variable_get('@auth')[:initial_credential].should == ''
39
+ adaptor.connection.instance_variable_get('@auth')[:challenge_response].should_not be_nil
40
+ end
41
+ it 'should setup ldap connection with sasl-gss' do
42
+ adaptor = OmniAuth::LDAP::Adaptor.new({host: "192.168.1.145", method: 'plain', base: 'dc=intridea, dc=com', port: 389, uid: 'sAMAccountName', try_sasl: true, sasl_mechanisms: ["GSS-SPNEGO"], bind_dn: 'bind_dn', password: 'password'})
43
+ adaptor.connection.should_not == nil
44
+ adaptor.connection.host.should == '192.168.1.145'
45
+ adaptor.connection.port.should == 389
46
+ adaptor.connection.base.should == 'dc=intridea, dc=com'
47
+ adaptor.connection.instance_variable_get('@auth')[:method].should == :sasl
48
+ adaptor.connection.instance_variable_get('@auth')[:mechanism].should == 'GSS-SPNEGO'
49
+ adaptor.connection.instance_variable_get('@auth')[:initial_credential].should =~ /^NTLMSSP/
50
+ adaptor.connection.instance_variable_get('@auth')[:challenge_response].should_not be_nil
51
+ end
52
+ end
53
+
54
+ describe 'bind_as' do
55
+ let(:args) { {:filter => Net::LDAP::Filter.eq('sAMAccountName', 'username'), :password => 'password', :size => 1} }
56
+ let(:rs) { Struct.new(:dn).new('new dn') }
57
+ it 'should bind simple' do
58
+ adaptor = OmniAuth::LDAP::Adaptor.new({host: "192.168.1.126", method: 'plain', base: 'dc=score, dc=local', port: 389, uid: 'sAMAccountName', bind_dn: 'bind_dn', password: 'password'})
59
+ adaptor.connection.should_receive(:open).and_yield(adaptor.connection)
60
+ adaptor.connection.should_receive(:search).with(args).and_return([rs])
61
+ adaptor.connection.should_receive(:bind).with({:username => 'new dn', :password => args[:password], :method => :simple}).and_return(true)
62
+ adaptor.bind_as(args).should == rs
63
+ end
64
+ it 'should bind sasl' do
65
+ adaptor = OmniAuth::LDAP::Adaptor.new({host: "192.168.1.145", method: 'plain', base: 'dc=intridea, dc=com', port: 389, uid: 'sAMAccountName', try_sasl: true, sasl_mechanisms: ["GSS-SPNEGO"], bind_dn: 'bind_dn', password: 'password'})
66
+ adaptor.connection.should_receive(:open).and_yield(adaptor.connection)
67
+ adaptor.connection.should_receive(:search).with(args).and_return([rs])
68
+ adaptor.connection.should_receive(:bind).and_return(true)
69
+ adaptor.bind_as(args).should == rs
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,104 @@
1
+ require 'spec_helper'
2
+ describe "OmniAuth::Strategies::LDAP" do
3
+ # :title => "My LDAP",
4
+ # :host => '10.101.10.1',
5
+ # :port => 389,
6
+ # :method => :plain,
7
+ # :base => 'dc=intridea, dc=com',
8
+ # :uid => 'sAMAccountName',
9
+ # :name_proc => Proc.new {|name| name.gsub(/@.*$/,'')}
10
+ # :bind_dn => 'default_bind_dn'
11
+ # :password => 'password'
12
+ class MyLdapProvider < OmniAuth::Strategies::LDAP; end
13
+ def app
14
+ Rack::Builder.new {
15
+ use OmniAuth::Test::PhonySession
16
+ use MyLdapProvider, :name => 'ldap', :title => 'MyLdap Form', :host => '192.168.1.145', :base => 'dc=score, dc=local', :name_proc => Proc.new {|name| name.gsub(/@.*$/,'')}
17
+ run lambda { |env| [404, {'Content-Type' => 'text/plain'}, [env.key?('omniauth.auth').to_s]] }
18
+ }.to_app
19
+ end
20
+
21
+ def session
22
+ last_request.env['rack.session']
23
+ end
24
+
25
+ it 'should add a camelization for itself' do
26
+ OmniAuth::Utils.camelize('ldap').should == 'LDAP'
27
+ end
28
+
29
+ describe '/auth/ldap' do
30
+ before(:each){ get '/auth/ldap' }
31
+
32
+ it 'should display a form' do
33
+ last_response.status.should == 200
34
+ last_response.body.should be_include("<form")
35
+ end
36
+
37
+ it 'should have the callback as the action for the form' do
38
+ last_response.body.should be_include("action='/auth/ldap/callback'")
39
+ end
40
+
41
+ it 'should have a text field for each of the fields' do
42
+ last_response.body.scan('<input').size.should == 2
43
+ end
44
+ it 'should have a label of the form title' do
45
+ last_response.body.scan('MyLdap Form').size.should > 1
46
+ end
47
+
48
+ end
49
+
50
+ describe 'post /auth/ldap/callback' do
51
+ before(:each) do
52
+ @adaptor = mock(OmniAuth::LDAP::Adaptor, {:uid => 'ping'})
53
+ OmniAuth::LDAP::Adaptor.stub(:new).and_return(@adaptor)
54
+ end
55
+ context 'failure' do
56
+ before(:each) do
57
+ @adaptor.stub(:bind_as).and_return(false)
58
+ end
59
+ it 'should raise MissingCredentialsError' do
60
+ lambda{post('/auth/ldap/callback', {})}.should raise_error OmniAuth::Strategies::LDAP::MissingCredentialsError
61
+ end
62
+ it 'should redirect to error page' do
63
+ post('/auth/ldap/callback', {:username => 'ping', :password => 'password'})
64
+ last_response.should be_redirect
65
+ last_response.headers['Location'].should =~ %r{invalid_credentials}
66
+ end
67
+ it 'should redirect to error page when there is exception' do
68
+ @adaptor.stub(:bind_as).and_throw(Exception.new('connection_error'))
69
+ post('/auth/ldap/callback', {:username => 'ping', :password => 'password'})
70
+ last_response.should be_redirect
71
+ last_response.headers['Location'].should =~ %r{ldap_error}
72
+ end
73
+ end
74
+
75
+ context 'success' do
76
+ let(:auth_hash){ last_request.env['omniauth.auth'] }
77
+ before(:each) do
78
+ @adaptor.stub(:bind_as).and_return({:dn => ['cn=ping, dc=intridea, dc=com'], :mail => ['ping@intridea.com'], :givenname => ['Ping'], :sn => ['Yu'],
79
+ :telephonenumber => ['555-555-5555'], :mobile => ['444-444-4444'], :uid => ['ping'], :title => ['dev'], :address =>[ 'k street'],
80
+ :l => ['Washington'], :st => ['DC'], :co => ["U.S.A"], :postofficebox => ['20001'], :wwwhomepage => ['www.intridea.com'],
81
+ :jpegphoto => ['http://www.intridea.com/ping.jpg'], :description => ['omniauth-ldap']})
82
+ post('/auth/ldap/callback', {:username => 'ping', :password => 'password'})
83
+ end
84
+
85
+ it 'should raise MissingCredentialsError' do
86
+ should_not raise_error OmniAuth::Strategies::LDAP::MissingCredentialsError
87
+ end
88
+ it 'should map user info' do
89
+ auth_hash.uid.should == 'cn=ping, dc=intridea, dc=com'
90
+ auth_hash.info.email.should == 'ping@intridea.com'
91
+ auth_hash.info.first_name.should == 'Ping'
92
+ auth_hash.info.last_name.should == 'Yu'
93
+ auth_hash.info.phone.should == '555-555-5555'
94
+ auth_hash.info.mobile.should == '444-444-4444'
95
+ auth_hash.info.nickname.should == 'ping'
96
+ auth_hash.info.title.should == 'dev'
97
+ auth_hash.info.location.should == 'k street, Washington, DC, U.S.A 20001'
98
+ auth_hash.info.url.should == 'www.intridea.com'
99
+ auth_hash.info.image.should == 'http://www.intridea.com/ping.jpg'
100
+ auth_hash.info.description.should == 'omniauth-ldap'
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,14 @@
1
+ $:.unshift File.expand_path('..', __FILE__)
2
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
+ require 'simplecov'
4
+ SimpleCov.start
5
+ require 'rspec'
6
+ require 'rack/test'
7
+ require 'omniauth'
8
+ require 'omniauth-ldap'
9
+
10
+ RSpec.configure do |config|
11
+ config.include Rack::Test::Methods
12
+ config.extend OmniAuth::Test::StrategyMacros, :type => :strategy
13
+ end
14
+
metadata CHANGED
@@ -1,156 +1,162 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: omniauth-ldap
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.2
4
5
  prerelease:
5
- version: 1.0.1
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Ping Yu
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
-
13
- date: 2011-11-02 00:00:00 -05:00
14
- default_executable:
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
12
+ date: 2011-12-17 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
17
15
  name: omniauth
18
- prerelease: false
19
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &70232010172840 !ruby/object:Gem::Requirement
20
17
  none: false
21
- requirements:
18
+ requirements:
22
19
  - - ~>
23
- - !ruby/object:Gem::Version
24
- version: "1.0"
20
+ - !ruby/object:Gem::Version
21
+ version: '1.0'
25
22
  type: :runtime
26
- version_requirements: *id001
27
- - !ruby/object:Gem::Dependency
28
- name: net-ldap
29
23
  prerelease: false
30
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *70232010172840
25
+ - !ruby/object:Gem::Dependency
26
+ name: net-ldap
27
+ requirement: &70232010172340 !ruby/object:Gem::Requirement
31
28
  none: false
32
- requirements:
29
+ requirements:
33
30
  - - ~>
34
- - !ruby/object:Gem::Version
31
+ - !ruby/object:Gem::Version
35
32
  version: 0.2.2
36
33
  type: :runtime
37
- version_requirements: *id002
38
- - !ruby/object:Gem::Dependency
39
- name: pyu-ruby-sasl
40
34
  prerelease: false
41
- requirement: &id003 !ruby/object:Gem::Requirement
35
+ version_requirements: *70232010172340
36
+ - !ruby/object:Gem::Dependency
37
+ name: pyu-ruby-sasl
38
+ requirement: &70232010171880 !ruby/object:Gem::Requirement
42
39
  none: false
43
- requirements:
40
+ requirements:
44
41
  - - ~>
45
- - !ruby/object:Gem::Version
42
+ - !ruby/object:Gem::Version
46
43
  version: 0.0.3.1
47
44
  type: :runtime
48
- version_requirements: *id003
49
- - !ruby/object:Gem::Dependency
50
- name: rubyntlm
51
45
  prerelease: false
52
- requirement: &id004 !ruby/object:Gem::Requirement
46
+ version_requirements: *70232010171880
47
+ - !ruby/object:Gem::Dependency
48
+ name: rubyntlm
49
+ requirement: &70232010171420 !ruby/object:Gem::Requirement
53
50
  none: false
54
- requirements:
51
+ requirements:
55
52
  - - ~>
56
- - !ruby/object:Gem::Version
53
+ - !ruby/object:Gem::Version
57
54
  version: 0.1.1
58
55
  type: :runtime
59
- version_requirements: *id004
60
- - !ruby/object:Gem::Dependency
61
- name: rspec
62
56
  prerelease: false
63
- requirement: &id005 !ruby/object:Gem::Requirement
57
+ version_requirements: *70232010171420
58
+ - !ruby/object:Gem::Dependency
59
+ name: rspec
60
+ requirement: &70232010170960 !ruby/object:Gem::Requirement
64
61
  none: false
65
- requirements:
62
+ requirements:
66
63
  - - ~>
67
- - !ruby/object:Gem::Version
68
- version: "2.7"
64
+ - !ruby/object:Gem::Version
65
+ version: '2.7'
69
66
  type: :development
70
- version_requirements: *id005
71
- - !ruby/object:Gem::Dependency
72
- name: simplecov
73
67
  prerelease: false
74
- requirement: &id006 !ruby/object:Gem::Requirement
68
+ version_requirements: *70232010170960
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: &70232010170580 !ruby/object:Gem::Requirement
75
72
  none: false
76
- requirements:
77
- - - ">="
78
- - !ruby/object:Gem::Version
79
- version: "0"
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
80
77
  type: :development
81
- version_requirements: *id006
82
- - !ruby/object:Gem::Dependency
83
- name: rack-test
84
78
  prerelease: false
85
- requirement: &id007 !ruby/object:Gem::Requirement
79
+ version_requirements: *70232010170580
80
+ - !ruby/object:Gem::Dependency
81
+ name: rack-test
82
+ requirement: &70232010170120 !ruby/object:Gem::Requirement
86
83
  none: false
87
- requirements:
88
- - - ">="
89
- - !ruby/object:Gem::Version
90
- version: "0"
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
91
88
  type: :development
92
- version_requirements: *id007
93
- - !ruby/object:Gem::Dependency
94
- name: libnotify
95
89
  prerelease: false
96
- requirement: &id008 !ruby/object:Gem::Requirement
90
+ version_requirements: *70232010170120
91
+ - !ruby/object:Gem::Dependency
92
+ name: libnotify
93
+ requirement: &70232010169700 !ruby/object:Gem::Requirement
97
94
  none: false
98
- requirements:
99
- - - ">="
100
- - !ruby/object:Gem::Version
101
- version: "0"
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
102
99
  type: :development
103
- version_requirements: *id008
104
- - !ruby/object:Gem::Dependency
105
- name: ruby-debug19
106
100
  prerelease: false
107
- requirement: &id009 !ruby/object:Gem::Requirement
101
+ version_requirements: *70232010169700
102
+ - !ruby/object:Gem::Dependency
103
+ name: ruby-debug19
104
+ requirement: &70232010169280 !ruby/object:Gem::Requirement
108
105
  none: false
109
- requirements:
110
- - - ">="
111
- - !ruby/object:Gem::Version
112
- version: "0"
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
113
110
  type: :development
114
- version_requirements: *id009
111
+ prerelease: false
112
+ version_requirements: *70232010169280
115
113
  description: A LDAP strategy for OmniAuth.
116
- email:
114
+ email:
117
115
  - ping@intridea.com
118
116
  executables: []
119
-
120
117
  extensions: []
121
-
122
118
  extra_rdoc_files: []
123
-
124
- files:
125
- - omniauth-ldap-1.0.0.rc1.gem
126
- - omniauth-ldap-1.0.0.rc2.gem
127
- has_rdoc: true
119
+ files:
120
+ - .gitignore
121
+ - .rspec
122
+ - Gemfile
123
+ - Gemfile.lock
124
+ - Guardfile
125
+ - README.md
126
+ - Rakefile
127
+ - lib/omniauth-ldap.rb
128
+ - lib/omniauth-ldap/adaptor.rb
129
+ - lib/omniauth-ldap/version.rb
130
+ - lib/omniauth/strategies/ldap.rb
131
+ - omniauth-ldap.gemspec
132
+ - spec/omniauth-ldap/adaptor_spec.rb
133
+ - spec/omniauth/strategies/ldap_spec.rb
134
+ - spec/spec_helper.rb
128
135
  homepage: https://github.com/intridea/omniauth-ldap
129
136
  licenses: []
130
-
131
137
  post_install_message:
132
138
  rdoc_options: []
133
-
134
- require_paths:
139
+ require_paths:
135
140
  - lib
136
- required_ruby_version: !ruby/object:Gem::Requirement
141
+ required_ruby_version: !ruby/object:Gem::Requirement
137
142
  none: false
138
- requirements:
139
- - - ">="
140
- - !ruby/object:Gem::Version
141
- version: "0"
142
- required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ! '>='
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
148
  none: false
144
- requirements:
145
- - - ">="
146
- - !ruby/object:Gem::Version
147
- version: "0"
149
+ requirements:
150
+ - - ! '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
148
153
  requirements: []
149
-
150
154
  rubyforge_project:
151
- rubygems_version: 1.6.2
155
+ rubygems_version: 1.8.10
152
156
  signing_key:
153
157
  specification_version: 3
154
158
  summary: A LDAP strategy for OmniAuth.
155
- test_files: []
156
-
159
+ test_files:
160
+ - spec/omniauth-ldap/adaptor_spec.rb
161
+ - spec/omniauth/strategies/ldap_spec.rb
162
+ - spec/spec_helper.rb
Binary file
Binary file