oauth2-provider 0.0.16
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 +8 -0
- data/Gemfile +3 -0
- data/README.md +49 -0
- data/Rakefile +24 -0
- data/examples/client/Gemfile +6 -0
- data/examples/client/Gemfile.lock +20 -0
- data/examples/client/README +8 -0
- data/examples/client/app.rb +59 -0
- data/examples/client/config.ru +3 -0
- data/examples/client/views/home.haml +3 -0
- data/examples/client/views/response.haml +11 -0
- data/examples/rails3-example/.gitignore +4 -0
- data/examples/rails3-example/Gemfile +10 -0
- data/examples/rails3-example/Gemfile.lock +82 -0
- data/examples/rails3-example/README +9 -0
- data/examples/rails3-example/Rakefile +7 -0
- data/examples/rails3-example/app/controllers/account_controller.rb +14 -0
- data/examples/rails3-example/app/controllers/application_controller.rb +18 -0
- data/examples/rails3-example/app/controllers/authorization_controller.rb +18 -0
- data/examples/rails3-example/app/controllers/home_controller.rb +4 -0
- data/examples/rails3-example/app/controllers/session_controller.rb +24 -0
- data/examples/rails3-example/app/helpers/application_helper.rb +2 -0
- data/examples/rails3-example/app/models/account.rb +6 -0
- data/examples/rails3-example/app/views/authorization/new.html.erb +5 -0
- data/examples/rails3-example/app/views/home/show.html.erb +1 -0
- data/examples/rails3-example/app/views/layouts/application.html.erb +16 -0
- data/examples/rails3-example/app/views/session/new.html.erb +7 -0
- data/examples/rails3-example/config.ru +4 -0
- data/examples/rails3-example/config/application.rb +42 -0
- data/examples/rails3-example/config/boot.rb +6 -0
- data/examples/rails3-example/config/database.yml +22 -0
- data/examples/rails3-example/config/environment.rb +5 -0
- data/examples/rails3-example/config/environments/development.rb +26 -0
- data/examples/rails3-example/config/environments/production.rb +49 -0
- data/examples/rails3-example/config/environments/test.rb +35 -0
- data/examples/rails3-example/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/rails3-example/config/initializers/inflections.rb +10 -0
- data/examples/rails3-example/config/initializers/mime_types.rb +5 -0
- data/examples/rails3-example/config/initializers/secret_token.rb +7 -0
- data/examples/rails3-example/config/initializers/session_store.rb +8 -0
- data/examples/rails3-example/config/locales/en.yml +5 -0
- data/examples/rails3-example/config/routes.rb +9 -0
- data/examples/rails3-example/db/migrate/20110508151935_add_account_table.rb +12 -0
- data/examples/rails3-example/db/migrate/20110508151948_add_oauth2_tables.rb +43 -0
- data/examples/rails3-example/db/schema.rb +52 -0
- data/examples/rails3-example/db/seeds.rb +11 -0
- data/examples/rails3-example/doc/README_FOR_APP +2 -0
- data/examples/rails3-example/lib/tasks/.gitkeep +0 -0
- data/examples/rails3-example/public/404.html +26 -0
- data/examples/rails3-example/public/422.html +26 -0
- data/examples/rails3-example/public/500.html +26 -0
- data/examples/rails3-example/public/favicon.ico +0 -0
- data/examples/rails3-example/public/images/rails.png +0 -0
- data/examples/rails3-example/public/robots.txt +5 -0
- data/examples/rails3-example/public/stylesheets/.gitkeep +0 -0
- data/examples/rails3-example/script/rails +6 -0
- data/lib/oauth2-provider.rb +3 -0
- data/lib/oauth2/provider.rb +39 -0
- data/lib/oauth2/provider/models.rb +40 -0
- data/lib/oauth2/provider/models/access_token.rb +54 -0
- data/lib/oauth2/provider/models/active_record.rb +30 -0
- data/lib/oauth2/provider/models/active_record/access_token.rb +13 -0
- data/lib/oauth2/provider/models/active_record/authorization.rb +16 -0
- data/lib/oauth2/provider/models/active_record/authorization_code.rb +13 -0
- data/lib/oauth2/provider/models/active_record/client.rb +15 -0
- data/lib/oauth2/provider/models/authorization.rb +40 -0
- data/lib/oauth2/provider/models/authorization_code.rb +27 -0
- data/lib/oauth2/provider/models/client.rb +28 -0
- data/lib/oauth2/provider/models/mongoid.rb +30 -0
- data/lib/oauth2/provider/models/mongoid/access_token.rb +40 -0
- data/lib/oauth2/provider/models/mongoid/authorization.rb +32 -0
- data/lib/oauth2/provider/models/mongoid/authorization_code.rb +43 -0
- data/lib/oauth2/provider/models/mongoid/client.rb +40 -0
- data/lib/oauth2/provider/rack.rb +11 -0
- data/lib/oauth2/provider/rack/access_token_handler.rb +103 -0
- data/lib/oauth2/provider/rack/authorization_code_request.rb +74 -0
- data/lib/oauth2/provider/rack/authorization_codes_support.rb +25 -0
- data/lib/oauth2/provider/rack/middleware.rb +28 -0
- data/lib/oauth2/provider/rack/resource_request.rb +91 -0
- data/lib/oauth2/provider/rack/responses.rb +34 -0
- data/lib/oauth2/provider/rails.rb +37 -0
- data/lib/oauth2/provider/rails/controller_authentication.rb +21 -0
- data/lib/oauth2/provider/random.rb +30 -0
- data/lib/oauth2/provider/version.rb +5 -0
- data/oauth2-provider.gemspec +35 -0
- data/spec/models/access_token_spec.rb +123 -0
- data/spec/models/authorization_code_spec.rb +115 -0
- data/spec/models/authorization_spec.rb +110 -0
- data/spec/models/client_spec.rb +75 -0
- data/spec/requests/access_tokens_controller_spec.rb +360 -0
- data/spec/requests/authentication_spec.rb +150 -0
- data/spec/requests/authorization_codes_support_spec.rb +157 -0
- data/spec/schema.rb +38 -0
- data/spec/set_backend_env_to_mongoid.rb +1 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/support/activerecord_backend.rb +18 -0
- data/spec/support/factories.rb +56 -0
- data/spec/support/macros.rb +46 -0
- data/spec/support/mongoid_backend.rb +34 -0
- data/spec/support/rack.rb +32 -0
- metadata +373 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe OAuth2::Provider.client_class do
|
|
4
|
+
describe "any instance" do
|
|
5
|
+
subject do
|
|
6
|
+
OAuth2::Provider.client_class.new :name => 'client'
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "is valid with a name, oauth identifier and oauth secret" do
|
|
10
|
+
subject.should be_valid
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "is invalid without a name" do
|
|
14
|
+
subject.name = nil
|
|
15
|
+
subject.should_not be_valid
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "is invalid without an oauth identifier" do
|
|
19
|
+
subject.oauth_identifier = nil
|
|
20
|
+
subject.should_not be_valid
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "is invalid without an oauth secret" do
|
|
24
|
+
subject.oauth_secret = nil
|
|
25
|
+
subject.should_not be_valid
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "is invalid if oauth_identifier not unique" do
|
|
29
|
+
duplicate = OAuth2::Provider.client_class.create! :name => 'client2'
|
|
30
|
+
subject.oauth_identifier = duplicate.oauth_identifier
|
|
31
|
+
subject.should_not be_valid
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "allows any grant type (custom subclasses can override this)" do
|
|
35
|
+
subject.allow_grant_type?('password').should be_true
|
|
36
|
+
subject.allow_grant_type?('authorization_code').should be_true
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
describe "a new instance" do
|
|
41
|
+
subject do
|
|
42
|
+
OAuth2::Provider.client_class.new :name => 'client'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "is assigned a randomly generated oauth identifier" do
|
|
46
|
+
subject.oauth_identifier.should_not be_nil
|
|
47
|
+
OAuth2::Provider.client_class.new.oauth_identifier.should_not be_nil
|
|
48
|
+
subject.oauth_identifier.should_not == OAuth2::Provider.client_class.new.oauth_identifier
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "is assigned a randomly generated oauth secret" do
|
|
52
|
+
subject.oauth_secret.should_not be_nil
|
|
53
|
+
OAuth2::Provider.client_class.new.oauth_secret.should_not be_nil
|
|
54
|
+
subject.oauth_secret.should_not == OAuth2::Provider.client_class.new.oauth_secret
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "returns nil when to_param called" do
|
|
58
|
+
subject.to_param.should be_nil
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe "a saved instance" do
|
|
63
|
+
subject do
|
|
64
|
+
OAuth2::Provider.client_class.create! :name => 'client'
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "returns oauth_identifer when to_param called" do
|
|
68
|
+
subject.to_param.should == subject.oauth_identifier
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "is findable by calling from_param with its oauth_identifier" do
|
|
72
|
+
subject.should == OAuth2::Provider.client_class.from_param(subject.oauth_identifier)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
class CustomClient < OAuth2::Provider.client_class
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
class NotAllowedGrantTypeClient < OAuth2::Provider.client_class
|
|
7
|
+
def allow_grant_type?(grant_type)
|
|
8
|
+
false
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "POSTs to /oauth/access_token" do
|
|
13
|
+
before :each do
|
|
14
|
+
@code = create_authorization_code
|
|
15
|
+
@client = @code.authorization.client
|
|
16
|
+
@valid_params = {
|
|
17
|
+
:grant_type => 'authorization_code',
|
|
18
|
+
:client_id => @code.authorization.client.oauth_identifier,
|
|
19
|
+
:client_secret => @code.authorization.client.oauth_secret,
|
|
20
|
+
:code => @code.code,
|
|
21
|
+
:redirect_uri => @code.redirect_uri
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
describe "Any request without a client_id parameter" do
|
|
26
|
+
before :each do
|
|
27
|
+
post "/oauth/access_token", @valid_params.except(:client_id)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
responds_with_json_error 'invalid_request', :description => "missing 'client_id' parameter", :status => 400
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe "Any request without a client_secret parameter" do
|
|
34
|
+
before :each do
|
|
35
|
+
post "/oauth/access_token", @valid_params.except(:client_secret)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
responds_with_json_error 'invalid_request', :description => "missing 'client_secret' parameter", :status => 400
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe "Any request without a grant_type parameter" do
|
|
42
|
+
before :each do
|
|
43
|
+
post "/oauth/access_token", @valid_params.except(:grant_type)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
responds_with_json_error 'invalid_request', :description => "missing 'grant_type' parameter", :status => 400
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe "Any request without several required parameters" do
|
|
50
|
+
before :each do
|
|
51
|
+
post "/oauth/access_token", @valid_params.except(:client_id, :client_secret)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
responds_with_json_error 'invalid_request', :description => "missing 'client_id', 'client_secret' parameters", :status => 400
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe "Any request with an unsupported grant_type" do
|
|
58
|
+
before :each do
|
|
59
|
+
post "/oauth/access_token", @valid_params.merge(:grant_type => 'unsupported')
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
responds_with_json_error 'unsupported_grant_type', :status => 400
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
describe "Any request where the client_id is unknown" do
|
|
66
|
+
before :each do
|
|
67
|
+
post "/oauth/access_token", @valid_params.merge(:client_id => 'unknown')
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
responds_with_json_error 'invalid_client', :status => 400
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
describe "Any request where the client_secret is wrong" do
|
|
74
|
+
before :each do
|
|
75
|
+
post "/oauth/access_token", @valid_params.merge(:client_secret => 'wrongvalue')
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
responds_with_json_error 'invalid_client', :status => 400
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe "Any request which doesn't use POST" do
|
|
82
|
+
before :each do
|
|
83
|
+
get "/oauth/access_token", @valid_params
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "responds with Method Not Allowed (405), and POST in the Allow header" do
|
|
87
|
+
response.status.should == 405
|
|
88
|
+
response.headers["Allow"].should == "POST"
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe "Any request where the client isn't allowed to use the requested grant type" do
|
|
93
|
+
before :each do
|
|
94
|
+
@original_client_class_name = OAuth2::Provider.client_class_name
|
|
95
|
+
OAuth2::Provider.client_class_name = NotAllowedGrantTypeClient.name
|
|
96
|
+
@client = NotAllowedGrantTypeClient.create! :name => 'client'
|
|
97
|
+
@code = create_authorization_code(:authorization => create_authorization(:client => @client))
|
|
98
|
+
@valid_params = {
|
|
99
|
+
:grant_type => 'authorization_code',
|
|
100
|
+
:client_id => @code.authorization.client.oauth_identifier,
|
|
101
|
+
:client_secret => @code.authorization.client.oauth_secret,
|
|
102
|
+
:code => @code.code,
|
|
103
|
+
:redirect_uri => @code.redirect_uri
|
|
104
|
+
}
|
|
105
|
+
post "/oauth/access_token", @valid_params
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
after :each do
|
|
109
|
+
OAuth2::Provider.client_class_name = @original_client_class_name
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
responds_with_json_error 'unauthorized_client', :status => 400
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
describe "A request using the authorization_code grant type" do
|
|
116
|
+
describe "with valid client, code and redirect_uri" do
|
|
117
|
+
before :each do
|
|
118
|
+
post "/oauth/access_token", @valid_params
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it "responds with claimed access token, refresh token and expiry time in JSON" do
|
|
122
|
+
token = OAuth2::Provider.access_token_class.find_by_access_token(json_from_response["access_token"])
|
|
123
|
+
token.should_not be_nil
|
|
124
|
+
json_from_response["expires_in"].should == token.expires_in
|
|
125
|
+
json_from_response["refresh_token"].should == token.refresh_token
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "sets cache-control header to no-store, as response is sensitive" do
|
|
129
|
+
response.headers["Cache-Control"].should =~ /no-store/
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it "destroys the claimed code, so it can't be used a second time" do
|
|
133
|
+
OAuth2::Provider.authorization_code_class.find_by_id(@code.id).should be_nil
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it "doesn't include a state in the JSON response" do
|
|
137
|
+
json_from_response.keys.include?("state").should be_false
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
describe "with valid client, code and redirect_uri and an additional state parameter" do
|
|
142
|
+
before :each do
|
|
143
|
+
post "/oauth/access_token", @valid_params.merge(:state => 'some-state-goes-here')
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it "includes the state in the JSON response" do
|
|
147
|
+
json_from_response["state"].should == 'some-state-goes-here'
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
describe "with an unknown code" do
|
|
152
|
+
before :each do
|
|
153
|
+
post "/oauth/access_token", @valid_params.merge(:code => 'unknown')
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
responds_with_json_error 'invalid_grant', :status => 400
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
describe "with an incorrect redirect uri" do
|
|
160
|
+
before :each do
|
|
161
|
+
post "/oauth/access_token", @valid_params.merge(:redirect_uri => 'https://wrong.example.com')
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
responds_with_json_error 'invalid_grant', :status => 400
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
describe "without a code parameter" do
|
|
168
|
+
before :each do
|
|
169
|
+
post "/oauth/access_token", @valid_params.except(:code)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
responds_with_json_error 'invalid_request', :status => 400
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
describe "without a redirect_uri parameter" do
|
|
176
|
+
before :each do
|
|
177
|
+
post "/oauth/access_token", @valid_params.except(:redirect_uri)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
responds_with_json_error 'invalid_request', :status => 400
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
describe "A request using the password grant type" do
|
|
185
|
+
before :each do
|
|
186
|
+
@resource_owner = ExampleResourceOwner.create!(:username => 'name', :password => 'password')
|
|
187
|
+
@valid_params = {
|
|
188
|
+
:grant_type => 'password',
|
|
189
|
+
:client_id => @client.to_param,
|
|
190
|
+
:client_secret => @client.oauth_secret,
|
|
191
|
+
:username => @resource_owner.username,
|
|
192
|
+
:password => @resource_owner.password
|
|
193
|
+
}
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
describe "with valid username and password" do
|
|
197
|
+
before :each do
|
|
198
|
+
post "/oauth/access_token", @valid_params
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
it "responds with access token, refresh token and expiry time in JSON" do
|
|
202
|
+
token = OAuth2::Provider.access_token_class.find_by_access_token(json_from_response["access_token"])
|
|
203
|
+
token.should_not be_nil
|
|
204
|
+
json_from_response["expires_in"].should == token.expires_in
|
|
205
|
+
json_from_response["refresh_token"].should == token.refresh_token
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it "sets cache-control header to no-store, as response is sensitive" do
|
|
209
|
+
response.headers["Cache-Control"].should =~ /no-store/
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
it "doesn't include a state in the JSON response" do
|
|
213
|
+
json_from_response.keys.include?("state").should be_false
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
describe "with valid username and password and an additional state parameter" do
|
|
218
|
+
before :each do
|
|
219
|
+
post "/oauth/access_token", @valid_params.merge(:state => 'some-state-goes-here')
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
it "includes the state in the JSON response" do
|
|
223
|
+
json_from_response["state"].should == 'some-state-goes-here'
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
describe "with an incorrect username" do
|
|
228
|
+
before :each do
|
|
229
|
+
post "/oauth/access_token", @valid_params.merge(:username => 'wrong')
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
responds_with_json_error 'invalid_grant', :status => 400
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
describe "with an incorrect password" do
|
|
236
|
+
before :each do
|
|
237
|
+
post "/oauth/access_token", @valid_params.merge(:password => 'wrong')
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
responds_with_json_error 'invalid_grant', :status => 400
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
describe "without a username parameter" do
|
|
244
|
+
before :each do
|
|
245
|
+
post "/oauth/access_token", @valid_params.except(:username)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
responds_with_json_error 'invalid_request', :status => 400
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
describe "without a password parameter" do
|
|
252
|
+
before :each do
|
|
253
|
+
post "/oauth/access_token", @valid_params.except(:password)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
responds_with_json_error 'invalid_request', :status => 400
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
describe "A request using the refresh token grant type" do
|
|
261
|
+
before :each do
|
|
262
|
+
@token = create_access_token
|
|
263
|
+
|
|
264
|
+
@client = @token.authorization.client
|
|
265
|
+
@valid_params = {
|
|
266
|
+
:grant_type => 'refresh_token',
|
|
267
|
+
:refresh_token => @token.refresh_token,
|
|
268
|
+
:client_id => @client.oauth_identifier,
|
|
269
|
+
:client_secret => @client.oauth_secret
|
|
270
|
+
}
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
describe "with a valid refresh token" do
|
|
274
|
+
before :each do
|
|
275
|
+
post "/oauth/access_token", @valid_params
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
it "responds with refreshed access token, refresh token and expiry time in JSON" do
|
|
279
|
+
token = OAuth2::Provider.access_token_class.find_by_access_token(json_from_response["access_token"])
|
|
280
|
+
token.should_not be_nil
|
|
281
|
+
token.should_not == @token
|
|
282
|
+
json_from_response["expires_in"].should == token.expires_in
|
|
283
|
+
json_from_response["refresh_token"].should == token.refresh_token
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
describe "when the token belongs to a different client" do
|
|
288
|
+
before :each do
|
|
289
|
+
@other_client = OAuth2::Provider.client_class.create! :name => 'client'
|
|
290
|
+
post "/oauth/access_token", @valid_params.merge(:client_id => @other_client.oauth_identifier, :client_secret => @other_client.oauth_secret)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
responds_with_json_error 'invalid_grant', :status => 400
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
describe "when the token is incorrect" do
|
|
297
|
+
before :each do
|
|
298
|
+
post "/oauth/access_token", @valid_params.merge(:refresh_token => 'incorrect')
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
responds_with_json_error 'invalid_grant', :status => 400
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
describe "without a refresh_token parameter" do
|
|
305
|
+
before :each do
|
|
306
|
+
post "/oauth/access_token", @valid_params.except(:refresh_token)
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
responds_with_json_error 'invalid_request', :status => 400
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
describe "When using a custom client class" do
|
|
314
|
+
before :each do
|
|
315
|
+
@original_client_class_name = OAuth2::Provider.client_class_name
|
|
316
|
+
OAuth2::Provider.client_class_name = "CustomClient"
|
|
317
|
+
@client = CustomClient.create! :name => 'client'
|
|
318
|
+
@client_params = {
|
|
319
|
+
:client_id => @client.to_param,
|
|
320
|
+
:client_secret => @client.oauth_secret,
|
|
321
|
+
}
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
after :each do
|
|
325
|
+
OAuth2::Provider.client_class_name = @original_client_class_name
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
describe "requests using authorization code grant type" do
|
|
329
|
+
before :each do
|
|
330
|
+
@code = create_authorization_code(:authorization => create_authorization(:client => @client))
|
|
331
|
+
@valid_params = @client_params.merge(
|
|
332
|
+
:grant_type => 'authorization_code',
|
|
333
|
+
:code => @code.code,
|
|
334
|
+
:redirect_uri => @code.redirect_uri
|
|
335
|
+
)
|
|
336
|
+
post "/oauth/access_token", @valid_params
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
it "are still successful" do
|
|
340
|
+
response.should be_successful
|
|
341
|
+
end
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
describe "requests using password grant type" do
|
|
345
|
+
before :each do
|
|
346
|
+
@resource_owner = ExampleResourceOwner.create!(:username => 'name', :password => 'password')
|
|
347
|
+
@valid_params = @client_params.merge(
|
|
348
|
+
:grant_type => 'password',
|
|
349
|
+
:username => @resource_owner.username,
|
|
350
|
+
:password => @resource_owner.password
|
|
351
|
+
)
|
|
352
|
+
post "/oauth/access_token", @valid_params
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
it "are still successful" do
|
|
356
|
+
response.should be_successful
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
end
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "A request for a protected resource" do
|
|
4
|
+
action do |env|
|
|
5
|
+
env['oauth2'].authenticate_request!(:scope => nil) do
|
|
6
|
+
successful_response
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
before :each do
|
|
11
|
+
@token = create_access_token(
|
|
12
|
+
:authorization => create_authorization(
|
|
13
|
+
:scope => "protected write"
|
|
14
|
+
)
|
|
15
|
+
)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "with no token passed" do
|
|
19
|
+
before :each do
|
|
20
|
+
get "/protected"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
responds_with_status 401
|
|
24
|
+
responds_with_header 'WWW-Authenticate', 'OAuth2'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "with a token passed as an oauth_token parameter" do
|
|
28
|
+
before :each do
|
|
29
|
+
get "/protected", :oauth_token => @token.access_token
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "is successful" do
|
|
33
|
+
response.should be_successful
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "makes the access token available to the requested action" do
|
|
37
|
+
response.body.should == "Success"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe "with a token passed in an Authorization header" do
|
|
42
|
+
before :each do
|
|
43
|
+
get "/protected", {}, {"HTTP_AUTHORIZATION" => "OAuth #{@token.access_token}"}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "is successful" do
|
|
47
|
+
response.should be_successful
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "makes the access token available to the requested action" do
|
|
51
|
+
response.body.should == "Success"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe "with same token passed in both the Authorization header and oauth_token parameter" do
|
|
56
|
+
before :each do
|
|
57
|
+
get "/protected", {:oauth_token => @token.access_token}, {"HTTP_AUTHORIZATION" => "OAuth #{@token.access_token}"}
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "is successful" do
|
|
61
|
+
response.should be_successful
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "makes the access token available to the requested action" do
|
|
65
|
+
response.body.should == "Success"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe "with different tokens passed in both the Authorization header and oauth_token parameter" do
|
|
70
|
+
before :each do
|
|
71
|
+
get "/protected", {:oauth_token => @token.access_token}, {"HTTP_AUTHORIZATION" => "OAuth DifferentToken"}
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
responds_with_json_error 'invalid_request', :description => 'both authorization header and oauth_token provided, with conflicting tokens', :status => 400
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe "with an invalid token" do
|
|
78
|
+
before :each do
|
|
79
|
+
get "/protected", :oauth_token => 'invalid-token'
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
responds_with_status 401
|
|
83
|
+
responds_with_header 'WWW-Authenticate', 'OAuth2 error="invalid_token"'
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
describe "with an expired token that can be refreshed" do
|
|
87
|
+
before :each do
|
|
88
|
+
@token.update_attributes(:expires_at => 1.day.ago)
|
|
89
|
+
get "/protected", :oauth_token => @token.access_token
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
responds_with_status 401
|
|
93
|
+
responds_with_header 'WWW-Authenticate', 'OAuth2 error="invalid_token"'
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
describe "with an expired token that can't be refreshed" do
|
|
97
|
+
before :each do
|
|
98
|
+
@token.update_attributes(:expires_at => 1.day.ago, :refresh_token => nil)
|
|
99
|
+
get "/protected", :oauth_token => @token.access_token
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
responds_with_status 401
|
|
103
|
+
responds_with_header 'WWW-Authenticate', 'OAuth2 error="invalid_token"'
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
describe "when warden is part of the stack" do
|
|
107
|
+
it "bypasses warden when no token is passed" do
|
|
108
|
+
warden = "warden"
|
|
109
|
+
warden.should_receive(:custom_failure!)
|
|
110
|
+
get "/protected", {}, {'warden' => warden}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "bypasses warden when token invalid" do
|
|
114
|
+
warden = "warden"
|
|
115
|
+
warden.should_receive(:custom_failure!)
|
|
116
|
+
get "/protected", {:oauth_token => 'invalid_token'}, {'warden' => warden}
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
describe "A request for a protected resource requiring a specific scope" do
|
|
122
|
+
action do |env|
|
|
123
|
+
env['oauth2'].authenticate_request!(:scope => 'omnipotent') do
|
|
124
|
+
successful_response
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
before :each do
|
|
129
|
+
@token = create_access_token(:authorization => create_authorization(:scope => "omnipotent admin"))
|
|
130
|
+
@insufficient_token = create_access_token(:authorization => create_authorization(:scope => "impotent admin"))
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
describe "made with a token with sufficient scope" do
|
|
134
|
+
before :each do
|
|
135
|
+
get '/protected_by_scope', :oauth_token => @token.access_token
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it "is successful" do
|
|
139
|
+
response.should be_successful
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
describe "made with a token with insufficient scope" do
|
|
144
|
+
before :each do
|
|
145
|
+
get '/protected_by_scope', :oauth_token => @insufficient_token.access_token
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
responds_with_json_error 'insufficient_scope', :status => 403
|
|
149
|
+
end
|
|
150
|
+
end
|