oa-enterprise 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +22 -2
- data/lib/omniauth/enterprise.rb +1 -0
- data/lib/omniauth/strategies/ldap.rb +94 -0
- data/lib/omniauth/strategies/ldap/adaptor.rb +293 -0
- metadata +53 -18
data/README.rdoc
CHANGED
@@ -11,7 +11,8 @@ To get just enterprise functionality:
|
|
11
11
|
For the full auth suite:
|
12
12
|
|
13
13
|
gem install omniauth
|
14
|
-
|
14
|
+
|
15
|
+
CAS strategy
|
15
16
|
== Stand-Alone Example
|
16
17
|
|
17
18
|
Use the strategy as a middleware in your application:
|
@@ -22,7 +23,9 @@ Use the strategy as a middleware in your application:
|
|
22
23
|
|
23
24
|
Then simply direct users to '/auth/cas' to have them sign in via your company's CAS server.
|
24
25
|
See OmniAuth::Strategies::CAS::Configuration for more configuration options.
|
25
|
-
|
26
|
+
|
27
|
+
Then simply direct users to '/auth/cas' to have them sign in via your company's CAS server.
|
28
|
+
See OmniAuth::Strategies::CAS::Configuration for more configuration options.
|
26
29
|
|
27
30
|
== OmniAuth Builder
|
28
31
|
|
@@ -36,3 +39,20 @@ If CAS is one of several authentication strategies, use the OmniAuth Builder:
|
|
36
39
|
provider :cas, :server => 'http://cas.mycompany.com/cas'
|
37
40
|
provider :campfire
|
38
41
|
end
|
42
|
+
|
43
|
+
LDAP strategy
|
44
|
+
|
45
|
+
use OmniAuth::Strategies::LDAP, :host => '10.101.10.1', :port => 389, :method => :plain, :base => 'dc=intridea, dc=com', :uid => 'sAMAccountName', :try_sasl => true, :sasl_mechanisms => "GSS-SPNEGO"
|
46
|
+
or
|
47
|
+
use OmniAuth::Builder do
|
48
|
+
provider :LDAP, :host => '10.101.10.1', :port => 389, :method => :plain, :base => 'dc=intridea, dc=com', :uid => 'sAMAccountName', :try_sasl => true, :sasl_mechanisms => "GSS-SPNEGO"
|
49
|
+
end
|
50
|
+
|
51
|
+
LDAP server's :host and :port are required, :method is also a required field, and allowed values are :plain, :ssl, and :tls.
|
52
|
+
:base is required, it is the distinguish name (DN) for your organization, all users should be searchable under this base.
|
53
|
+
:uid is required, it is the LDAP attribute name for the user name in the login form. typically AD would be 'sAMAccountName' or 'UniquePersonalIdentifier', while
|
54
|
+
OpenLDAP is 'uid'. You can also use 'dn', if your user choose the put in the dn in the login form (but usually is too long for user to remember or know).
|
55
|
+
:try_sasl and :sasl_mechanisms are optional, use it to initial SASL connection to server. mechanism supported are DIGEST-MD5 and GSS-SPNEGO.
|
56
|
+
|
57
|
+
Then simply direct users to '/auth/ldap' to have them authenticated via your company's LDAP server.
|
58
|
+
|
data/lib/omniauth/enterprise.rb
CHANGED
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'omniauth/enterprise'
|
2
|
+
require 'net/ldap'
|
3
|
+
|
4
|
+
module OmniAuth
|
5
|
+
module Strategies
|
6
|
+
class LDAP
|
7
|
+
include OmniAuth::Strategy
|
8
|
+
|
9
|
+
autoload :Adaptor, 'omniauth/strategies/ldap/adaptor'
|
10
|
+
@@config = {'first_name' => 'givenName', 'last_name' => 'sn', 'email' => ['mail', "email", 'userPrincipalName'],
|
11
|
+
'phone' => ['telephoneNumber', 'homePhone', 'facsimileTelephoneNumber'],
|
12
|
+
'mobile_number' => ['mobile', 'mobileTelephoneNumber'],
|
13
|
+
'nickname' => ['uid', 'userid', 'sAMAccountName'],
|
14
|
+
'title' => 'title',
|
15
|
+
'location' => {"%0, %1, %2, %3 %4" => [['address', 'postalAddress', 'homePostalAddress', 'street', 'streetAddress'], ['l'], ['st'],['co'],['postOfficeBox']]},
|
16
|
+
'uid' => 'dn',
|
17
|
+
'url' => ['wwwhomepage'],
|
18
|
+
'image' => 'jpegPhoto',
|
19
|
+
'description' => 'description'}
|
20
|
+
def initialize(app, title, options = {})
|
21
|
+
super(app, options.delete(:name) || :ldap)
|
22
|
+
@title = title
|
23
|
+
@adaptor = OmniAuth::Strategies::LDAP::Adaptor.new(options)
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def request_phase
|
29
|
+
if env['REQUEST_METHOD'] == 'GET'
|
30
|
+
get_credentials
|
31
|
+
else
|
32
|
+
perform
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_credentials
|
37
|
+
OmniAuth::Form.build(@title) do
|
38
|
+
text_field 'Login', 'username'
|
39
|
+
password_field 'Password', 'password'
|
40
|
+
end.to_response
|
41
|
+
end
|
42
|
+
def perform
|
43
|
+
begin
|
44
|
+
@adaptor.bind(:bind_dn => request.POST['username'], :password => request.POST['password'])
|
45
|
+
@ldap_user_info = @adaptor.search(:filter => Net::LDAP::Filter.eq(@adaptor.uid, request.POST['username']),:limit => 1)
|
46
|
+
@user_info = self.class.map_user(@@config, @ldap_user_info)
|
47
|
+
request.POST['auth'] = auth_hash
|
48
|
+
@env['REQUEST_METHOD'] = 'GET'
|
49
|
+
@env['PATH_INFO'] = "#{OmniAuth.config.path_prefix}/#{name}/callback"
|
50
|
+
|
51
|
+
@app.call(@env)
|
52
|
+
rescue Exception => e
|
53
|
+
puts e.message
|
54
|
+
fail!(:invalid_credentials)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def callback_phase
|
59
|
+
fail!(:invalid_request)
|
60
|
+
end
|
61
|
+
|
62
|
+
def auth_hash
|
63
|
+
OmniAuth::Utils.deep_merge(super, {
|
64
|
+
'uid' => @user_info["uid"],
|
65
|
+
'user_info' => @user_info,
|
66
|
+
'extra' => @ldap_user_info
|
67
|
+
})
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.map_user mapper, object
|
71
|
+
user = {}
|
72
|
+
mapper.each do |key, value|
|
73
|
+
case value
|
74
|
+
when String
|
75
|
+
user[key] = object[value.downcase.to_sym].to_s if object[value.downcase.to_sym]
|
76
|
+
when Array
|
77
|
+
value.each {|v| (user[key] = object[v.downcase.to_sym].to_s; break;) if object[v.downcase.to_sym]}
|
78
|
+
when Hash
|
79
|
+
value.map do |key1, value1|
|
80
|
+
pattern = key1.dup
|
81
|
+
value1.each_with_index do |v,i|
|
82
|
+
part = '';
|
83
|
+
v.each {|v1| (part = object[v1.downcase.to_sym].to_s; break;) if object[v1.downcase.to_sym]}
|
84
|
+
pattern.gsub!("%#{i}",part||'')
|
85
|
+
end
|
86
|
+
user[key] = pattern
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
user
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,293 @@
|
|
1
|
+
#this code boughts pieces from activeldap and net-ldap
|
2
|
+
require 'rack'
|
3
|
+
require 'net/ldap'
|
4
|
+
require 'net/ntlm'
|
5
|
+
require 'uri'
|
6
|
+
module OmniAuth
|
7
|
+
module Strategies
|
8
|
+
class LDAP
|
9
|
+
class Adaptor
|
10
|
+
class LdapError < StandardError; end
|
11
|
+
class ConfigurationError < StandardError; end
|
12
|
+
class AuthenticationError < StandardError; end
|
13
|
+
class ConnectionError < StandardError; end
|
14
|
+
VALID_ADAPTER_CONFIGURATION_KEYS = [:host, :port, :method, :bind_dn, :password,
|
15
|
+
:try_sasl, :sasl_mechanisms, :uid, :base]
|
16
|
+
MUST_HAVE_KEYS = [:host, :port, :method, :uid, :base]
|
17
|
+
METHOD = {
|
18
|
+
:ssl => :simple_tls,
|
19
|
+
:tls => :start_tls,
|
20
|
+
:plain => nil
|
21
|
+
}
|
22
|
+
attr_accessor :bind_dn, :password
|
23
|
+
attr_reader :connection, :uid, :base
|
24
|
+
def initialize(configuration={})
|
25
|
+
@connection = nil
|
26
|
+
@disconnected = false
|
27
|
+
@bound = false
|
28
|
+
@configuration = configuration.dup
|
29
|
+
@logger = @configuration.delete(:logger)
|
30
|
+
message = []
|
31
|
+
MUST_HAVE_KEYS.each do |name|
|
32
|
+
message << name if configuration[name].nil?
|
33
|
+
end
|
34
|
+
raise ArgumentError.new(message.join(",") +" MUST be provided") unless message.empty?
|
35
|
+
VALID_ADAPTER_CONFIGURATION_KEYS.each do |name|
|
36
|
+
instance_variable_set("@#{name}", configuration[name])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def connect(options={})
|
41
|
+
host = options[:host] || @host
|
42
|
+
method = options[:method] || @method || :plain
|
43
|
+
port = options[:port] || @port || ensure_port(method)
|
44
|
+
method = ensure_method(method)
|
45
|
+
@disconnected = false
|
46
|
+
@bound = false
|
47
|
+
@bind_tried = false
|
48
|
+
config = {
|
49
|
+
:host => host,
|
50
|
+
:port => port,
|
51
|
+
}
|
52
|
+
config[:encryption] = {:method => method} if method
|
53
|
+
@connection, @uri, @with_start_tls =
|
54
|
+
begin
|
55
|
+
uri = construct_uri(host, port, method == :simple_tls)
|
56
|
+
with_start_tls = method == :start_tls
|
57
|
+
puts ({:uri => uri, :with_start_tls => with_start_tls}).inspect
|
58
|
+
[Net::LDAP::Connection.new(config), uri, with_start_tls]
|
59
|
+
rescue Net::LDAP::LdapError
|
60
|
+
raise ConnectionError, $!.message
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def unbind(options={})
|
65
|
+
@connection.close # Net::LDAP doesn't implement unbind.
|
66
|
+
end
|
67
|
+
|
68
|
+
def bind(options={})
|
69
|
+
connect(options) unless connecting?
|
70
|
+
begin
|
71
|
+
@bind_tried = true
|
72
|
+
|
73
|
+
bind_dn = (options[:bind_dn] || @bind_dn).to_s
|
74
|
+
try_sasl = options.has_key?(:try_sasl) ? options[:try_sasl] : @try_sasl
|
75
|
+
|
76
|
+
# Rough bind loop:
|
77
|
+
# Attempt 1: SASL if available
|
78
|
+
# Attempt 2: SIMPLE with credentials if password block
|
79
|
+
if try_sasl and sasl_bind(bind_dn, options)
|
80
|
+
puts "bind with sasl"
|
81
|
+
elsif simple_bind(bind_dn, options)
|
82
|
+
puts "bind with simple"
|
83
|
+
else
|
84
|
+
message = yield if block_given?
|
85
|
+
message ||= ('All authentication methods for %s exhausted.') % target
|
86
|
+
raise AuthenticationError, message
|
87
|
+
end
|
88
|
+
|
89
|
+
@bound = true
|
90
|
+
rescue Net::LDAP::LdapError
|
91
|
+
raise AuthenticationError, $!.message
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def disconnect!(options={})
|
96
|
+
unbind(options)
|
97
|
+
@connection = @uri = @with_start_tls = nil
|
98
|
+
@disconnected = true
|
99
|
+
end
|
100
|
+
|
101
|
+
def rebind(options={})
|
102
|
+
unbind(options) if bound?
|
103
|
+
connect(options)
|
104
|
+
end
|
105
|
+
|
106
|
+
def connecting?
|
107
|
+
!@connection.nil? and !@disconnected
|
108
|
+
end
|
109
|
+
|
110
|
+
def bound?
|
111
|
+
connecting? and @bound
|
112
|
+
end
|
113
|
+
|
114
|
+
def search(options={}, &block)
|
115
|
+
base = options[:base]
|
116
|
+
filter = options[:filter]
|
117
|
+
limit = options[:limit]
|
118
|
+
|
119
|
+
args = {
|
120
|
+
:base => @base,
|
121
|
+
:filter => filter,
|
122
|
+
:size => limit
|
123
|
+
}
|
124
|
+
puts args.inspect
|
125
|
+
attributes = {}
|
126
|
+
execute(:search, args) do |entry|
|
127
|
+
entry.attribute_names.each do |name|
|
128
|
+
attributes[name] = entry[name]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
attributes
|
132
|
+
end
|
133
|
+
private
|
134
|
+
def execute(method, *args, &block)
|
135
|
+
result = @connection.send(method, *args, &block)
|
136
|
+
message = nil
|
137
|
+
if result.is_a?(Hash)
|
138
|
+
message = result[:errorMessage]
|
139
|
+
result = result[:resultCode]
|
140
|
+
end
|
141
|
+
unless result.zero?
|
142
|
+
message = [Net::LDAP.result2string(result), message].compact.join(": ")
|
143
|
+
raise LdapError, message
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def ensure_port(method)
|
148
|
+
if method == :ssl
|
149
|
+
URI::LDAPS::DEFAULT_PORT
|
150
|
+
else
|
151
|
+
URI::LDAP::DEFAULT_PORT
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def prepare_connection(options)
|
156
|
+
end
|
157
|
+
|
158
|
+
def ensure_method(method)
|
159
|
+
method ||= "plain"
|
160
|
+
normalized_method = method.to_s.downcase.to_sym
|
161
|
+
return METHOD[normalized_method] if METHOD.has_key?(normalized_method)
|
162
|
+
|
163
|
+
available_methods = METHOD.keys.collect {|m| m.inspect}.join(", ")
|
164
|
+
format = "%s is not one of the available connect methods: %s"
|
165
|
+
raise ConfigurationError, format % [method.inspect, available_methods]
|
166
|
+
end
|
167
|
+
|
168
|
+
def sasl_bind(bind_dn, options={})
|
169
|
+
sasl_mechanisms = options[:sasl_mechanisms] || @sasl_mechanisms
|
170
|
+
sasl_mechanisms.each do |mechanism|
|
171
|
+
begin
|
172
|
+
normalized_mechanism = mechanism.downcase.gsub(/-/, '_')
|
173
|
+
sasl_bind_setup = "sasl_bind_setup_#{normalized_mechanism}"
|
174
|
+
next unless respond_to?(sasl_bind_setup, true)
|
175
|
+
initial_credential, challenge_response =
|
176
|
+
send(sasl_bind_setup, bind_dn, options)
|
177
|
+
args = {
|
178
|
+
:method => :sasl,
|
179
|
+
:initial_credential => initial_credential,
|
180
|
+
:mechanism => mechanism,
|
181
|
+
:challenge_response => challenge_response,
|
182
|
+
}
|
183
|
+
info = {
|
184
|
+
:name => "bind: SASL", :dn => bind_dn, :mechanism => mechanism,
|
185
|
+
}
|
186
|
+
puts info.inspect
|
187
|
+
execute(:bind, args)
|
188
|
+
return true
|
189
|
+
rescue Exception => e
|
190
|
+
puts e.message
|
191
|
+
end
|
192
|
+
end
|
193
|
+
false
|
194
|
+
end
|
195
|
+
|
196
|
+
def parse_sasl_digest_md5_credential(cred)
|
197
|
+
params = {}
|
198
|
+
cred.scan(/(\w+)=(\"?)(.+?)\2(?:,|$)/) do |name, sep, value|
|
199
|
+
params[name] = value
|
200
|
+
end
|
201
|
+
params
|
202
|
+
end
|
203
|
+
CHARS = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
|
204
|
+
def generate_client_nonce(size=32)
|
205
|
+
nonce = ""
|
206
|
+
size.times do |i|
|
207
|
+
nonce << CHARS[rand(CHARS.size)]
|
208
|
+
end
|
209
|
+
nonce
|
210
|
+
end
|
211
|
+
def sasl_bind_setup_digest_md5(bind_dn, options)
|
212
|
+
initial_credential = ""
|
213
|
+
nonce_count = 1
|
214
|
+
challenge_response = Proc.new do |cred|
|
215
|
+
params = parse_sasl_digest_md5_credential(cred)
|
216
|
+
qops = params["qop"].split(/,/)
|
217
|
+
unless qops.include?("auth")
|
218
|
+
raise ActiveLdap::AuthenticationError,
|
219
|
+
_("unsupported qops: %s") % qops.inspect
|
220
|
+
end
|
221
|
+
qop = "auth"
|
222
|
+
server = @connection.instance_variable_get("@conn").addr[2]
|
223
|
+
realm = params['realm']
|
224
|
+
uri = "ldap/#{server}"
|
225
|
+
nc = "%08x" % nonce_count
|
226
|
+
nonce = params["nonce"]
|
227
|
+
cnonce = generate_client_nonce
|
228
|
+
requests = {
|
229
|
+
:username => bind_dn.inspect,
|
230
|
+
:realm => realm.inspect,
|
231
|
+
:nonce => nonce.inspect,
|
232
|
+
:cnonce => cnonce.inspect,
|
233
|
+
:nc => nc,
|
234
|
+
:qop => qop,
|
235
|
+
:maxbuf => "65536",
|
236
|
+
"digest-uri" => uri.inspect,
|
237
|
+
}
|
238
|
+
a1 = "#{bind_dn}:#{realm}:#{options[:password]||@password}"
|
239
|
+
a1 = "#{Digest::MD5.digest(a1)}:#{nonce}:#{cnonce}"
|
240
|
+
ha1 = Digest::MD5.hexdigest(a1)
|
241
|
+
a2 = "AUTHENTICATE:#{uri}"
|
242
|
+
ha2 = Digest::MD5.hexdigest(a2)
|
243
|
+
response = "#{ha1}:#{nonce}:#{nc}:#{cnonce}:#{qop}:#{ha2}"
|
244
|
+
requests["response"] = Digest::MD5.hexdigest(response)
|
245
|
+
nonce_count += 1
|
246
|
+
requests.collect do |key, value|
|
247
|
+
"#{key}=#{value}"
|
248
|
+
end.join(",")
|
249
|
+
end
|
250
|
+
[initial_credential, challenge_response]
|
251
|
+
end
|
252
|
+
def sasl_bind_setup_gss_spnego(bind_dn, options)
|
253
|
+
puts options.inspect
|
254
|
+
user,psw = [bind_dn, options[:password]||@password]
|
255
|
+
raise LdapError.new( "invalid binding information" ) unless (user && psw)
|
256
|
+
|
257
|
+
nego = proc {|challenge|
|
258
|
+
t2_msg = Net::NTLM::Message.parse( challenge )
|
259
|
+
user, domain = user.split('\\').reverse
|
260
|
+
t2_msg.target_name = Net::NTLM::encode_utf16le(domain) if domain
|
261
|
+
t3_msg = t2_msg.response( {:user => user, :password => psw}, {:ntlmv2 => true} )
|
262
|
+
t3_msg.serialize
|
263
|
+
}
|
264
|
+
[Net::NTLM::Message::Type1.new.serialize, nego]
|
265
|
+
end
|
266
|
+
|
267
|
+
def simple_bind(bind_dn, options={})
|
268
|
+
args = {
|
269
|
+
:method => :simple,
|
270
|
+
:username => bind_dn,
|
271
|
+
:password => options[:password]||@password,
|
272
|
+
}
|
273
|
+
execute(:bind, args)
|
274
|
+
true
|
275
|
+
end
|
276
|
+
|
277
|
+
def construct_uri(host, port, ssl)
|
278
|
+
protocol = ssl ? "ldaps" : "ldap"
|
279
|
+
URI.parse("#{protocol}://#{host}:#{port}").to_s
|
280
|
+
end
|
281
|
+
|
282
|
+
def target
|
283
|
+
return nil if @uri.nil?
|
284
|
+
if @with_start_tls
|
285
|
+
"#{@uri}(StartTLS)"
|
286
|
+
else
|
287
|
+
@uri
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
metadata
CHANGED
@@ -1,21 +1,22 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oa-enterprise
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- James A. Rosen
|
14
|
+
- Ping Yu
|
14
15
|
autorequire:
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
18
|
|
18
|
-
date: 2010-10-
|
19
|
+
date: 2010-10-04 00:00:00 -05:00
|
19
20
|
default_executable:
|
20
21
|
dependencies:
|
21
22
|
- !ruby/object:Gem::Dependency
|
@@ -24,12 +25,12 @@ dependencies:
|
|
24
25
|
requirements:
|
25
26
|
- - "="
|
26
27
|
- !ruby/object:Gem::Version
|
27
|
-
hash:
|
28
|
+
hash: 25
|
28
29
|
segments:
|
29
30
|
- 0
|
30
31
|
- 1
|
31
|
-
-
|
32
|
-
version: 0.1.
|
32
|
+
- 1
|
33
|
+
version: 0.1.1
|
33
34
|
requirement: *id001
|
34
35
|
name: oa-core
|
35
36
|
prerelease: false
|
@@ -52,6 +53,38 @@ dependencies:
|
|
52
53
|
type: :runtime
|
53
54
|
- !ruby/object:Gem::Dependency
|
54
55
|
version_requirements: &id003 !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ~>
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 25
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
- 1
|
64
|
+
- 1
|
65
|
+
version: 0.1.1
|
66
|
+
requirement: *id003
|
67
|
+
name: net-ldap
|
68
|
+
prerelease: false
|
69
|
+
type: :runtime
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
hash: 25
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
- 1
|
80
|
+
- 1
|
81
|
+
version: 0.1.1
|
82
|
+
requirement: *id004
|
83
|
+
name: rubyntlm
|
84
|
+
prerelease: false
|
85
|
+
type: :runtime
|
86
|
+
- !ruby/object:Gem::Dependency
|
87
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
55
88
|
none: false
|
56
89
|
requirements:
|
57
90
|
- - ">="
|
@@ -60,12 +93,12 @@ dependencies:
|
|
60
93
|
segments:
|
61
94
|
- 0
|
62
95
|
version: "0"
|
63
|
-
requirement: *
|
96
|
+
requirement: *id005
|
64
97
|
name: rake
|
65
98
|
prerelease: false
|
66
99
|
type: :development
|
67
100
|
- !ruby/object:Gem::Dependency
|
68
|
-
version_requirements: &
|
101
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
69
102
|
none: false
|
70
103
|
requirements:
|
71
104
|
- - ~>
|
@@ -76,12 +109,12 @@ dependencies:
|
|
76
109
|
- 0
|
77
110
|
- 8
|
78
111
|
version: 0.0.8
|
79
|
-
requirement: *
|
112
|
+
requirement: *id006
|
80
113
|
name: mg
|
81
114
|
prerelease: false
|
82
115
|
type: :development
|
83
116
|
- !ruby/object:Gem::Dependency
|
84
|
-
version_requirements: &
|
117
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
85
118
|
none: false
|
86
119
|
requirements:
|
87
120
|
- - ~>
|
@@ -92,12 +125,12 @@ dependencies:
|
|
92
125
|
- 3
|
93
126
|
- 0
|
94
127
|
version: 1.3.0
|
95
|
-
requirement: *
|
128
|
+
requirement: *id007
|
96
129
|
name: rspec
|
97
130
|
prerelease: false
|
98
131
|
type: :development
|
99
132
|
- !ruby/object:Gem::Dependency
|
100
|
-
version_requirements: &
|
133
|
+
version_requirements: &id008 !ruby/object:Gem::Requirement
|
101
134
|
none: false
|
102
135
|
requirements:
|
103
136
|
- - ~>
|
@@ -108,12 +141,12 @@ dependencies:
|
|
108
141
|
- 3
|
109
142
|
- 4
|
110
143
|
version: 1.3.4
|
111
|
-
requirement: *
|
144
|
+
requirement: *id008
|
112
145
|
name: webmock
|
113
146
|
prerelease: false
|
114
147
|
type: :development
|
115
148
|
- !ruby/object:Gem::Dependency
|
116
|
-
version_requirements: &
|
149
|
+
version_requirements: &id009 !ruby/object:Gem::Requirement
|
117
150
|
none: false
|
118
151
|
requirements:
|
119
152
|
- - ~>
|
@@ -124,12 +157,12 @@ dependencies:
|
|
124
157
|
- 5
|
125
158
|
- 4
|
126
159
|
version: 0.5.4
|
127
|
-
requirement: *
|
160
|
+
requirement: *id009
|
128
161
|
name: rack-test
|
129
162
|
prerelease: false
|
130
163
|
type: :development
|
131
164
|
- !ruby/object:Gem::Dependency
|
132
|
-
version_requirements: &
|
165
|
+
version_requirements: &id010 !ruby/object:Gem::Requirement
|
133
166
|
none: false
|
134
167
|
requirements:
|
135
168
|
- - ~>
|
@@ -140,7 +173,7 @@ dependencies:
|
|
140
173
|
- 4
|
141
174
|
- 3
|
142
175
|
version: 1.4.3
|
143
|
-
requirement: *
|
176
|
+
requirement: *id010
|
144
177
|
name: json
|
145
178
|
prerelease: false
|
146
179
|
type: :development
|
@@ -157,6 +190,8 @@ files:
|
|
157
190
|
- lib/omniauth/strategies/cas/configuration.rb
|
158
191
|
- lib/omniauth/strategies/cas/service_ticket_validator.rb
|
159
192
|
- lib/omniauth/strategies/cas.rb
|
193
|
+
- lib/omniauth/strategies/ldap/adaptor.rb
|
194
|
+
- lib/omniauth/strategies/ldap.rb
|
160
195
|
- README.rdoc
|
161
196
|
- LICENSE.rdoc
|
162
197
|
- CHANGELOG.rdoc
|