warden_oauth 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +5 -0
- data/CHANGELOG +6 -0
- data/LICENSE +20 -0
- data/README.rdoc +60 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/lib/warden_oauth.rb +19 -0
- data/lib/warden_oauth/config.rb +43 -0
- data/lib/warden_oauth/errors.rb +9 -0
- data/lib/warden_oauth/manager.rb +43 -0
- data/lib/warden_oauth/strategy.rb +140 -0
- data/lib/warden_oauth/strategy_builder.rb +92 -0
- data/lib/warden_oauth/utils.rb +40 -0
- data/spec/application_runner.rb +11 -0
- data/spec/application_scenario.rb +36 -0
- data/spec/fixtures/authorize_request_token.txt +1 -0
- data/spec/fixtures/unauthorized_request_token.txt +1 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/warden_oauth/manager_spec.rb +48 -0
- data/spec/warden_oauth/strategy_spec.rb +144 -0
- data/warden_oauth.gemspec +87 -0
- metadata +140 -0
data/.document
ADDED
data/CHANGELOG
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
* 0.0.2 (Oct 1, 2009) Keep the manager out of the business of strategies
|
2
|
+
* Removing the access_token_user_finder from Warden::Manager and adding it to
|
3
|
+
the Warden::StrategyBuilder module
|
4
|
+
|
5
|
+
* 0.0.1 (Sep 16, 2009) The beginning of easy OAuth for Warden
|
6
|
+
* Adding the initial implementation of the warden_oauth gem
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Roman Gonzalez
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
= warden_oauth
|
2
|
+
|
3
|
+
warden_oauth enhances the Warden authentication framework, offering a simple interface for creating
|
4
|
+
oauth strategies.
|
5
|
+
|
6
|
+
== Getting Started
|
7
|
+
|
8
|
+
To get started you just have to require the warden_oauth libraries, and setup the
|
9
|
+
oauth services you would like to have on the <tt>Warden::Manager</tt> middleware declaration:
|
10
|
+
|
11
|
+
Warden::Manager do |manager|
|
12
|
+
manager.failure_app = FailureApp
|
13
|
+
manager.oauth(:twitter) do |twitter|
|
14
|
+
twitter.consumer_secret = <YOUR CONSUMER SECRET>
|
15
|
+
twitter.consumer_key = <YOUR CONSUMER KEY>
|
16
|
+
twitter.options :site => 'http://twitter.com'
|
17
|
+
end
|
18
|
+
manager.default_strategies(:twitter_oauth, :password, :other)
|
19
|
+
end
|
20
|
+
|
21
|
+
== Giving an Access Token fetcher
|
22
|
+
|
23
|
+
Users get identified on a system via an access_token and an access_secret, when a valid access_token is
|
24
|
+
recevied, warden_oauth calls a fetcher declared on <tt>Warden::Manager.access_token_user_finder</tt>.
|
25
|
+
|
26
|
+
Warden::Manager.access_token_user_finder(:twitter) do |access_token|
|
27
|
+
User.find_by_access_token_and_access_secret(access_token.token, access_token.secret)
|
28
|
+
end
|
29
|
+
|
30
|
+
If a user is returned, then this is the user that is going to be authenticated in the session, otherwise the
|
31
|
+
<tt>FailureApp</tt> will be called, you may check the <tt>env['warden.options'][:oauth][:access_token]</tt> to check
|
32
|
+
the original access_token and <em>create a new user</em> from there if desired.
|
33
|
+
|
34
|
+
== Strategy Class info
|
35
|
+
|
36
|
+
When you declare an oauth strategy on the <tt>Warden::Manager</tt> initialization, (e.g. manager.oauth(:service_name))
|
37
|
+
a <tt>Warden::OAuth::Strategy::ServiceName</tt> will be declared, at the same time this class will be registered as
|
38
|
+
<tt>:service_name_oauth</tt> on the <tt>Warden::Strategies</tt>.
|
39
|
+
|
40
|
+
So if we have a declaration like the one of the Getting Started section, we will have an Strategy class
|
41
|
+
called <tt>Warden::OAuth::Strategy::Twitter</tt>, and this will be registered as <tt>:twitter_oauth</tt>.
|
42
|
+
|
43
|
+
== Running the Strategy
|
44
|
+
|
45
|
+
In order to get the strategy running in the app, you have to specify a parameter called warden_oauth_provider
|
46
|
+
with the name of the oauth service you want to start. So for example, if you would like to boot the twitter
|
47
|
+
oauth example given on the "Getting Started" section you just have to specify the parameter on a protected
|
48
|
+
url.
|
49
|
+
|
50
|
+
In Rails:
|
51
|
+
|
52
|
+
link_to 'Twitter Authentication', url_for(login_path(:warden_oauth_provider => 'twitter'))
|
53
|
+
|
54
|
+
== Note on Patches/Pull Requests
|
55
|
+
|
56
|
+
For any error send an email to: romanandreg [at] gmail [dot] com
|
57
|
+
|
58
|
+
== Copyright
|
59
|
+
|
60
|
+
Copyright (c) 2009 Roman Gonzalez. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "warden_oauth"
|
8
|
+
gem.summary = %Q{OAuth Strategy generator for Warden Authentication Framework}
|
9
|
+
gem.description = %Q{
|
10
|
+
warden_oauth will help you create oauth authentication strategies using the oauth
|
11
|
+
helper method on the Warden::Manager config setup
|
12
|
+
}
|
13
|
+
gem.email = "romanandreg@gmail.com"
|
14
|
+
gem.homepage = "http://github.com/roman/warden_oauth"
|
15
|
+
gem.authors = ["Roman Gonzalez"]
|
16
|
+
gem.rubyforge_project = "warden_oauth"
|
17
|
+
gem.add_dependency('warden')
|
18
|
+
gem.add_dependency('oauth')
|
19
|
+
gem.add_development_dependency("rack-test")
|
20
|
+
gem.add_development_dependency("fakeweb")
|
21
|
+
gem.add_development_dependency("rspec")
|
22
|
+
gem.add_development_dependency("yard")
|
23
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
24
|
+
end
|
25
|
+
Jeweler::GemcutterTasks.new
|
26
|
+
rescue LoadError
|
27
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
28
|
+
end
|
29
|
+
|
30
|
+
require 'spec/rake/spectask'
|
31
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
32
|
+
spec.libs << 'lib' << 'spec'
|
33
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
34
|
+
end
|
35
|
+
|
36
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
37
|
+
spec.libs << 'lib' << 'spec'
|
38
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
39
|
+
spec.rcov = true
|
40
|
+
end
|
41
|
+
|
42
|
+
task :spec => :check_dependencies
|
43
|
+
|
44
|
+
task :default => :spec
|
45
|
+
|
46
|
+
begin
|
47
|
+
require 'yard'
|
48
|
+
YARD::Rake::YardocTask.new
|
49
|
+
rescue LoadError
|
50
|
+
task :yardoc do
|
51
|
+
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
52
|
+
end
|
53
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
data/lib/warden_oauth.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "rack"
|
2
|
+
require "warden"
|
3
|
+
require "oauth"
|
4
|
+
|
5
|
+
module Warden
|
6
|
+
module OAuth
|
7
|
+
|
8
|
+
base_path = File.dirname(__FILE__) + "/warden_oauth"
|
9
|
+
|
10
|
+
require base_path + "/errors"
|
11
|
+
autoload :Utils, base_path + '/utils'
|
12
|
+
autoload :StrategyBuilder, base_path + '/strategy_builder'
|
13
|
+
autoload :Strategy, base_path + '/strategy'
|
14
|
+
autoload :Config, base_path + "/config"
|
15
|
+
require base_path + "/manager"
|
16
|
+
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Warden
|
2
|
+
module OAuth
|
3
|
+
|
4
|
+
#
|
5
|
+
# Holds all the information of the OAuth service.
|
6
|
+
#
|
7
|
+
class Config
|
8
|
+
attr_accessor :provider_name
|
9
|
+
|
10
|
+
def consumer_key(key = nil)
|
11
|
+
unless key.nil?
|
12
|
+
@consumer_key = key
|
13
|
+
end
|
14
|
+
@consumer_key
|
15
|
+
end
|
16
|
+
alias_method :consumer_key=, :consumer_key
|
17
|
+
|
18
|
+
def consumer_secret(secret = nil)
|
19
|
+
unless secret.nil?
|
20
|
+
@consumer_secret = secret
|
21
|
+
end
|
22
|
+
@consumer_secret
|
23
|
+
end
|
24
|
+
alias_method :consumer_secret=, :consumer_secret
|
25
|
+
|
26
|
+
def options(options = nil)
|
27
|
+
unless options.nil?
|
28
|
+
@options = options
|
29
|
+
end
|
30
|
+
@options
|
31
|
+
end
|
32
|
+
alias_method :options=, :options
|
33
|
+
|
34
|
+
def check_requirements
|
35
|
+
if @consumer_key.nil? || @consumer_secret.nil?
|
36
|
+
raise Warden::OAuth::ConfigError.new("You need to specify the consumer key and the consumer secret")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Warden
|
2
|
+
module OAuth
|
3
|
+
|
4
|
+
#
|
5
|
+
# Holds all the extensions made to Warden::Manager in order to create OAuth
|
6
|
+
# consumers.
|
7
|
+
#
|
8
|
+
module Manager
|
9
|
+
|
10
|
+
#
|
11
|
+
# Helps to setup a new OAuth client authentication, to get started you need to define
|
12
|
+
# a service name, and then on the block assign the different values required in order
|
13
|
+
# to boot the OAuth process.
|
14
|
+
# @param [Symbol] service An identifier of the OAuth service
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
#
|
18
|
+
# Warden::Manager.oauth(:twitter) do
|
19
|
+
# consumer_key "<YOUR CONSUMER KEY>"
|
20
|
+
# consumer_secret "<YOUR CONSUMER SECRET>"
|
21
|
+
# options :site => 'http://twitter.com'
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
def oauth(service, &block)
|
25
|
+
config = Warden::OAuth::Config.new
|
26
|
+
if block_given?
|
27
|
+
if block.arity == 1
|
28
|
+
yield config
|
29
|
+
else
|
30
|
+
config.instance_eval(&block)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
config.check_requirements
|
34
|
+
config.provider_name = service
|
35
|
+
Warden::OAuth::Strategy.build(service, config)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Warden::Manager.send(:include, Warden::OAuth::Manager)
|
@@ -0,0 +1,140 @@
|
|
1
|
+
module Warden
|
2
|
+
module OAuth
|
3
|
+
|
4
|
+
#
|
5
|
+
# Holds all the main logic of the OAuth authentication, all the generated
|
6
|
+
# OAuth classes will extend from this class
|
7
|
+
#
|
8
|
+
class Strategy < Warden::Strategies::Base
|
9
|
+
extend StrategyBuilder
|
10
|
+
|
11
|
+
######################
|
12
|
+
### Strategy Logic ###
|
13
|
+
######################
|
14
|
+
|
15
|
+
#
|
16
|
+
# An OAuth strategy will be valid to execute if:
|
17
|
+
# * A 'warden_oauth_provider' parameter is given, with the name of the OAuth service
|
18
|
+
# * A 'oauth_token' is being receive on the request (response from an OAuth provider)
|
19
|
+
#
|
20
|
+
def valid?
|
21
|
+
(params.include?('warden_oauth_provider') && params['warden_oauth_provider'] == config.provider_name.to_s) ||
|
22
|
+
params.include?('oauth_token')
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
#
|
27
|
+
# Manages the OAuth authentication process, there can be 3 outcomes from this Strategy:
|
28
|
+
# 1. The OAuth credentials are invalid and the FailureApp is called
|
29
|
+
# 2. The OAuth credentials are valid, but there is no user associated to them. In this case
|
30
|
+
# the FailureApp is called, but the env['warden.options'][:oauth][:access_token] will be
|
31
|
+
# available.
|
32
|
+
# 3. The OAuth credentials are valid, and the user is authenticated successfuly
|
33
|
+
#
|
34
|
+
# @note
|
35
|
+
# If you want to signup users with the twitter credentials, you can manage the creation of a new
|
36
|
+
# user in the FailureApp with the given access_token
|
37
|
+
#
|
38
|
+
def authenticate!
|
39
|
+
if params.include?('warden_oauth_provider')
|
40
|
+
store_request_token_on_session
|
41
|
+
redirect!(request_token.authorize_url)
|
42
|
+
|
43
|
+
elsif params.include?('oauth_token')
|
44
|
+
load_request_token_from_session
|
45
|
+
if missing_stored_token?
|
46
|
+
fail!("There is no OAuth authentication in progress")
|
47
|
+
elsif !stored_token_match_recieved_token?
|
48
|
+
fail!("Received OAuth token didn't match stored OAuth token")
|
49
|
+
else
|
50
|
+
user = find_user_by_access_token(access_token)
|
51
|
+
if user.nil?
|
52
|
+
fail!("User with access token not found")
|
53
|
+
throw_error_with_oauth_info
|
54
|
+
else
|
55
|
+
success!(user)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
def fail!(msg) #:nodoc:
|
63
|
+
self.errors.add(service_param_name.to_sym, msg)
|
64
|
+
super
|
65
|
+
end
|
66
|
+
|
67
|
+
###################
|
68
|
+
### OAuth Logic ###
|
69
|
+
###################
|
70
|
+
|
71
|
+
def consumer
|
72
|
+
@consumer ||= ::OAuth::Consumer.new(config.consumer_key, config.consumer_secret, config.options)
|
73
|
+
end
|
74
|
+
|
75
|
+
def request_token
|
76
|
+
host_with_port = Warden::OAuth::Utils.host_with_port(request)
|
77
|
+
@request_token ||= consumer.get_request_token(:oauth_callback => host_with_port)
|
78
|
+
end
|
79
|
+
|
80
|
+
def access_token
|
81
|
+
@access_token ||= request_token.get_access_token(:oauth_verifier => params['oauth_verifier'])
|
82
|
+
end
|
83
|
+
|
84
|
+
protected
|
85
|
+
|
86
|
+
def find_user_by_access_token(access_token)
|
87
|
+
raise RuntimeError.new(<<-ERROR_MESSAGE) unless self.respond_to?(:_find_user_by_access_token)
|
88
|
+
|
89
|
+
You need to define a finder by access_token for this strategy.
|
90
|
+
Write on the warden initializer the following code:
|
91
|
+
Warden::Strategies[:#{config.provider_name}_oauth].access_token_user_finder do |access_token|
|
92
|
+
# Logic to get your user from an access_token
|
93
|
+
end
|
94
|
+
|
95
|
+
ERROR_MESSAGE
|
96
|
+
self._find_user_by_access_token(access_token)
|
97
|
+
end
|
98
|
+
|
99
|
+
def throw_error_with_oauth_info
|
100
|
+
throw(:warden, :oauth => {
|
101
|
+
self.config.provider_name => {
|
102
|
+
:provider => config.provider_name,
|
103
|
+
:access_token => access_token,
|
104
|
+
:consumer_key => config.consumer_key,
|
105
|
+
:consumer_secret => config.consumer_secret
|
106
|
+
}
|
107
|
+
})
|
108
|
+
end
|
109
|
+
|
110
|
+
def store_request_token_on_session
|
111
|
+
session[:request_token] = request_token.token
|
112
|
+
session[:request_secret] = request_token.secret
|
113
|
+
end
|
114
|
+
|
115
|
+
def load_request_token_from_session
|
116
|
+
token = session.delete(:request_token)
|
117
|
+
secret = session.delete(:request_secret)
|
118
|
+
@request_token = ::OAuth::RequestToken.new(consumer, token, secret)
|
119
|
+
end
|
120
|
+
|
121
|
+
def missing_stored_token?
|
122
|
+
!request_token
|
123
|
+
end
|
124
|
+
|
125
|
+
def stored_token_match_recieved_token?
|
126
|
+
request_token.token == params['oauth_token']
|
127
|
+
end
|
128
|
+
|
129
|
+
def service_param_name
|
130
|
+
'%s_oauth' % config.provider_name
|
131
|
+
end
|
132
|
+
|
133
|
+
def config
|
134
|
+
self.class::CONFIG
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Warden
|
2
|
+
module OAuth
|
3
|
+
|
4
|
+
#
|
5
|
+
# Handles the creation an registration of OAuth strategies based on configuration parameters
|
6
|
+
# via the Warden::Manager.oauth method
|
7
|
+
#
|
8
|
+
module StrategyBuilder
|
9
|
+
extend self
|
10
|
+
|
11
|
+
|
12
|
+
#
|
13
|
+
# Defines the user finder from the access_token for the strategy, receives a block
|
14
|
+
# that will be invoked each time you want to find an user via an access_token in your
|
15
|
+
# system.
|
16
|
+
#
|
17
|
+
# @param blk Block that recieves the access_token as a parameter and will return a user or nil
|
18
|
+
#
|
19
|
+
def access_token_user_finder(&blk)
|
20
|
+
define_method(:_find_user_by_access_token, &blk)
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Manages the creation and registration of the OAuth strategy specified
|
25
|
+
# on the keyword
|
26
|
+
#
|
27
|
+
# @param [Symbol] name of the oauth service
|
28
|
+
# @param [Walruz::Config] configuration specified on the declaration of the oauth service
|
29
|
+
#
|
30
|
+
def build(keyword, config)
|
31
|
+
strategy_class = self.create_oauth_strategy_class(keyword)
|
32
|
+
self.register_oauth_strategy_class(keyword, strategy_class)
|
33
|
+
self.set_oauth_service_info(strategy_class, config)
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Creates the OAuth Strategy class from the keyword specified on the declaration of the
|
38
|
+
# oauth service. This class will be namespaced inside Warden::OAuth::Strategy
|
39
|
+
#
|
40
|
+
# @param [Symbol] name of the OAuth service
|
41
|
+
# @return [Class] The class representing the Warden strategy
|
42
|
+
#
|
43
|
+
# @example
|
44
|
+
#
|
45
|
+
# self.create_oauth_strategy_class(:twitter) #=> Warden::OAuth::Strategy::Twitter
|
46
|
+
# # will create a class Warden::OAuth::Strategy::Twitter that extends from
|
47
|
+
# # Warden::OAuth::Strategy
|
48
|
+
#
|
49
|
+
def create_oauth_strategy_class(keyword)
|
50
|
+
class_name = Warden::OAuth::Utils.camelize(keyword.to_s)
|
51
|
+
if self.const_defined?(class_name)
|
52
|
+
self.const_get(class_name)
|
53
|
+
else
|
54
|
+
self.const_set(class_name, Class.new(self))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Registers the generated OAuth Strategy in the Warden::Strategies collection, the label
|
60
|
+
# of the strategy will be the given oauth service name plus an '_oauth' postfix
|
61
|
+
#
|
62
|
+
# @param [Symbol] name of the OAuth service
|
63
|
+
#
|
64
|
+
# @example
|
65
|
+
# manager.oauth(:twitter) { |twitter| ... } # will register a strategy :twitter_oauth
|
66
|
+
#
|
67
|
+
def register_oauth_strategy_class(keyword, strategy_class)
|
68
|
+
keyword_name = "%s_oauth" % keyword.to_s
|
69
|
+
if Warden::Strategies[keyword_name.to_sym].nil?
|
70
|
+
Warden::Strategies.add(keyword_name.to_sym, strategy_class)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# Defines a CONFIG constant in the generated class that will hold the configuration information
|
76
|
+
# (consumer_key, consumer_secret and options) of the oauth service.
|
77
|
+
#
|
78
|
+
# @param [Class] strategy class that will hold the configuration info
|
79
|
+
# @param [Warden::OAuth::Config] configuration info of the oauth service
|
80
|
+
#
|
81
|
+
def set_oauth_service_info(strategy_class, config)
|
82
|
+
strategy_class.const_set("CONFIG", config) unless strategy_class.const_defined?("CONFIG")
|
83
|
+
end
|
84
|
+
|
85
|
+
protected :create_oauth_strategy_class,
|
86
|
+
:register_oauth_strategy_class,
|
87
|
+
:set_oauth_service_info
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Warden
|
2
|
+
module OAuth
|
3
|
+
|
4
|
+
#
|
5
|
+
# Contains methods from Rails to avoid unnecessary dependencies
|
6
|
+
#
|
7
|
+
module Utils
|
8
|
+
|
9
|
+
#
|
10
|
+
# Fetched from ActiveSupport::Inflector.camelize to avoid dependencies
|
11
|
+
#
|
12
|
+
def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
|
13
|
+
if first_letter_in_uppercase
|
14
|
+
lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
15
|
+
else
|
16
|
+
lower_case_and_underscored_word.first.downcase + camelize(lower_case_and_underscored_word)[1..-1]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# Fetched from ActionController::Request to avoid dependencies
|
22
|
+
#
|
23
|
+
def host_with_port(request)
|
24
|
+
url = request.scheme + "://"
|
25
|
+
url << request.host
|
26
|
+
|
27
|
+
if request.scheme == "https" && request.port != 443 ||
|
28
|
+
request.scheme == "http" && request.port != 80
|
29
|
+
url << ":#{request.port}"
|
30
|
+
end
|
31
|
+
|
32
|
+
url
|
33
|
+
end
|
34
|
+
|
35
|
+
module_function :camelize, :host_with_port
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'rubygems'
|
4
|
+
require 'warden_oauth'
|
5
|
+
require File.dirname(__FILE__) + "/application_scenario"
|
6
|
+
|
7
|
+
Warden::Manager.access_token_user_finder do |access_token|
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
|
11
|
+
Rack::Handler::Mongrel.run $app, :Port => '4567'
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class ClientApp
|
2
|
+
|
3
|
+
def self.call(env)
|
4
|
+
env['warden'].authenticate!
|
5
|
+
[200, {"Content-Type" => 'text/plain'}, "Welcome"]
|
6
|
+
end
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
class ErrorApp
|
11
|
+
|
12
|
+
def self.call(env)
|
13
|
+
if env['warden.options'][:oauth].nil?
|
14
|
+
[401, {'Content-Type' => 'text/plain'}, "You are not authenticated"]
|
15
|
+
else
|
16
|
+
access_token = env['warden.options'][:oauth][:access_token]
|
17
|
+
[401, {'Content-Type' => 'text/plain'}, "No user with the given access token"]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
$app = Rack::Builder.new do
|
24
|
+
use Rack::Session::Cookie
|
25
|
+
use Warden::Manager do |manager|
|
26
|
+
manager.oauth(:example) do |example|
|
27
|
+
example.consumer_key "aCOTnTeKniyifcwwF3Mo"
|
28
|
+
example.consumer_secret "dEu91qxWfO0Z4Be1tHGuZ63FzHoUm9mk4Z8rzKa8"
|
29
|
+
example.options :site => 'http://localhost:3000'
|
30
|
+
end
|
31
|
+
manager.default_strategies :example_oauth
|
32
|
+
manager.failure_app = ErrorApp
|
33
|
+
end
|
34
|
+
run ClientApp
|
35
|
+
end if $app.nil?
|
36
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
oauth_token=SylltB94pocC6hex8kr9&oauth_verifier=omPxEkKnnx9ygnu7dd6f
|
@@ -0,0 +1 @@
|
|
1
|
+
oauth_token=SylltB94pocC6hex8kr9&oauth_token_secret=WkU0NDgdOlKeB7arFWJyAQjlaVZEEcH0lhdy1kFs&oauth_callback_confirmed=true
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
require 'rubygems'
|
4
|
+
require 'warden_oauth'
|
5
|
+
require 'spec'
|
6
|
+
require 'fakeweb'
|
7
|
+
require 'spec/autorun'
|
8
|
+
|
9
|
+
require File.dirname(__FILE__) + "/application_scenario"
|
10
|
+
|
11
|
+
Spec::Runner.configure do |config|
|
12
|
+
config.before(:all) do
|
13
|
+
FakeWeb.allow_net_connect = false
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../spec_helper"
|
2
|
+
|
3
|
+
describe Warden::Manager do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
failure_app = lambda { |env| "Failure" }
|
7
|
+
@manager = Warden::Manager.new(nil, :failure_app => failure_app)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should respond to an `oauth` message" do
|
11
|
+
@manager.should respond_to(:oauth)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#oauth" do
|
15
|
+
|
16
|
+
describe "when initialize" do
|
17
|
+
|
18
|
+
it "should require setting the consumer_key" do
|
19
|
+
lambda do
|
20
|
+
@manager.oauth(:service) do |service|
|
21
|
+
service.consumer_secret "ABC"
|
22
|
+
end
|
23
|
+
end.should raise_error(Warden::OAuth::ConfigError, "You need to specify the consumer key and the consumer secret")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should require setting the consumer_secret" do
|
27
|
+
lambda do
|
28
|
+
@manager.oauth(:service) do |service|
|
29
|
+
service.consumer_key "ABC"
|
30
|
+
end
|
31
|
+
end.should raise_error(Warden::OAuth::ConfigError, "You need to specify the consumer key and the consumer secret")
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should create a new instance of strategy" do
|
35
|
+
@manager.oauth(:service) do |service|
|
36
|
+
service.consumer_key "ABC"
|
37
|
+
service.consumer_secret "123"
|
38
|
+
end
|
39
|
+
lambda do
|
40
|
+
Warden::OAuth::Strategy::Service
|
41
|
+
end.should_not raise_error(NameError)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../spec_helper"
|
2
|
+
require "rack/test"
|
3
|
+
|
4
|
+
describe Warden::OAuth::Strategy do
|
5
|
+
|
6
|
+
def fixture_response(name)
|
7
|
+
filename = File.dirname(__FILE__) + "/../fixtures/%s.txt" % name
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.build' do
|
11
|
+
before(:each) do
|
12
|
+
@config = Warden::OAuth::Config.new
|
13
|
+
@config.consumer_key "ABC"
|
14
|
+
@config.consumer_secret "123"
|
15
|
+
@config.options :site => 'http://service.com'
|
16
|
+
Warden::OAuth::Strategy.send(:remove_const, "Service") if Warden::OAuth::Strategy.const_defined?("Service")
|
17
|
+
Warden::Strategies.clear!
|
18
|
+
Warden::OAuth::Strategy.build(:service, @config)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should create a new instance that extends from Warden::OAuth::Strategy" do
|
22
|
+
Warden::OAuth::Strategy.const_defined?("Service").should be_true
|
23
|
+
(Warden::OAuth::Strategy::Service < Warden::OAuth::Strategy).should be_true
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should register the oauth service key on the Warden strategies with `_oauth` appended" do
|
27
|
+
Warden::Strategies[:service_oauth].should_not be_nil
|
28
|
+
Warden::OAuth::Strategy::Service.should_not be_nil
|
29
|
+
Warden::Strategies[:service_oauth].should == Warden::OAuth::Strategy::Service
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should assign the oauth_service config as a constant" do
|
33
|
+
Warden::OAuth::Strategy::Service::CONFIG.should_not be_nil
|
34
|
+
Warden::OAuth::Strategy::Service::CONFIG.should == @config
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "when invoking the strategy" do
|
40
|
+
|
41
|
+
before(:each) do
|
42
|
+
@request = Rack::MockRequest.new($app)
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
describe "without warden_oauth_service nor oauth_token parameter" do
|
47
|
+
|
48
|
+
before(:each) do
|
49
|
+
@response = @request.get("/")
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should render the failure app response" do
|
53
|
+
@response.body.should == "You are not authenticated"
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "with a warden_oauth_provider parameter" do
|
59
|
+
|
60
|
+
before(:each) do
|
61
|
+
FakeWeb.register_uri(:post, 'http://localhost:3000/oauth/request_token',
|
62
|
+
:body => fixture_response("unauthorized_request_token"))
|
63
|
+
@response = @request.get("/", :input => 'warden_oauth_provider=example')
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should redirect to the authorize url" do
|
67
|
+
@response.headers['Location'].should =~ %r"http://localhost:3000/oauth/authorize"
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "when receiving a valid oauth response" do
|
73
|
+
include Rack::Test::Methods
|
74
|
+
|
75
|
+
def app
|
76
|
+
$app
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "and the access_token_finder hasn't been declared" do
|
80
|
+
|
81
|
+
before(:each) do
|
82
|
+
FakeWeb.register_uri(:post, 'http://localhost:3000/oauth/request_token',
|
83
|
+
:body => fixture_response("unauthorized_request_token"))
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should raise an exception saying that the access_token_finder is not declared" do
|
87
|
+
get "/", 'warden_oauth_provider' => 'example'
|
88
|
+
FakeWeb.register_uri(:post, 'http://localhost:3000/oauth/access_token',
|
89
|
+
:body => 'oauth_token=ABC&oauth_token_secret=123')
|
90
|
+
lambda do
|
91
|
+
get "/", 'oauth_token' => "SylltB94pocC6hex8kr9",
|
92
|
+
'oauth_verifier' => "omPxEkKnnx9ygnu7dd6f"
|
93
|
+
end.should raise_error(RuntimeError, /strategy/)
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "and the access_token_finder has been declared" do
|
99
|
+
|
100
|
+
before(:each) do
|
101
|
+
Warden::Strategies[:example_oauth].access_token_user_finder do |access_token|
|
102
|
+
Object.new if access_token.token == 'ABC' && access_token.secret == '123'
|
103
|
+
end
|
104
|
+
FakeWeb.register_uri(:post, 'http://localhost:3000/oauth/request_token',
|
105
|
+
:body => fixture_response("unauthorized_request_token"))
|
106
|
+
get "/", 'warden_oauth_provider' => 'example'
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "and the user is not found" do
|
110
|
+
|
111
|
+
before(:each) do
|
112
|
+
FakeWeb.register_uri(:post, 'http://localhost:3000/oauth/access_token',
|
113
|
+
:body => 'oauth_token=ABD&oauth_token_secret=122')
|
114
|
+
get "/", 'oauth_token' => "SylltB94pocC6hex8kr9",
|
115
|
+
'oauth_verifier' => "omPxEkKnnx9ygnu7dd6f"
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should invoke the fail app" do
|
119
|
+
last_response.body.should == "No user with the given access token"
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "and the user is found" do
|
125
|
+
|
126
|
+
before(:each) do
|
127
|
+
FakeWeb.register_uri(:post, 'http://localhost:3000/oauth/access_token',
|
128
|
+
:body => 'oauth_token=ABC&oauth_token_secret=123')
|
129
|
+
get "/", 'oauth_token' => "SylltB94pocC6hex8kr9",
|
130
|
+
'oauth_verifier' => "omPxEkKnnx9ygnu7dd6f"
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should go to the desired app" do
|
134
|
+
last_response.body.should == "Welcome"
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{warden_oauth}
|
8
|
+
s.version = "0.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Roman Gonzalez"]
|
12
|
+
s.date = %q{2009-11-02}
|
13
|
+
s.description = %q{
|
14
|
+
warden_oauth will help you create oauth authentication strategies using the oauth
|
15
|
+
helper method on the Warden::Manager config setup
|
16
|
+
}
|
17
|
+
s.email = %q{romanandreg@gmail.com}
|
18
|
+
s.extra_rdoc_files = [
|
19
|
+
"LICENSE",
|
20
|
+
"README.rdoc"
|
21
|
+
]
|
22
|
+
s.files = [
|
23
|
+
".document",
|
24
|
+
".gitignore",
|
25
|
+
"CHANGELOG",
|
26
|
+
"LICENSE",
|
27
|
+
"README.rdoc",
|
28
|
+
"Rakefile",
|
29
|
+
"VERSION",
|
30
|
+
"lib/warden_oauth.rb",
|
31
|
+
"lib/warden_oauth/config.rb",
|
32
|
+
"lib/warden_oauth/errors.rb",
|
33
|
+
"lib/warden_oauth/manager.rb",
|
34
|
+
"lib/warden_oauth/strategy.rb",
|
35
|
+
"lib/warden_oauth/strategy_builder.rb",
|
36
|
+
"lib/warden_oauth/utils.rb",
|
37
|
+
"spec/application_runner.rb",
|
38
|
+
"spec/application_scenario.rb",
|
39
|
+
"spec/fixtures/authorize_request_token.txt",
|
40
|
+
"spec/fixtures/unauthorized_request_token.txt",
|
41
|
+
"spec/spec_helper.rb",
|
42
|
+
"spec/warden_oauth/manager_spec.rb",
|
43
|
+
"spec/warden_oauth/strategy_spec.rb",
|
44
|
+
"warden_oauth.gemspec"
|
45
|
+
]
|
46
|
+
s.homepage = %q{http://github.com/roman/warden_oauth}
|
47
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
48
|
+
s.require_paths = ["lib"]
|
49
|
+
s.rubyforge_project = %q{warden_oauth}
|
50
|
+
s.rubygems_version = %q{1.3.5}
|
51
|
+
s.summary = %q{OAuth Strategy generator for Warden Authentication Framework}
|
52
|
+
s.test_files = [
|
53
|
+
"spec/application_runner.rb",
|
54
|
+
"spec/application_scenario.rb",
|
55
|
+
"spec/spec_helper.rb",
|
56
|
+
"spec/warden_oauth/manager_spec.rb",
|
57
|
+
"spec/warden_oauth/strategy_spec.rb"
|
58
|
+
]
|
59
|
+
|
60
|
+
if s.respond_to? :specification_version then
|
61
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
62
|
+
s.specification_version = 3
|
63
|
+
|
64
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
65
|
+
s.add_runtime_dependency(%q<warden>, [">= 0"])
|
66
|
+
s.add_runtime_dependency(%q<oauth>, [">= 0"])
|
67
|
+
s.add_development_dependency(%q<rack-test>, [">= 0"])
|
68
|
+
s.add_development_dependency(%q<fakeweb>, [">= 0"])
|
69
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
70
|
+
s.add_development_dependency(%q<yard>, [">= 0"])
|
71
|
+
else
|
72
|
+
s.add_dependency(%q<warden>, [">= 0"])
|
73
|
+
s.add_dependency(%q<oauth>, [">= 0"])
|
74
|
+
s.add_dependency(%q<rack-test>, [">= 0"])
|
75
|
+
s.add_dependency(%q<fakeweb>, [">= 0"])
|
76
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
77
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
78
|
+
end
|
79
|
+
else
|
80
|
+
s.add_dependency(%q<warden>, [">= 0"])
|
81
|
+
s.add_dependency(%q<oauth>, [">= 0"])
|
82
|
+
s.add_dependency(%q<rack-test>, [">= 0"])
|
83
|
+
s.add_dependency(%q<fakeweb>, [">= 0"])
|
84
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
85
|
+
s.add_dependency(%q<yard>, [">= 0"])
|
86
|
+
end
|
87
|
+
end
|
metadata
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: warden_oauth
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Roman Gonzalez
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-11-02 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: warden
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: oauth
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: rack-test
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: fakeweb
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
type: :development
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: "0"
|
64
|
+
version:
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: yard
|
67
|
+
type: :development
|
68
|
+
version_requirement:
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: "0"
|
74
|
+
version:
|
75
|
+
description: " \n warden_oauth will help you create oauth authentication strategies using the oauth\n helper method on the Warden::Manager config setup\n "
|
76
|
+
email: romanandreg@gmail.com
|
77
|
+
executables: []
|
78
|
+
|
79
|
+
extensions: []
|
80
|
+
|
81
|
+
extra_rdoc_files:
|
82
|
+
- LICENSE
|
83
|
+
- README.rdoc
|
84
|
+
files:
|
85
|
+
- .document
|
86
|
+
- .gitignore
|
87
|
+
- CHANGELOG
|
88
|
+
- LICENSE
|
89
|
+
- README.rdoc
|
90
|
+
- Rakefile
|
91
|
+
- VERSION
|
92
|
+
- lib/warden_oauth.rb
|
93
|
+
- lib/warden_oauth/config.rb
|
94
|
+
- lib/warden_oauth/errors.rb
|
95
|
+
- lib/warden_oauth/manager.rb
|
96
|
+
- lib/warden_oauth/strategy.rb
|
97
|
+
- lib/warden_oauth/strategy_builder.rb
|
98
|
+
- lib/warden_oauth/utils.rb
|
99
|
+
- spec/application_runner.rb
|
100
|
+
- spec/application_scenario.rb
|
101
|
+
- spec/fixtures/authorize_request_token.txt
|
102
|
+
- spec/fixtures/unauthorized_request_token.txt
|
103
|
+
- spec/spec_helper.rb
|
104
|
+
- spec/warden_oauth/manager_spec.rb
|
105
|
+
- spec/warden_oauth/strategy_spec.rb
|
106
|
+
- warden_oauth.gemspec
|
107
|
+
has_rdoc: true
|
108
|
+
homepage: http://github.com/roman/warden_oauth
|
109
|
+
licenses: []
|
110
|
+
|
111
|
+
post_install_message:
|
112
|
+
rdoc_options:
|
113
|
+
- --charset=UTF-8
|
114
|
+
require_paths:
|
115
|
+
- lib
|
116
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: "0"
|
121
|
+
version:
|
122
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: "0"
|
127
|
+
version:
|
128
|
+
requirements: []
|
129
|
+
|
130
|
+
rubyforge_project: warden_oauth
|
131
|
+
rubygems_version: 1.3.5
|
132
|
+
signing_key:
|
133
|
+
specification_version: 3
|
134
|
+
summary: OAuth Strategy generator for Warden Authentication Framework
|
135
|
+
test_files:
|
136
|
+
- spec/application_runner.rb
|
137
|
+
- spec/application_scenario.rb
|
138
|
+
- spec/spec_helper.rb
|
139
|
+
- spec/warden_oauth/manager_spec.rb
|
140
|
+
- spec/warden_oauth/strategy_spec.rb
|