warden 0.5.3 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +8 -5
- data/README.textile +1 -1
- data/lib/warden.rb +7 -4
- data/lib/warden/declarable.rb +43 -0
- data/lib/warden/hooks.rb +121 -0
- data/lib/warden/manager.rb +52 -21
- data/lib/warden/mixins/common.rb +11 -2
- data/lib/warden/proxy.rb +88 -32
- data/lib/warden/serializers.rb +20 -0
- data/lib/warden/serializers/base.rb +38 -0
- data/lib/warden/serializers/cookie.rb +34 -0
- data/lib/warden/serializers/session.rb +30 -0
- data/lib/warden/strategies.rb +18 -0
- data/lib/warden/{authentication/strategy_base.rb → strategies/base.rb} +27 -2
- data/lib/warden/version.rb +1 -1
- data/spec/helpers/request_helper.rb +14 -12
- data/spec/{warden → helpers}/strategies/failz.rb +0 -0
- data/spec/{warden → helpers}/strategies/invalid.rb +0 -0
- data/spec/{warden → helpers}/strategies/pass.rb +0 -0
- data/spec/{warden → helpers}/strategies/pass_without_user.rb +0 -0
- data/spec/{warden → helpers}/strategies/password.rb +0 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/warden/authenticated_data_store_spec.rb +4 -4
- data/spec/warden/manager_spec.rb +0 -8
- data/spec/warden/proxy_spec.rb +61 -10
- data/spec/warden/serializers/cookie_spec.rb +60 -0
- data/spec/warden/serializers/session_spec.rb +47 -0
- data/spec/warden/serializers_spec.rb +96 -0
- data/spec/warden/{strategy_base_spec.rb → strategies/base_spec.rb} +1 -1
- data/spec/warden/strategies_spec.rb +19 -15
- data/warden.gemspec +28 -18
- metadata +28 -18
- data/VERSION +0 -1
- data/lib/warden/authentication/hooks.rb +0 -124
- data/lib/warden/authentication/strategies.rb +0 -59
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'warden/declarable'
|
3
|
+
|
4
|
+
module Warden
|
5
|
+
module Serializers
|
6
|
+
extend Warden::Declarable
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def check_validity!(label, serializer)
|
10
|
+
[:fetch, :store, :stored?, :delete].each do |method|
|
11
|
+
next if serializer.method_defined?(method)
|
12
|
+
raise NoMethodError, "#{method} is not declared in the #{label.inspect} serializer"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
alias :_serializers :_declarations
|
17
|
+
end # << self
|
18
|
+
|
19
|
+
end # Serializers
|
20
|
+
end # Warden
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Warden
|
3
|
+
module Serializers
|
4
|
+
# A serializer is a place where you put the logic to serializing and deserializing an user. All serializers
|
5
|
+
# inherits from Warden::Serializers::Base.
|
6
|
+
#
|
7
|
+
# The Warden::Serializers.add method is a simple way to provide custom serializers. In order to do so,
|
8
|
+
# you _must_ declare @store@, @fetch@, @delete@ and @stored?@ methods.
|
9
|
+
#
|
10
|
+
# The parameters for Warden::Serializers.add method is:
|
11
|
+
# <label: Symbol> The label is the name given to a serializer. Use the label to refer to the serializer when authenticating
|
12
|
+
# <serializer: Class|nil> The optional serializer argument if set _must_ be a class that inherits from Warden::Serializers::Base
|
13
|
+
# <block> The block acts as a convinient way to declare your serializer. Inside is the class definition of a serializer.
|
14
|
+
#
|
15
|
+
# Check Session and Cookie serializers for more information.
|
16
|
+
#
|
17
|
+
class Base
|
18
|
+
attr_accessor :env
|
19
|
+
include ::Warden::Mixins::Common
|
20
|
+
|
21
|
+
def initialize(env)
|
22
|
+
@env = env
|
23
|
+
end
|
24
|
+
|
25
|
+
def key_for(scope)
|
26
|
+
"warden.user.#{scope}.key"
|
27
|
+
end
|
28
|
+
|
29
|
+
def serialize(user)
|
30
|
+
user
|
31
|
+
end
|
32
|
+
|
33
|
+
def deserialize(key)
|
34
|
+
key
|
35
|
+
end
|
36
|
+
end # Base
|
37
|
+
end # Serializers
|
38
|
+
end # Warden
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Warden
|
3
|
+
module Serializers
|
4
|
+
# A cookie serializer provided by Warden. You need to implement the serialize and deserialize
|
5
|
+
# methods in order to use it.
|
6
|
+
class Cookie < Base
|
7
|
+
def store(user, scope)
|
8
|
+
response.set_cookie key_for(scope), default_options(user)
|
9
|
+
end
|
10
|
+
|
11
|
+
def fetch(scope)
|
12
|
+
key = request.cookies[key_for(scope)]
|
13
|
+
return nil unless key
|
14
|
+
user = deserialize(key)
|
15
|
+
delete(scope) unless user
|
16
|
+
user
|
17
|
+
end
|
18
|
+
|
19
|
+
def stored?(scope)
|
20
|
+
!!request.cookies[key_for(scope)]
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete(scope, user=nil)
|
24
|
+
response.delete_cookie(key_for(scope))
|
25
|
+
end
|
26
|
+
|
27
|
+
def default_options(user)
|
28
|
+
{ :value => serialize(user), :expires => (Time.now + 7 * 24 * 3600), :path => "/" }
|
29
|
+
end
|
30
|
+
end # Cookie
|
31
|
+
|
32
|
+
Serializers.add(:cookie, Cookie)
|
33
|
+
end # Serializers
|
34
|
+
end # Warden
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Warden
|
3
|
+
module Serializers
|
4
|
+
# A session serializer provided by Warden. You need to implement the serialize and deserialize
|
5
|
+
# methods in order to use it.
|
6
|
+
class Session < Base
|
7
|
+
def store(user, scope)
|
8
|
+
session[key_for(scope)] = serialize(user)
|
9
|
+
end
|
10
|
+
|
11
|
+
def fetch(scope)
|
12
|
+
key = session[key_for(scope)]
|
13
|
+
return nil unless key
|
14
|
+
user = deserialize(key)
|
15
|
+
delete(scope) unless user
|
16
|
+
user
|
17
|
+
end
|
18
|
+
|
19
|
+
def stored?(scope)
|
20
|
+
!!session[key_for(scope)]
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete(scope, user=nil)
|
24
|
+
session.delete(key_for(scope))
|
25
|
+
end
|
26
|
+
end # Session
|
27
|
+
|
28
|
+
Serializers.add(:session, Session)
|
29
|
+
end # Serializers
|
30
|
+
end # Warden
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'warden/declarable'
|
3
|
+
|
4
|
+
module Warden
|
5
|
+
module Strategies
|
6
|
+
extend Warden::Declarable
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def check_validity!(label, strategy)
|
10
|
+
return if strategy.method_defined?(:authenticate!)
|
11
|
+
raise NoMethodError, "authenticate! is not declared in the #{label.inspect} strategy"
|
12
|
+
end
|
13
|
+
|
14
|
+
alias :_strategies :_declarations
|
15
|
+
end # << self
|
16
|
+
|
17
|
+
end # Strategies
|
18
|
+
end # Warden
|
@@ -1,6 +1,32 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Warden
|
3
3
|
module Strategies
|
4
|
+
# A strategy is a place where you can put logic related to authentication. Any strategy inherits
|
5
|
+
# from Warden::Strategies::Base.
|
6
|
+
#
|
7
|
+
# The Warden::Strategies.add method is a simple way to provide custom strategies.
|
8
|
+
# You _must_ declare an @authenticate!@ method.
|
9
|
+
# You _may_ provide a @valid?@ method.
|
10
|
+
# The valid method should return true or false depending on if the strategy is a valid one for the request.
|
11
|
+
#
|
12
|
+
# The parameters for Warden::Strategies.add method is:
|
13
|
+
# <label: Symbol> The label is the name given to a strategy. Use the label to refer to the strategy when authenticating
|
14
|
+
# <strategy: Class|nil> The optional stragtegy argument if set _must_ be a class that inherits from Warden::Strategies::Base and _must_
|
15
|
+
# implement an @authenticate!@ method
|
16
|
+
# <block> The block acts as a convinient way to declare your strategy. Inside is the class definition of a strategy.
|
17
|
+
#
|
18
|
+
# Examples:
|
19
|
+
#
|
20
|
+
# Block Declared Strategy:
|
21
|
+
# Warden::Strategies.add(:foo) do
|
22
|
+
# def authenticate!
|
23
|
+
# # authentication logic
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# Class Declared Strategy:
|
28
|
+
# Warden::Strategies.add(:foo, MyStrategy)
|
29
|
+
#
|
4
30
|
class Base
|
5
31
|
# :api: public
|
6
32
|
attr_accessor :user, :message
|
@@ -24,7 +50,7 @@ module Warden
|
|
24
50
|
@halted = false
|
25
51
|
end
|
26
52
|
|
27
|
-
# The method that is called from above.
|
53
|
+
# The method that is called from above. This method calls the underlying authenticate! method
|
28
54
|
# :api: private
|
29
55
|
def _run! # :nodoc:
|
30
56
|
result = authenticate!
|
@@ -107,7 +133,6 @@ module Warden
|
|
107
133
|
headers["Content-Type"] = opts[:content_type] || 'text/plain'
|
108
134
|
|
109
135
|
@message = opts[:message].nil? ? "You are being redirected to #{headers["Location"]}" : opts[:message]
|
110
|
-
|
111
136
|
@result = :redirect
|
112
137
|
|
113
138
|
headers["Location"]
|
data/lib/warden/version.rb
CHANGED
@@ -1,49 +1,51 @@
|
|
1
1
|
module Warden::Spec
|
2
2
|
module Helpers
|
3
|
-
|
3
|
+
|
4
4
|
FAILURE_APP = lambda{|e|[401, {"Content-Type" => "text/plain"}, ["You Fail!"]] }
|
5
|
-
|
5
|
+
|
6
6
|
def env_with_params(path = "/", params = {})
|
7
7
|
method = params.fetch(:method, "GET")
|
8
8
|
Rack::MockRequest.env_for(path, :input => Rack::Utils.build_query(params),
|
9
9
|
'HTTP_VERSION' => '1.1',
|
10
10
|
'REQUEST_METHOD' => "#{method}")
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def setup_rack(app = nil, opts = {}, &block)
|
14
14
|
app ||= block if block_given?
|
15
|
-
opts[:default_strategies]
|
15
|
+
opts[:default_strategies] ||= [:password]
|
16
|
+
opts[:default_serializers] ||= [:session]
|
16
17
|
opts[:failure_app] ||= Warden::Spec::Helpers::FAILURE_APP
|
17
|
-
Rack::Builder.new do
|
18
|
+
Rack::Builder.new do
|
18
19
|
use Warden::Spec::Helpers::Session
|
19
20
|
use Warden::Manager, opts do |manager|
|
20
21
|
manager.failure_app = Warden::Spec::Helpers::FAILURE_APP
|
21
22
|
manager.default_strategies *opts[:default_strategies]
|
23
|
+
manager.default_serializers *opts[:default_serializers]
|
22
24
|
end
|
23
25
|
run app
|
24
26
|
end
|
25
27
|
end
|
26
|
-
|
28
|
+
|
27
29
|
def valid_response
|
28
|
-
|
30
|
+
Rack::Response.new("OK").finish
|
29
31
|
end
|
30
|
-
|
32
|
+
|
31
33
|
def failure_app
|
32
34
|
Warden::Spec::Helpers::FAILURE_APP
|
33
35
|
end
|
34
|
-
|
36
|
+
|
35
37
|
def success_app
|
36
38
|
lambda{|e| [200, {"Content-Type" => "text/plain"}, ["You Win"]]}
|
37
39
|
end
|
38
|
-
|
40
|
+
|
39
41
|
class Session
|
40
42
|
attr_accessor :app
|
41
43
|
def initialize(app,configs = {})
|
42
44
|
@app = app
|
43
45
|
end
|
44
|
-
|
46
|
+
|
45
47
|
def call(e)
|
46
|
-
e['rack.session'] ||= {}
|
48
|
+
e['rack.session'] ||= {}
|
47
49
|
@app.call(e)
|
48
50
|
end
|
49
51
|
end # session
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/spec/spec_helper.rb
CHANGED
@@ -12,7 +12,7 @@ Spec::Runner.configure do |config|
|
|
12
12
|
config.include(Warden::Spec::Helpers)
|
13
13
|
|
14
14
|
def load_strategies
|
15
|
-
Dir[File.join(File.dirname(__FILE__), "
|
15
|
+
Dir[File.join(File.dirname(__FILE__), "helpers", "strategies", "**/*.rb")].each do |f|
|
16
16
|
load f
|
17
17
|
end
|
18
18
|
end
|
@@ -5,9 +5,9 @@ describe "authenticated data store" do
|
|
5
5
|
before(:each) do
|
6
6
|
@env = env_with_params
|
7
7
|
@env['rack.session'] = {
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
"warden.user.foo.key" => "foo user",
|
9
|
+
"warden.user.default.key" => "default user",
|
10
|
+
:foo => "bar"
|
11
11
|
}
|
12
12
|
end
|
13
13
|
|
@@ -18,7 +18,7 @@ describe "authenticated data store" do
|
|
18
18
|
e['warden'].should be_authenticated
|
19
19
|
e['warden'].should be_authenticated(:foo)
|
20
20
|
|
21
|
-
# Store the data for :
|
21
|
+
# Store the data for :default
|
22
22
|
e['warden'].session[:key] = "value"
|
23
23
|
valid_response
|
24
24
|
end
|
data/spec/warden/manager_spec.rb
CHANGED
@@ -12,14 +12,6 @@ describe Warden::Manager do
|
|
12
12
|
env["warden"].should be_an_instance_of(Warden::Proxy)
|
13
13
|
end
|
14
14
|
|
15
|
-
describe "user storage" do
|
16
|
-
it "should take a user and store it in the provided session" do
|
17
|
-
session = {}
|
18
|
-
Warden::Manager._store_user("The User", session, "some_scope")
|
19
|
-
session["warden.user.some_scope.key"].should == "The User"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
15
|
describe "thrown auth" do
|
24
16
|
before(:each) do
|
25
17
|
@basic_app = lambda{|env| [200,{'Content-Type' => 'text/plain'},'OK']}
|
data/spec/warden/proxy_spec.rb
CHANGED
@@ -165,9 +165,9 @@ describe Warden::Proxy do
|
|
165
165
|
env['warden'].authenticate(:pass, :scope => :foo)
|
166
166
|
env['warden'].authenticate(:pass, :scope => :bar)
|
167
167
|
env['warden'].authenticate(:password)
|
168
|
-
env['warden'].authenticated?(:foo).should
|
169
|
-
env['warden'].authenticated?(:bar).should
|
170
|
-
env['warden'].authenticated?.should
|
168
|
+
env['warden'].authenticated?(:foo).should be_true
|
169
|
+
env['warden'].authenticated?(:bar).should be_true
|
170
|
+
env['warden'].authenticated?.should be_false
|
171
171
|
valid_response
|
172
172
|
end
|
173
173
|
env = env_with_params
|
@@ -195,7 +195,7 @@ describe Warden::Proxy do
|
|
195
195
|
end
|
196
196
|
end # describe "authentication"
|
197
197
|
|
198
|
-
describe "stored
|
198
|
+
describe "stored?" do
|
199
199
|
before(:each) do
|
200
200
|
@env['rack.session'] ||= {}
|
201
201
|
@env['rack.session']['warden.user.default.key'] = "User"
|
@@ -203,7 +203,7 @@ describe Warden::Proxy do
|
|
203
203
|
|
204
204
|
it "returns true if user key is stored in session" do
|
205
205
|
app = lambda do |env|
|
206
|
-
env['warden'].
|
206
|
+
env['warden'].stored?.should be_true
|
207
207
|
valid_response
|
208
208
|
end
|
209
209
|
setup_rack(app).call(@env)
|
@@ -212,11 +212,31 @@ describe Warden::Proxy do
|
|
212
212
|
it "returns false if user key is not stored in session" do
|
213
213
|
@env['rack.session'].delete("warden.user.default.key")
|
214
214
|
app = lambda do |env|
|
215
|
-
env['warden'].
|
215
|
+
env['warden'].stored?.should be_false
|
216
216
|
valid_response
|
217
217
|
end
|
218
218
|
setup_rack(app).call(@env)
|
219
219
|
end
|
220
|
+
|
221
|
+
it "returns false if scope given is not stored in session" do
|
222
|
+
app = lambda do |env|
|
223
|
+
env['warden'].stored?.should be_true
|
224
|
+
env['warden'].stored?(:another).should be_false
|
225
|
+
valid_response
|
226
|
+
end
|
227
|
+
setup_rack(app).call(@env)
|
228
|
+
end
|
229
|
+
|
230
|
+
it "returns based on the given store" do
|
231
|
+
@env['rack.session'].delete("warden.user.default.key")
|
232
|
+
@env["HTTP_COOKIE"] = "warden.user.default.key=user;"
|
233
|
+
app = lambda do |env|
|
234
|
+
env['warden'].stored?(:default, :session).should be_false
|
235
|
+
env['warden'].stored?(:default, :cookie).should be_true
|
236
|
+
valid_response
|
237
|
+
end
|
238
|
+
setup_rack(app, :default_serializers => [:session, :cookie]).call(@env)
|
239
|
+
end
|
220
240
|
end
|
221
241
|
|
222
242
|
describe "set user" do
|
@@ -232,6 +252,19 @@ describe Warden::Proxy do
|
|
232
252
|
setup_rack(app).call(env)
|
233
253
|
end
|
234
254
|
|
255
|
+
it "should store the user in all serializers" do
|
256
|
+
env = env_with_params("/")
|
257
|
+
app = lambda do |env|
|
258
|
+
env['warden'].authenticate(:pass)
|
259
|
+
env['warden'].should be_authenticated
|
260
|
+
env['warden'].user.should == "Valid User"
|
261
|
+
valid_response
|
262
|
+
end
|
263
|
+
setup_rack(app, :default_serializers => [:session, :cookie]).call(env)
|
264
|
+
headers = env['warden'].serializers.last.response.headers
|
265
|
+
headers['Set-Cookie'].split(";").first.should == "warden.user.default.key=Valid+User"
|
266
|
+
end
|
267
|
+
|
235
268
|
it "should not store the user if the :store option is set to false" do
|
236
269
|
env = env_with_params("/")
|
237
270
|
app = lambda do |e|
|
@@ -268,6 +301,15 @@ describe Warden::Proxy do
|
|
268
301
|
setup_rack(app).call(@env)
|
269
302
|
end
|
270
303
|
|
304
|
+
it "should load user from others serializers" do
|
305
|
+
@env["HTTP_COOKIE"] = "warden.user.default.key=user;"
|
306
|
+
app = lambda do |env|
|
307
|
+
env['warden'].user.should == "user"
|
308
|
+
valid_response
|
309
|
+
end
|
310
|
+
setup_rack(app, :default_serializers => [:session, :cookie]).call(@env)
|
311
|
+
end
|
312
|
+
|
271
313
|
describe "previously logged in" do
|
272
314
|
|
273
315
|
before(:each) do
|
@@ -299,14 +341,14 @@ describe Warden::Proxy do
|
|
299
341
|
before(:each) do
|
300
342
|
@env = env = env_with_params
|
301
343
|
@env['rack.session'] = {"warden.user.default.key" => "default key", "warden.user.foo.key" => "foo key", :foo => "bar"}
|
302
|
-
app = lambda do |e|
|
344
|
+
@app = lambda do |e|
|
303
345
|
e['warden'].logout(env['warden.spec.which_logout'])
|
304
346
|
valid_response
|
305
347
|
end
|
306
|
-
@app = setup_rack(app)
|
307
348
|
end
|
308
349
|
|
309
350
|
it "should logout only the scoped foo user" do
|
351
|
+
@app = setup_rack(@app)
|
310
352
|
@env['warden.spec.which_logout'] = :foo
|
311
353
|
@app.call(@env)
|
312
354
|
@env['rack.session']['warden.user.default.key'].should == "default key"
|
@@ -315,6 +357,7 @@ describe Warden::Proxy do
|
|
315
357
|
end
|
316
358
|
|
317
359
|
it "should logout only the scoped default user" do
|
360
|
+
@app = setup_rack(@app)
|
318
361
|
@env['warden.spec.which_logout'] = :default
|
319
362
|
@app.call(@env)
|
320
363
|
@env['rack.session']['warden.user.default.key'].should be_nil
|
@@ -343,7 +386,6 @@ describe Warden::Proxy do
|
|
343
386
|
end
|
344
387
|
setup_rack(app).call(@env)
|
345
388
|
@env['warden'].user.should be_nil
|
346
|
-
|
347
389
|
end
|
348
390
|
|
349
391
|
it "should clear the session data when logging out" do
|
@@ -357,6 +399,15 @@ describe Warden::Proxy do
|
|
357
399
|
setup_rack(app).call(@env)
|
358
400
|
end
|
359
401
|
|
402
|
+
it "should clear the session in all serializers" do
|
403
|
+
@app = setup_rack(@app, :default_serializers => [:session, :cookie])
|
404
|
+
@env['warden.spec.which_logout'] = :default
|
405
|
+
@app.call(@env)
|
406
|
+
@env['warden'].serializers.last.should_not be_nil
|
407
|
+
headers = @env['warden'].serializers.last.response.headers
|
408
|
+
headers['Set-Cookie'].first.split(";").first.should == "warden.user.default.key="
|
409
|
+
end
|
410
|
+
|
360
411
|
it "should clear out the session by calling reset_session! so that plugins can setup their own session clearing" do
|
361
412
|
@env['rack.session'].should_not be_nil
|
362
413
|
app = lambda do |e|
|
@@ -395,7 +446,7 @@ describe Warden::Proxy do
|
|
395
446
|
it "should return false for authenticated when there are no valid? strategies" do
|
396
447
|
@env['rack.session'] = {}
|
397
448
|
app = lambda do |e|
|
398
|
-
e['warden'].authenticated?(:invalid).should
|
449
|
+
e['warden'].authenticated?(:invalid).should be_false
|
399
450
|
end
|
400
451
|
setup_rack(app).call(@env)
|
401
452
|
end
|