adauth 0.0.1pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +5 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +26 -0
- data/Rakefile +2 -0
- data/Readme.rdoc +64 -0
- data/adauth.gemspec +21 -0
- data/lib/adauth.rb +26 -0
- data/lib/adauth/config.rb +10 -0
- data/lib/adauth/helpers.rb +21 -0
- data/lib/adauth/user.rb +85 -0
- data/lib/adauth/user_model.rb +25 -0
- data/lib/adauth/version.rb +3 -0
- data/lib/generators/adauth/user_model/USAGE +14 -0
- data/lib/generators/adauth/user_model/templates/migration.rb.erb +14 -0
- data/lib/generators/adauth/user_model/templates/model.rb.erb +3 -0
- data/lib/generators/adauth/user_model/user_model_generator.rb +24 -0
- data/spec/adauth_spec.rb +92 -0
- metadata +114 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
adauth (0.0.1pre)
|
5
|
+
ruby-net-ldap
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
diff-lcs (1.1.2)
|
11
|
+
rspec (2.6.0)
|
12
|
+
rspec-core (~> 2.6.0)
|
13
|
+
rspec-expectations (~> 2.6.0)
|
14
|
+
rspec-mocks (~> 2.6.0)
|
15
|
+
rspec-core (2.6.1)
|
16
|
+
rspec-expectations (2.6.0)
|
17
|
+
diff-lcs (~> 1.1.2)
|
18
|
+
rspec-mocks (2.6.0)
|
19
|
+
ruby-net-ldap (0.0.4)
|
20
|
+
|
21
|
+
PLATFORMS
|
22
|
+
ruby
|
23
|
+
|
24
|
+
DEPENDENCIES
|
25
|
+
adauth!
|
26
|
+
rspec
|
data/Rakefile
ADDED
data/Readme.rdoc
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
= {Adauth}[http://adauth.arcath.net/]
|
2
|
+
|
3
|
+
Easy to use Active Directory Authentication for Rails.
|
4
|
+
|
5
|
+
== Install
|
6
|
+
|
7
|
+
Add the Adauth gem to your Gemfile:
|
8
|
+
|
9
|
+
gem 'adauth'
|
10
|
+
|
11
|
+
and run a bundle install
|
12
|
+
|
13
|
+
== Usage
|
14
|
+
|
15
|
+
Create an initializer in _config/initilaizers_ called adauth.rb and place this code in it:
|
16
|
+
|
17
|
+
Adauth.configure do |c|
|
18
|
+
c.domain = "example.com" #The domain name used on your network e.g. example.com or example.local
|
19
|
+
c.server = "127.0.0.1" #The IP of any DC on your network
|
20
|
+
c.base = "dc=example, dc=com" #the base for your users.
|
21
|
+
end
|
22
|
+
|
23
|
+
c.port can also be used but defaults to 389 which is the default for AD/LDAP. For a full list of options see {Configuration}[...] on the wiki.
|
24
|
+
|
25
|
+
Thats enough to very basically run Adauth, and if you prefer complete control over how your authentication is handled you can use this method:
|
26
|
+
|
27
|
+
Adauth.authenticate(username, password)
|
28
|
+
|
29
|
+
Which has 2 possible return values nil if the users details are wrong or an instance of Adauth::User if the details are correct.
|
30
|
+
|
31
|
+
Adauth provides generators and helper methods for getting your application up and running.
|
32
|
+
|
33
|
+
== Developing
|
34
|
+
|
35
|
+
Obviously to test the AD functionality Adauth requires a working domain and a user to try logging in with. If you try running the tests without first creating the test_data.yml file then they will fail with this error:
|
36
|
+
|
37
|
+
Failure/Error: @yaml = YAML::load(File.open('spec/test_data.yml'))
|
38
|
+
|
39
|
+
You need to create a yaml file that looks like this:
|
40
|
+
|
41
|
+
domain:
|
42
|
+
domain: example.com
|
43
|
+
server: 127.0.0.1
|
44
|
+
port: 389
|
45
|
+
base: "dc=example, dc=com"
|
46
|
+
pass_allowed_groups:
|
47
|
+
- group
|
48
|
+
fail_allowed_groups:
|
49
|
+
- no_group
|
50
|
+
|
51
|
+
user:
|
52
|
+
login: username
|
53
|
+
password: password
|
54
|
+
group: group
|
55
|
+
|
56
|
+
The domain portion of this file is pretty self explanatory, they are the same as the code above for creating a domain connection. ALL options need to be set here.
|
57
|
+
|
58
|
+
The pass and fail allowed groups need to be an array with pass containing a group that the test user is a member of and fail containing a group that the test user isn't a member of. (The fail group doesn't have to exist)
|
59
|
+
|
60
|
+
The user is a user capable of logging into the domain, you can use your account here or any account on the domain. The group attribute needs to be set to a group that you are a member of so that the tests can make sure that the correct groups are picked up from AD.
|
61
|
+
|
62
|
+
Don't worry about this file making it into a pull request, it is in the .gitignore file so unless you remove it from there it wont be comitted.
|
63
|
+
|
64
|
+
If you make any additions/changes please add some tests for them.
|
data/adauth.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require 'adauth/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "adauth"
|
7
|
+
s.version = Adauth::Version
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Adam \"Arcath\" Laycock"]
|
10
|
+
s.email = ["gems@arcath.net"]
|
11
|
+
s.homepage = "http://adauth.arcath.net"
|
12
|
+
s.summary = "Provides Active Directory authentication for Rails"
|
13
|
+
|
14
|
+
s.add_development_dependency "rspec"
|
15
|
+
s.add_dependency "ruby-net-ldap"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
end
|
data/lib/adauth.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'net/ldap'
|
2
|
+
require 'adauth/version'
|
3
|
+
require 'adauth/user'
|
4
|
+
require 'adauth/config'
|
5
|
+
require 'adauth/helpers'
|
6
|
+
require 'adauth/user_model' if defined? ActiveRecord
|
7
|
+
|
8
|
+
module Adauth
|
9
|
+
def self.authenticate(login, pass)
|
10
|
+
if @config.allowed_groups != []
|
11
|
+
user = Adauth::User.authenticate(login, pass)
|
12
|
+
(user && @config.allowed_groups != (@config.allowed_groups - user.groups)) ? user : nil
|
13
|
+
else
|
14
|
+
Adauth::User.authenticate(login, pass)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.configure
|
19
|
+
@config = Config.new
|
20
|
+
yield(@config)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.config
|
24
|
+
@config
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Adauth
|
2
|
+
module Helpers
|
3
|
+
def adauth_form
|
4
|
+
form_tag '/adauth', :id => "adauth_login" do
|
5
|
+
yield.html_safe
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def default_adauth_form
|
10
|
+
adauth_form do
|
11
|
+
"<p>#{label_tag :username}:
|
12
|
+
#{text_field_tag :username}</p>
|
13
|
+
<p>#{label_tag :password}:
|
14
|
+
#{password_field_tag :password}</p>
|
15
|
+
<p>#{submit_tag "Login!"}</p>"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
ActionView::Base.send :include, Adauth::Helpers if defined? ActionView
|
data/lib/adauth/user.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
module Adauth
|
2
|
+
class User
|
3
|
+
ATTR_SV = {
|
4
|
+
:login => :samaccountname,
|
5
|
+
:first_name => :givenname,
|
6
|
+
:last_name => :sn,
|
7
|
+
:email => :mail,
|
8
|
+
:name => :name
|
9
|
+
}
|
10
|
+
|
11
|
+
ATTR_MV = {
|
12
|
+
:groups => [ :memberof,
|
13
|
+
Proc.new {|g| g.sub(/.*?CN=(.*?),.*/, '\1')} ]
|
14
|
+
}
|
15
|
+
|
16
|
+
def self.authenticate(login, pass)
|
17
|
+
return nil if login.empty? or pass.empty?
|
18
|
+
conn = Net::LDAP.new :host => Adauth.config.server,
|
19
|
+
:port => Adauth.config.port,
|
20
|
+
:base => Adauth.config.base,
|
21
|
+
:auth => { :username => "#{login}@#{Adauth.config.domain}",
|
22
|
+
:password => pass,
|
23
|
+
:method => :simple }
|
24
|
+
if conn.bind and user = conn.search(:filter => "sAMAccountName=#{login}").first
|
25
|
+
return self.new(user)
|
26
|
+
else
|
27
|
+
return nil
|
28
|
+
end
|
29
|
+
rescue Net::LDAP::LdapError => e
|
30
|
+
return nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def full_name
|
34
|
+
self.first_name + ' ' + self.last_name
|
35
|
+
end
|
36
|
+
|
37
|
+
def member_of?(group)
|
38
|
+
self.groups.include?(group)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def initialize(entry)
|
44
|
+
@entry = entry
|
45
|
+
self.class.class_eval do
|
46
|
+
generate_single_value_readers
|
47
|
+
generate_multi_value_readers
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.generate_single_value_readers
|
52
|
+
ATTR_SV.each_pair do |k, v|
|
53
|
+
val, block = Array(v)
|
54
|
+
define_method(k) do
|
55
|
+
if @entry.attribute_names.include?(val)
|
56
|
+
if block.is_a?(Proc)
|
57
|
+
return block[@entry.send(val).to_s]
|
58
|
+
else
|
59
|
+
return @entry.send(val).to_s
|
60
|
+
end
|
61
|
+
else
|
62
|
+
return ''
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.generate_multi_value_readers
|
69
|
+
ATTR_MV.each_pair do |k, v|
|
70
|
+
val, block = Array(v)
|
71
|
+
define_method(k) do
|
72
|
+
if @entry.attribute_names.include?(val)
|
73
|
+
if block.is_a?(Proc)
|
74
|
+
return @entry.send(val).collect(&block)
|
75
|
+
else
|
76
|
+
return @entry.send(val)
|
77
|
+
end
|
78
|
+
else
|
79
|
+
return []
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Adauth
|
2
|
+
module UserModel
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
def groups
|
8
|
+
group_strings.split(", ")
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def return_and_create_with_adauth(adauth_user)
|
13
|
+
find_by_login(adauth_user.login) || create_user_with_adauth(adauth_user)
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_user_with_adauth(adauth_user)
|
17
|
+
create! do |user|
|
18
|
+
user.login = adauth_user.login
|
19
|
+
user.group_strings = adauth_user.groups.join(", ")
|
20
|
+
user.name = adauth_user.name
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Description:
|
2
|
+
Default for MODEL_NAME is user
|
3
|
+
Default for MIGRATION_NAME is "create_(plural of MODEL_NAME)"
|
4
|
+
Creates a model for storing Adauth users which inherits from Adauth::UserModel
|
5
|
+
|
6
|
+
Example:
|
7
|
+
adauth:user_model
|
8
|
+
Will result in app/model/user.rb and a migration called create_users
|
9
|
+
|
10
|
+
adauth:user_model employee
|
11
|
+
Will result in app/model/employee.rb and a migration called create_employees
|
12
|
+
|
13
|
+
adauth:user_model employee add_adauth_to_employees
|
14
|
+
Will result in app/model/employee.rb and a migration called add_adauth_to_employees
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class <%= migration_name_for_array.camelize %>
|
2
|
+
def self.up
|
3
|
+
create_table :<%= model_name.pluralize %> do |t|
|
4
|
+
t.string :login
|
5
|
+
t.string :group_strings
|
6
|
+
t.string :name
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.down
|
12
|
+
drop_table :<%= model_name.pluralize %>
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Adauth
|
2
|
+
module Generators
|
3
|
+
class UserModelGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
5
|
+
argument :model_name, :type => :string, :default => "user"
|
6
|
+
argument :migration_name, :type => :string, :default => false
|
7
|
+
|
8
|
+
def generate_user_model
|
9
|
+
template "model.rb.erb", "app/models/#{file_name}.rb"
|
10
|
+
template "migration.rb.erb", "db/migrate/#{Time.now.utc.strftime("%Y%m%d%H%M%S")}_#{migration_name_for_array}.rb"
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def file_name
|
16
|
+
model_name.underscore
|
17
|
+
end
|
18
|
+
|
19
|
+
def migration_name_for_array
|
20
|
+
migration_name || "create_#{model_name.pluralize}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/spec/adauth_spec.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'lib/adauth'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
describe Adauth, "#configure" do
|
5
|
+
it "should accept a block" do
|
6
|
+
Adauth.configure do |c|
|
7
|
+
c.domain = "example.com"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe Adauth, "#config" do
|
13
|
+
before :each do
|
14
|
+
Adauth.configure do |c|
|
15
|
+
c.domain = "example.com"
|
16
|
+
c.base = "dc=example, dc=com"
|
17
|
+
c.server = "127.0.0.1"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should allow retrival of data" do
|
22
|
+
Adauth.config.domain.should == "example.com"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should set port to 389 if not set" do
|
26
|
+
Adauth.config.port.should == 389
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe Adauth, "#authenticate" do
|
31
|
+
before :each do
|
32
|
+
@yaml = YAML::load(File.open('spec/test_data.yml'))
|
33
|
+
Adauth.configure do |c|
|
34
|
+
c.domain = @yaml["domain"]["domain"]
|
35
|
+
c.server = @yaml["domain"]["server"]
|
36
|
+
c.port = @yaml["domain"]["port"]
|
37
|
+
c.base = @yaml["domain"]["base"]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should succesfully authenticate with the example user" do
|
42
|
+
Adauth.authenticate(@yaml["user"]["login"], @yaml["user"]["password"]).should be_a Adauth::User
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should return nil for a failed bind" do
|
46
|
+
Adauth.authenticate(@yaml["user"]["login"], @yaml["user"]["group"]).should == nil
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should return nil for a failed bind whilst using allowed groups" do
|
50
|
+
Adauth.config.allowed_groups = @yaml["domain"]["pass_allowed_groups"]
|
51
|
+
Adauth.authenticate(@yaml["user"]["login"], @yaml["user"]["group"]).should be_nil
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should allow users who are in an allowed group" do
|
55
|
+
Adauth.config.allowed_groups = @yaml["domain"]["pass_allowed_groups"]
|
56
|
+
Adauth.authenticate(@yaml["user"]["login"], @yaml["user"]["password"]).should be_a Adauth::User
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should dis-allow users who are not in an allowed group" do
|
60
|
+
Adauth.config.allowed_groups = @yaml["domain"]["fail_allowed_groups"]
|
61
|
+
Adauth.authenticate(@yaml["user"]["login"], @yaml["user"]["password"]).should be_nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe Adauth::User do
|
66
|
+
before :each do
|
67
|
+
@yaml = YAML::load(File.open('spec/test_data.yml'))
|
68
|
+
Adauth.configure do |c|
|
69
|
+
c.domain = @yaml["domain"]["domain"]
|
70
|
+
c.server = @yaml["domain"]["server"]
|
71
|
+
c.port = @yaml["domain"]["port"]
|
72
|
+
c.base = @yaml["domain"]["base"]
|
73
|
+
end
|
74
|
+
@user = Adauth.authenticate(@yaml["user"]["login"], @yaml["user"]["password"])
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should return groups for an authenticated user" do
|
78
|
+
@user.groups.should be_a Array
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should return true for a member_of test using the users group" do
|
82
|
+
@user.member_of?(@yaml["user"]["group"]).should == true
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should return false for a member_of test using the users password" do
|
86
|
+
@user.member_of?(@yaml["user"]["password"]).should == false
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should have the correct user" do
|
90
|
+
@user.login.should == @yaml["user"]["login"]
|
91
|
+
end
|
92
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: adauth
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 961915968
|
5
|
+
prerelease: 5
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
- pre
|
11
|
+
version: 0.0.1pre
|
12
|
+
platform: ruby
|
13
|
+
authors:
|
14
|
+
- Adam "Arcath" Laycock
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2011-06-06 00:00:00 +01:00
|
20
|
+
default_executable:
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
name: rspec
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 3
|
31
|
+
segments:
|
32
|
+
- 0
|
33
|
+
version: "0"
|
34
|
+
type: :development
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: ruby-net-ldap
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 3
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
version: "0"
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id002
|
50
|
+
description:
|
51
|
+
email:
|
52
|
+
- gems@arcath.net
|
53
|
+
executables: []
|
54
|
+
|
55
|
+
extensions: []
|
56
|
+
|
57
|
+
extra_rdoc_files: []
|
58
|
+
|
59
|
+
files:
|
60
|
+
- .gitignore
|
61
|
+
- Gemfile
|
62
|
+
- Gemfile.lock
|
63
|
+
- Rakefile
|
64
|
+
- Readme.rdoc
|
65
|
+
- adauth.gemspec
|
66
|
+
- lib/adauth.rb
|
67
|
+
- lib/adauth/config.rb
|
68
|
+
- lib/adauth/helpers.rb
|
69
|
+
- lib/adauth/user.rb
|
70
|
+
- lib/adauth/user_model.rb
|
71
|
+
- lib/adauth/version.rb
|
72
|
+
- lib/generators/adauth/user_model/USAGE
|
73
|
+
- lib/generators/adauth/user_model/templates/migration.rb.erb
|
74
|
+
- lib/generators/adauth/user_model/templates/model.rb.erb
|
75
|
+
- lib/generators/adauth/user_model/user_model_generator.rb
|
76
|
+
- spec/adauth_spec.rb
|
77
|
+
has_rdoc: true
|
78
|
+
homepage: http://adauth.arcath.net
|
79
|
+
licenses: []
|
80
|
+
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
hash: 3
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
version: "0"
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ">"
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
hash: 25
|
101
|
+
segments:
|
102
|
+
- 1
|
103
|
+
- 3
|
104
|
+
- 1
|
105
|
+
version: 1.3.1
|
106
|
+
requirements: []
|
107
|
+
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 1.6.2
|
110
|
+
signing_key:
|
111
|
+
specification_version: 3
|
112
|
+
summary: Provides Active Directory authentication for Rails
|
113
|
+
test_files:
|
114
|
+
- spec/adauth_spec.rb
|