danski-ooh-auth 0.1.2
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/LICENSE +20 -0
- data/Rakefile +58 -0
- data/app/controllers/application.rb +16 -0
- data/app/controllers/authenticating_clients.rb +60 -0
- data/app/controllers/tokens.rb +94 -0
- data/app/helpers/application_helper.rb +64 -0
- data/app/helpers/authenticating_clients_helper.rb +5 -0
- data/app/helpers/authentications_helper.rb +5 -0
- data/app/models/authenticating_client.rb +12 -0
- data/app/models/authenticating_client/dm_authenticating_client.rb +71 -0
- data/app/models/token.rb +12 -0
- data/app/models/token/dm_token.rb +150 -0
- data/app/views/authenticating_clients/_help.html.erb +1 -0
- data/app/views/authenticating_clients/edit.html.erb +27 -0
- data/app/views/authenticating_clients/index.html.erb +24 -0
- data/app/views/authenticating_clients/new.html.erb +47 -0
- data/app/views/authenticating_clients/show.html.erb +40 -0
- data/app/views/layout/ooh_auth.html.erb +23 -0
- data/app/views/tokens/create.html.erb +34 -0
- data/app/views/tokens/edit.html.erb +4 -0
- data/app/views/tokens/new.html.erb +52 -0
- data/app/views/tokens/show.html.erb +1 -0
- data/lib/ooh-auth.rb +103 -0
- data/lib/ooh-auth/authentication_mixin.rb +13 -0
- data/lib/ooh-auth/controller_mixin.rb +38 -0
- data/lib/ooh-auth/key_generators.rb +57 -0
- data/lib/ooh-auth/merbtasks.rb +103 -0
- data/lib/ooh-auth/request_verification_mixin.rb +160 -0
- data/lib/ooh-auth/slicetasks.rb +18 -0
- data/lib/ooh-auth/spectasks.rb +65 -0
- data/lib/ooh-auth/strategies/oauth.rb +16 -0
- data/public/javascripts/master.js +0 -0
- data/public/stylesheets/master.css +2 -0
- data/readme.markdown +43 -0
- data/spec/controllers/application_spec.rb +35 -0
- data/spec/controllers/authenticating_clients_spec.rb +119 -0
- data/spec/controllers/tokens_spec.rb +173 -0
- data/spec/merb-auth-slice-fullfat_spec.rb +41 -0
- data/spec/models/authenticating_client_spec.rb +44 -0
- data/spec/models/oauth_strategy_spec.rb +48 -0
- data/spec/models/request_verification_mixin_spec.rb +121 -0
- data/spec/models/token_spec.rb +139 -0
- data/spec/spec_fixtures.rb +19 -0
- data/spec/spec_helper.rb +107 -0
- data/stubs/app/controllers/application.rb +2 -0
- data/stubs/app/controllers/main.rb +2 -0
- metadata +133 -0
@@ -0,0 +1,119 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
|
2
|
+
|
3
|
+
describe OohAuth::AuthenticatingClients do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
Merb::Router.prepare do
|
7
|
+
add_slice(:OohAuth)
|
8
|
+
end if standalone?
|
9
|
+
@controller = dispatch_to(OohAuth::AuthenticatingClients, :index)
|
10
|
+
@prefix = OohAuth[:path_prefix]
|
11
|
+
end
|
12
|
+
|
13
|
+
after :all do
|
14
|
+
Merb::Router.reset! if standalone?
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "index action" do
|
18
|
+
it "should render successfully without authentication" do
|
19
|
+
@controller.should be_successful
|
20
|
+
lambda {@controller = dispatch_to(OohAuth::AuthenticatingClients, :new)}.should raise_error(Merb::Controller::Unauthenticated)
|
21
|
+
end
|
22
|
+
it "should show a list of clients when authenticated"
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "new/create action" do
|
26
|
+
before :each do
|
27
|
+
@user = user_class.gen
|
28
|
+
|
29
|
+
@bad_authenticating_client_attrs = OohAuth::AuthenticatingClient.gen.attributes
|
30
|
+
[:name, :user_id].each {|a| @bad_authenticating_client_attrs.delete(a) }
|
31
|
+
|
32
|
+
@good_authenticating_client_attrs = OohAuth::AuthenticatingClient.gen(:kind=>"desktop").attributes
|
33
|
+
[:id, :secret, :api_key, :user_id].each {|a| @good_authenticating_client_attrs.delete(a) }
|
34
|
+
@good_authenticating_client_attrs[:name] = "unique fo realz"
|
35
|
+
|
36
|
+
@controller = OohAuth::AuthenticatingClients.new(Merb::Test::RequestHelper::FakeRequest.new)
|
37
|
+
@controller.request.session.user = @user
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should show validation messages when creation is attempted with bad data" do
|
41
|
+
ac_count = OohAuth::AuthenticatingClient.count
|
42
|
+
@controller.create(@bad_authenticating_client_attrs)
|
43
|
+
@controller.status.should == 200
|
44
|
+
@controller.assigns(:authenticating_client).user_id.should == @user.id
|
45
|
+
ac_count.should == OohAuth::AuthenticatingClient.count
|
46
|
+
end
|
47
|
+
it "should create the registration and display the app details when good data is entered" do
|
48
|
+
ac_count = OohAuth::AuthenticatingClient.count
|
49
|
+
@controller.create(@good_authenticating_client_attrs)
|
50
|
+
@controller.assigns(:authenticating_client).should be_valid
|
51
|
+
@controller.assigns(:authenticating_client).user_id.should == @user.id
|
52
|
+
@controller.status.should == 201
|
53
|
+
@controller.headers['Location'].should == @controller.slice_url(:authenticating_client, @controller.assigns(:authenticating_client))
|
54
|
+
(ac_count + 1).should == OohAuth::AuthenticatingClient.count
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "show action" do
|
59
|
+
before :each do
|
60
|
+
@user = user_class.gen
|
61
|
+
@authenticating_client = OohAuth::AuthenticatingClient.gen(:user=>@user)
|
62
|
+
@other_authenticating_client = OohAuth::AuthenticatingClient.gen
|
63
|
+
@controller = OohAuth::AuthenticatingClients.new(Merb::Test::RequestHelper::FakeRequest.new)
|
64
|
+
@controller.request.session.user = @user
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should raise NotFound for users other than the app's owning user" do
|
68
|
+
lambda { @controller.show(@other_authenticating_client.id)}.should raise_error(Merb::Controller::NotFound)
|
69
|
+
end
|
70
|
+
it "should successfully show the app data for the app's owning user" do
|
71
|
+
@controller.show(@authenticating_client.id)
|
72
|
+
@controller.should be_successful
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "edit/update action" do
|
77
|
+
before :each do
|
78
|
+
@user = user_class.gen
|
79
|
+
@authenticating_client = OohAuth::AuthenticatingClient.gen(:user=>@user)
|
80
|
+
@other_authenticating_client = OohAuth::AuthenticatingClient.gen
|
81
|
+
@controller = OohAuth::AuthenticatingClients.new(Merb::Test::RequestHelper::FakeRequest.new)
|
82
|
+
@controller.request.session.user = @user
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should raise NotFound for the wrong user on GET" do
|
86
|
+
lambda {@controller.edit(@other_authenticating_client.id)}.should raise_error(Merb::Controller::NotFound)
|
87
|
+
end
|
88
|
+
it "should raise NotFound for the wrong user on POST/PUT" do
|
89
|
+
lambda {@controller.update(@other_authenticating_client.id, {:name=>"renamed!"})}.should raise_error(Merb::Controller::NotFound)
|
90
|
+
end
|
91
|
+
it "should show a form to the app's owning user" do
|
92
|
+
@controller.edit(@authenticating_client.id)
|
93
|
+
@controller.should be_successful
|
94
|
+
end
|
95
|
+
it "cannot be used to reassign apps to other users" #do
|
96
|
+
# Waiting on ticket: http://wm.lighthouseapp.com/projects/4819/tickets/669-problem-with-protected-attribute-mass-assignment#ticket-669-1
|
97
|
+
# related to problems preventing mass-assignment.
|
98
|
+
# @controller.update(@authenticating_client.id, {:user_id=>@user.id+50})
|
99
|
+
# @controller.assigns(:authenticating_client).user_id.should == @user.id
|
100
|
+
#end
|
101
|
+
it "should show a form with errors when given bad input" do
|
102
|
+
@controller.update(@authenticating_client.id, {:name=>""})
|
103
|
+
@controller.should be_successful
|
104
|
+
@controller.assigns(:authenticating_client).should_not be_valid
|
105
|
+
end
|
106
|
+
it "should redirect to the resource on successful update" do
|
107
|
+
@controller.update(@authenticating_client.id, {:name=>"renamed renamed renamed"})
|
108
|
+
@controller.status.should == 302
|
109
|
+
@controller.should redirect_to(@controller.slice_url(:authenticating_client, @controller.assigns(:authenticating_client)))
|
110
|
+
@controller.assigns(:authenticating_client).should be_valid
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "delete action" do
|
115
|
+
it "should not be destroyable by any user other than the owning user"
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
|
2
|
+
|
3
|
+
describe OohAuth::Tokens do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@user = user_class.gen
|
7
|
+
@authenticating_client = OohAuth::AuthenticatingClient.gen
|
8
|
+
@other_authenticating_client = OohAuth::AuthenticatingClient.gen
|
9
|
+
@receipt = OohAuth::Token.create_request_key(@authenticating_client, 1.hour.since)
|
10
|
+
@token = OohAuth::Token.create_request_key(@authenticating_client, 1.hour.since)
|
11
|
+
@token.activate!(@user)
|
12
|
+
@bad_receipt = OohAuth::Token.create_request_key(@other_authenticating_client, 1.hour.since)
|
13
|
+
@controller = dispatch_to(OohAuth::Public, :index)
|
14
|
+
end
|
15
|
+
|
16
|
+
before :all do
|
17
|
+
Merb::Router.prepare do
|
18
|
+
add_slice(:OohAuth)
|
19
|
+
end if standalone?
|
20
|
+
end
|
21
|
+
|
22
|
+
after :all do
|
23
|
+
Merb::Router.reset! if standalone?
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "index action" do
|
27
|
+
%w(js yaml xml html).each do |format|
|
28
|
+
it "#{format} requests should generate an anonymous receipt when sent GET with a consumer and no other information." do
|
29
|
+
@controller = get(sign_url_with(@authenticating_client, @controller.slice_url(:tokens, :format=>format)))
|
30
|
+
@controller.should be_successful
|
31
|
+
request_token = @controller.assigns(:token)
|
32
|
+
request_token.should be_kind_of(OohAuth::Token)
|
33
|
+
request_token.activated?.should be_false
|
34
|
+
request_token.new_record?.should be_false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should return OAuth-format key responses if no format is specified" do
|
39
|
+
@controller = get(sign_url_with(@authenticating_client, @controller.slice_url(:tokens, :format=>"html")))
|
40
|
+
request_token = @controller.assigns(:token)
|
41
|
+
@controller.body.should == "oauth_token=#{request_token.token_key}&oauth_token_secret=#{request_token.secret}"
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
it "should generate nothing and return a 406 not acceptable when the request is not signed or contains an incorrect API key" do
|
46
|
+
lambda {get(@controller.slice_url(:tokens, :oauth_consumer_key=>@authenticating_client.api_key))}.should raise_error(Merb::Controller::NotAcceptable)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should generate an authorised access key when sent GET with a consumer key and unauthorized request key when the request key is activated." do
|
50
|
+
@controller = OohAuth::Tokens.new(
|
51
|
+
request_signed_by(@authenticating_client, {:oauth_token=>@token.token_key}, {}, {:request_uri=>@controller.slice_url(:tokens)})
|
52
|
+
)
|
53
|
+
@controller.index
|
54
|
+
@controller.should be_successful
|
55
|
+
auth = @controller.assigns(:token)
|
56
|
+
auth.should be_kind_of(OohAuth::Token)
|
57
|
+
auth.activated?.should be_true
|
58
|
+
end
|
59
|
+
it "should not generate an auth token if the given token does not belong to the given application" do
|
60
|
+
@controller = OohAuth::Tokens.new(
|
61
|
+
request_signed_by(@authenticating_client, {:oauth_token=>@bad_receipt.token_key}, {}, {:request_uri=>@controller.slice_url(:tokens)})
|
62
|
+
)
|
63
|
+
lambda {@controller.index}.should raise_error(Merb::Controller::NotAcceptable)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
describe "new action" do
|
69
|
+
before :all do
|
70
|
+
@user = user_class.gen
|
71
|
+
@desktop_app = OohAuth::AuthenticatingClient.gen(:kind=>"desktop")
|
72
|
+
@request_key = OohAuth::Token.create_request_key(@desktop_app, 1.hour.since)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should require a login" do
|
76
|
+
lambda {@controller = get(sign_url_with(@desktop_app, @controller.slice_url(:new_token), :oauth_token=>@request_key.token_key)) }.
|
77
|
+
should raise_error(Merb::Controller::Unauthenticated)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should display a form to the user and locate the correct receipt from the database on GET" do
|
81
|
+
request = fake_request(:query_string=>"oauth_token=#{@request_key.token_key}&oauth_callback=http://www.feesh.com/index.php")
|
82
|
+
request.session.user = @user
|
83
|
+
@controller = OohAuth::Tokens.new(request)
|
84
|
+
doc = @controller.new
|
85
|
+
@controller.should be_successful
|
86
|
+
@controller.assigns(:authenticating_client).should == @desktop_app
|
87
|
+
@controller.assigns(:token).activated?.should be_false
|
88
|
+
doc.should contain(@controller.assigns(:authenticating_client).name)
|
89
|
+
end
|
90
|
+
it "should display nothing and return a 406 when the params contain an request key which is invalid" do
|
91
|
+
lambda do
|
92
|
+
@controller = get(sign_url_with(@authenticating_client, @controller.slice_url(:new_token), :oauth_consumer_key=>"DIDDLYSQUAT"))
|
93
|
+
end.should raise_error(Merb::Controller::NotAcceptable)
|
94
|
+
end
|
95
|
+
it "should raise unauthenticated when a client attempts to render the page using oauth credentials" do
|
96
|
+
@token.activated?.should be_true
|
97
|
+
@token.authenticating_client.should == @authenticating_client
|
98
|
+
lambda do
|
99
|
+
@controller = get(sign_url_with(@authenticating_client, @controller.slice_url(:new_token), :oauth_token=>@token.token_key))
|
100
|
+
end.should raise_error(Merb::Controller::Unauthenticated)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "create action" do
|
105
|
+
before :each do
|
106
|
+
@user = user_class.gen
|
107
|
+
@desktop_app = OohAuth::AuthenticatingClient.gen(:kind=>"desktop")
|
108
|
+
@request_key = OohAuth::Token.create_request_key(@desktop_app, 1.hour.since)
|
109
|
+
@access_key = OohAuth::Token.create_request_key(@desktop_app, 1.hour.since)
|
110
|
+
@access_key.activate!(@user)
|
111
|
+
@date = Date.today + 5.years
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should not activate a valid request token when any button other than 'allow' was clicked to submit the auth form" do
|
115
|
+
request = fake_request({}, {:post_body=>"oauth_token=#{@request_key.token_key}&commit=deny&"})
|
116
|
+
request.session.user = @user
|
117
|
+
@controller = OohAuth::Tokens.new(request)
|
118
|
+
response = @controller.create({})
|
119
|
+
auth = @controller.assigns(:token)
|
120
|
+
auth.user.should be_nil
|
121
|
+
auth.activated?.should be_false
|
122
|
+
response.should contain("You denied")
|
123
|
+
end
|
124
|
+
it "should activate a request token on POST when the 'allow' button was clicked to submit the auth form" do
|
125
|
+
request = fake_request({}, {:post_body=>"oauth_token=#{@request_key.token_key}&commit=allow&"})
|
126
|
+
request.session.user = @user
|
127
|
+
@controller = OohAuth::Tokens.new(request)
|
128
|
+
response = @controller.create({:expires=>@date.strftime("%Y-%m-%d"), :permissions=>"delete"})
|
129
|
+
auth = @controller.assigns(:token)
|
130
|
+
auth.user.should == @user
|
131
|
+
auth.authenticating_client.should == @desktop_app
|
132
|
+
auth.expires.should >= Date.today + 4.years + 364.days
|
133
|
+
auth.expires.should <= Date.today + 5.years + 1.days
|
134
|
+
auth.activated?.should be_true
|
135
|
+
response.should contain("You successfully authorized")
|
136
|
+
end
|
137
|
+
it "should redirect to the callback URL on successful activation if a callback url is given, appending oauth_token to the callback URL's parameters" do
|
138
|
+
request = fake_request({}, {:post_body=>"oauth_token=#{@request_key.token_key}&commit=allow&oauth_callback=#{Merb::Parse.escape("http://www.test.com/noflags")}"})
|
139
|
+
request.session.user = @user
|
140
|
+
@controller = OohAuth::Tokens.new(request)
|
141
|
+
response = @controller.create({})
|
142
|
+
@controller.assigns(:token).activated?.should be_true
|
143
|
+
@controller.should redirect_to("http://www.test.com/noflags?oauth_token=#{@controller.assigns(:token).token_key}")
|
144
|
+
end
|
145
|
+
it "should gracefully handle existing GET parameters on the callback url" do
|
146
|
+
request = fake_request({}, {:post_body=>"oauth_token=#{@request_key.token_key}&commit=allow&oauth_callback=#{Merb::Parse.escape("http://www.test.com/flags?foo=bar")}"})
|
147
|
+
request.session.user = @user
|
148
|
+
@controller = OohAuth::Tokens.new(request)
|
149
|
+
response = @controller.create({})
|
150
|
+
@controller.assigns(:token).activated?.should be_true
|
151
|
+
@controller.should redirect_to("http://www.test.com/flags?foo=bar&oauth_token=#{@controller.assigns(:token).token_key}")
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should require a user to be logged in via session" do
|
155
|
+
lambda do
|
156
|
+
@controller = post(sign_url_with(@authenticating_client, @controller.slice_url(:new_token), :oauth_token=>@access_key.token_key))
|
157
|
+
end.should raise_error(Merb::Controller::Unauthenticated)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
#
|
161
|
+
#describe "edit/update action" do
|
162
|
+
# it "should only be accessible by the token's owning user"
|
163
|
+
# it "should return 404 not found for other users"
|
164
|
+
# it "should only allow the expiry and permission level to be altered"
|
165
|
+
#end
|
166
|
+
#
|
167
|
+
#describe "delete/destroy action" do
|
168
|
+
# it "should only be accessible by the token's owning user"
|
169
|
+
# it "should return a 404 not found for other users"
|
170
|
+
# it "should remove all authentications for this user/application if multiple records are present"
|
171
|
+
#end
|
172
|
+
|
173
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe "OohAuth" do
|
4
|
+
|
5
|
+
describe "::KeyGenerators" do
|
6
|
+
|
7
|
+
before(:each) { @module = OohAuth::KeyGenerators }
|
8
|
+
|
9
|
+
it "should generate a different memorable password every time" do
|
10
|
+
past_items = []
|
11
|
+
100.times do |i|
|
12
|
+
key = @module::Password.gen
|
13
|
+
key.should =~ /^\d+[a-z]+[A-Z][a-z]+$/
|
14
|
+
past_items.should_not include(key)
|
15
|
+
past_items << key
|
16
|
+
end
|
17
|
+
end
|
18
|
+
it "should be able to generate long-form passphrases" do
|
19
|
+
past_items = []
|
20
|
+
100.times do |i|
|
21
|
+
key = @module::Passphrase.gen(5)
|
22
|
+
key.should =~ /^([a-z]+\s){4}([a-z]+)$/
|
23
|
+
key.split(" ").length.should == 5
|
24
|
+
past_items.should_not include(key)
|
25
|
+
past_items << key
|
26
|
+
end
|
27
|
+
end
|
28
|
+
it "should be able to generate alphanumeric nonmemorable keys" do
|
29
|
+
past_items = []
|
30
|
+
100.times do |i|
|
31
|
+
key = @module::Alphanum.gen(50)
|
32
|
+
key.should =~ /^[a-zA-Z0-9]{50}$/
|
33
|
+
key.length.should == 50
|
34
|
+
past_items.should_not include(key)
|
35
|
+
past_items << key
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), '..', "spec_helper" )
|
2
|
+
|
3
|
+
describe OohAuth::AuthenticatingClient do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
OohAuth::AuthenticatingClient.all.destroy!
|
7
|
+
@user = user_class.gen
|
8
|
+
@authenticating_clients = 10.of {OohAuth::AuthenticatingClient.gen}
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should generate a unique API key and a non-unique secret upon saving" do
|
12
|
+
keys = []
|
13
|
+
10.times do |i|
|
14
|
+
@authenticating_client = OohAuth::AuthenticatingClient.gen
|
15
|
+
@authenticating_client.api_key = nil
|
16
|
+
@authenticating_client.secret = nil
|
17
|
+
@authenticating_client.save
|
18
|
+
@authenticating_client.api_key.should be_kind_of(String)
|
19
|
+
@authenticating_client.api_key.length.should >= 10
|
20
|
+
keys << @authenticating_client.api_key
|
21
|
+
keys.uniq.length.should == keys.length
|
22
|
+
@authenticating_client.secret.length.should == 40
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should not change API keys when they are set" do
|
27
|
+
@authenticating_client = OohAuth::AuthenticatingClient.gen
|
28
|
+
@authenticating_client.new_record?.should be_false
|
29
|
+
@authenticating_client.name = "changed"
|
30
|
+
ak = @authenticating_client.api_key
|
31
|
+
ss = @authenticating_client.secret
|
32
|
+
@authenticating_client.save.should be_true
|
33
|
+
@authenticating_client.api_key.should == ak
|
34
|
+
@authenticating_client.secret.should == ss
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should not allow internal URLs to be given as callback URLs"
|
38
|
+
|
39
|
+
it "should return an empty array when find_for_user is called with nil" do
|
40
|
+
arr = OohAuth::AuthenticatingClient.find_for_user(nil)
|
41
|
+
arr.length.should == 0
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), '..', "spec_helper" )
|
2
|
+
|
3
|
+
describe Merb::Authentication::Strategies::OAuth do
|
4
|
+
|
5
|
+
before :all do
|
6
|
+
# Create a client and a user, and authorise the client against the user by creating a token
|
7
|
+
@authenticating_client = OohAuth::AuthenticatingClient.gen
|
8
|
+
@user = user_class.gen
|
9
|
+
@access = OohAuth::Token.create_request_key(@authenticating_client, 1.hour.since)
|
10
|
+
@access.activate!(@user).should be_true
|
11
|
+
@request = OohAuth::Token.create_request_key(@authenticating_client, 1.hour.since)
|
12
|
+
@request.activated?.should be_false
|
13
|
+
|
14
|
+
Merb::Router.prepare do
|
15
|
+
add_slice(:OohAuth)
|
16
|
+
match("/secrets").to(:controller=>"ooh_auth/secrets", :action=>"index").name(:secrets)
|
17
|
+
end if standalone?
|
18
|
+
end
|
19
|
+
|
20
|
+
after :all do
|
21
|
+
Merb::Router.reset! if standalone?
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should not authenticate with an unsigned request even if the given token is correct" do
|
25
|
+
request = fake_request(:request_uri=>"/secrets", :query_string=>"oauth_token=#{@access.token_key}&oauth_consumer_key=#{@authenticating_client.api_key}")
|
26
|
+
request.authentication_token.activated?.should be_true
|
27
|
+
request.consumer_key.should == @authenticating_client.api_key
|
28
|
+
request.token.should == @access.token_key
|
29
|
+
strat = Merb::Authentication::Strategies::OAuth.new(request, {})
|
30
|
+
strat.run!.should be_nil
|
31
|
+
end
|
32
|
+
it "should authenticate a signed request with a valid token" do
|
33
|
+
request = request_signed_by(@authenticating_client, {:oauth_token=>@access.token_key, :other_param=>"CHEEESE"})
|
34
|
+
request.authentication_token.activated?.should be_true
|
35
|
+
request.consumer_key.should == @authenticating_client.api_key
|
36
|
+
request.token.should == @access.token_key
|
37
|
+
strat = Merb::Authentication::Strategies::OAuth.new(request, {})
|
38
|
+
strat.run!.should == @user
|
39
|
+
end
|
40
|
+
it "should not authenticate a signed request with an expired token"
|
41
|
+
it "should not authenticate a signed request with a receipt but no token" do
|
42
|
+
request = request_signed_by(@authenticating_client, {:oauth_token=>@request.token_key})
|
43
|
+
request.authentication_token.activated?.should be_false
|
44
|
+
strat = Merb::Authentication::Strategies::OAuth.new(request, {})
|
45
|
+
strat.run!.should be_nil
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), '..', "spec_helper" )
|
2
|
+
|
3
|
+
require 'hmac-sha1'
|
4
|
+
require 'hmac-md5'
|
5
|
+
|
6
|
+
describe OohAuth::Request::VerificationMixin do
|
7
|
+
|
8
|
+
before :all do
|
9
|
+
Merb::Router.prepare do
|
10
|
+
add_slice(:OohAuth)
|
11
|
+
match("/secrets").to(:controller=>"ooh_auth/secrets", :action=>"index").name(:secrets)
|
12
|
+
end if standalone?
|
13
|
+
end
|
14
|
+
|
15
|
+
after :all do
|
16
|
+
Merb::Router.reset! if standalone?
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should be included in the Merb::Request and FakeRequest classes on slice initialisation" do
|
20
|
+
Merb::Request.include?(OohAuth::Request::VerificationMixin).should be_true
|
21
|
+
Merb::Test::RequestHelper::FakeRequest.include?(OohAuth::Request::VerificationMixin).should be_true
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "Signature verification" do
|
25
|
+
before :each do
|
26
|
+
@authenticating_client = OohAuth::AuthenticatingClient.gen
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should verify that a correctly-signed GET request is signed using GET parameters" do
|
30
|
+
req = request_signed_by(@authenticating_client, { :a=>"1", :b=>"3", :c=>"2"})
|
31
|
+
req.method.should == :get
|
32
|
+
req.authenticating_client.should == @authenticating_client
|
33
|
+
req.signed?.should be_true
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should include POST parameters when signing POST requests" do
|
37
|
+
req = request_signed_by(@authenticating_client, {}, {:post_me => "a_var" }, {:request_method=>"POST"})
|
38
|
+
req.method.should == :post
|
39
|
+
req.authenticating_client.should == @authenticating_client
|
40
|
+
req.signature_base_string.should match(/a_var/)
|
41
|
+
req.signed?.should be_true
|
42
|
+
end
|
43
|
+
it "should fail to verify that a request is signed if the signature is in any way wrong" do
|
44
|
+
get_params = {
|
45
|
+
:a=>"1",
|
46
|
+
:oauth_consumer_key=>@authenticating_client.api_key,
|
47
|
+
:oauth_signature=>"I R HACKIN YOO LOL"
|
48
|
+
}
|
49
|
+
param_string = get_params.collect{|k,v| "#{k}=#{v}"}.join("&")
|
50
|
+
req = fake_request(:query_string => param_string, :http_host => "test.fullfat.com", :request_uri=>"/secrets/")
|
51
|
+
req.authenticating_client.should == @authenticating_client
|
52
|
+
req.signed?.should be_false
|
53
|
+
end
|
54
|
+
it "should properly construct the baseline signature string" do
|
55
|
+
req = fake_request(:http_host=>"test.fullfat.com", :request_uri=>"/secrets", "Authorization"=>"OAuth realm=\"FOO\", foo=\"bar\", bar=\"baz\", overridden=\"no\"", :query_string=>"get=yes&overridden=yes")
|
56
|
+
req.signature_base_string.should == "GET&http://test.fullfat.com/secrets&bar=baz&foo=bar&get=yes&overridden=no"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "OAuth headers" do
|
61
|
+
before :each do
|
62
|
+
@authenticating_client = OohAuth::AuthenticatingClient.gen
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should successfully parse OAuth HTTP headers" do
|
66
|
+
# Make a real nasty header example with carriage returns and other gremlins
|
67
|
+
oauth_headers = "OAuth realm=\"FOO\", foo=\"bar\",
|
68
|
+
bar=\"baz\""
|
69
|
+
req = fake_request("Authorization"=>oauth_headers)
|
70
|
+
req.env["AUTHORIZATION"].should == oauth_headers
|
71
|
+
req.oauth_headers.should == {:realm=>"FOO", :foo=>"bar", :bar=>"baz"}
|
72
|
+
end
|
73
|
+
it "should remove the OAuth realm from the signature headers" do
|
74
|
+
# Make a real nasty header example with carriage returns and other gremlins
|
75
|
+
req = fake_request(:request_uri=>"/secrets", "Authorization"=>"OAuth realm=\"FOO\", foo=\"bar\", bar=\"baz\"")
|
76
|
+
req.signature_oauth_headers.should == {:foo=>"bar", :bar=>"baz"}
|
77
|
+
req.oauth_headers.should == {:realm=>"FOO", :foo=>"bar", :bar=>"baz"}
|
78
|
+
end
|
79
|
+
it "should merge POST/GET params into auth header params, giving auth header params priority" do
|
80
|
+
req = fake_request(:request_uri=>"/secrets", "Authorization"=>"OAuth realm=\"FOO\", foo=\"bar\", bar=\"baz\", overridden=\"no\"", :query_string=>"get=yes&overridden=yes")
|
81
|
+
req.normalise_signature_params.should == "bar=baz&foo=bar&get=yes&overridden=no"
|
82
|
+
end
|
83
|
+
it "should recognise OAuth requests" do
|
84
|
+
req = fake_request(:http_host=>"test.fullfat.com", :request_uri=>"/secrets", "Authorization"=>"OAuth realm=\"FOO\", oauth_consumer_key=\"DSFARGEG\"", :query_string=>"get=yes&overridden=yes")
|
85
|
+
req.oauth_request?.should be_true
|
86
|
+
req = fake_request(:http_host=>"test.fullfat.com", :request_uri=>"/secrets", "Authorization"=>"OAuth realm=\"FOO\"", :query_string=>"get=yes&overridden=yes")
|
87
|
+
req.oauth_request?.should be_false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "signature encryption" do
|
92
|
+
before :each do
|
93
|
+
@authenticating_client = OohAuth::AuthenticatingClient.gen
|
94
|
+
@req = fake_request(:http_host=>"test.fullfat.com", :request_uri=>"/secrets", "Authorization"=>"OAuth realm=\"FOO\", oauth_consumer_key=\"#{@authenticating_client.api_key}\", foo=\"bar\", bar=\"baz\", overridden=\"no\"", :query_string=>"get=yes&overridden=yes")
|
95
|
+
@req.authenticating_client.should == @authenticating_client
|
96
|
+
@token = OohAuth::Token.create_request_key(@authenticating_client)
|
97
|
+
@req.signed?.should be_false
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should properly compare the encrypted HMAC-SHA1 signature strings when a valid consumer key is given" do
|
101
|
+
req = fake_request(:http_host=>"test.fullfat.com", :request_uri=>"/secrets", "Authorization"=>"OAuth realm=\"FOO\", oauth_signature=\"#{@req.build_signature}\", oauth_consumer_key=\"#{@authenticating_client.api_key}\", foo=\"bar\", bar=\"baz\", overridden=\"no\"", :query_string=>"get=yes&overridden=yes")
|
102
|
+
req.signed?.should be_true
|
103
|
+
end
|
104
|
+
it "should properly compare the encrypted HMAC-MD5 signature strings when a valid consumer key is given" do
|
105
|
+
@req = fake_request(:http_host=>"test.fullfat.com", :request_uri=>"/secrets", "Authorization"=>"OAuth realm=\"FOO\", oauth_signature_method=\"HMAC-MD5\", oauth_consumer_key=\"#{@authenticating_client.api_key}\"")
|
106
|
+
req = fake_request(:http_host=>"test.fullfat.com", :request_uri=>"/secrets", "Authorization"=>"OAuth realm=\"FOO\", oauth_signature_method=\"HMAC-MD5\", oauth_signature=\"#{@req.build_signature}\", oauth_consumer_key=\"#{@authenticating_client.api_key}\"")
|
107
|
+
req.signature_method.should == "HMAC-MD5"
|
108
|
+
req.signed?.should be_true
|
109
|
+
end
|
110
|
+
it "should omit the token secret from the signature key if no token was given" do
|
111
|
+
@req.signature_secret.should == "#{@authenticating_client.secret}&"
|
112
|
+
end
|
113
|
+
it "should include the token secret in the signature key when a token is present" do
|
114
|
+
@req = fake_request(:http_host=>"test.fullfat.com", :request_uri=>"/secrets", "Authorization"=>"OAuth realm=\"FOO\", oauth_signature_method=\"HMAC-MD5\", oauth_token=\"#{@token.token_key}\", oauth_signature=\"#{@req.build_signature}\", oauth_consumer_key=\"#{@authenticating_client.api_key}\"")
|
115
|
+
@req.signature_secret.should == "#{@authenticating_client.secret}&#{@token.secret}"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
end
|