doorkeeper 0.5.0 → 0.6.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of doorkeeper might be problematic. Click here for more details.
- data/.travis.yml +15 -6
- data/CHANGELOG.md +19 -1
- data/Gemfile +23 -7
- data/README.md +62 -27
- data/app/controllers/doorkeeper/application_controller.rb +1 -1
- data/app/controllers/doorkeeper/authorizations_controller.rb +45 -35
- data/app/controllers/doorkeeper/token_info_controller.rb +10 -9
- data/app/controllers/doorkeeper/tokens_controller.rb +13 -32
- data/app/validators/redirect_uri_validator.rb +11 -0
- data/app/views/doorkeeper/applications/_form.html.erb +6 -1
- data/app/views/doorkeeper/applications/edit.html.erb +2 -2
- data/app/views/doorkeeper/applications/new.html.erb +2 -2
- data/app/views/doorkeeper/applications/show.html.erb +4 -1
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +17 -17
- data/app/views/doorkeeper/authorizations/show.html.erb +4 -0
- data/config/locales/en.yml +10 -0
- data/doorkeeper.gemspec +3 -3
- data/lib/doorkeeper.rb +11 -2
- data/lib/doorkeeper/config.rb +6 -1
- data/lib/doorkeeper/errors.rb +15 -0
- data/lib/doorkeeper/helpers/controller.rb +24 -0
- data/lib/doorkeeper/models/access_grant.rb +1 -1
- data/lib/doorkeeper/models/access_token.rb +2 -3
- data/lib/doorkeeper/models/active_record/access_token.rb +6 -0
- data/lib/doorkeeper/models/mongo_mapper/access_grant.rb +28 -0
- data/lib/doorkeeper/models/mongo_mapper/access_token.rb +51 -0
- data/lib/doorkeeper/models/mongo_mapper/application.rb +30 -0
- data/lib/doorkeeper/models/mongo_mapper/revocable.rb +15 -0
- data/lib/doorkeeper/models/{mongoid → mongoid2}/access_grant.rb +1 -1
- data/lib/doorkeeper/models/{mongoid → mongoid2}/access_token.rb +6 -0
- data/lib/doorkeeper/models/{mongoid → mongoid2}/application.rb +2 -2
- data/lib/doorkeeper/models/mongoid3/access_grant.rb +22 -0
- data/lib/doorkeeper/models/mongoid3/access_token.rb +41 -0
- data/lib/doorkeeper/models/mongoid3/application.rb +22 -0
- data/lib/doorkeeper/oauth/authorization/code.rb +9 -17
- data/lib/doorkeeper/oauth/authorization/token.rb +8 -18
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +2 -0
- data/lib/doorkeeper/oauth/authorization_code_request.rb +82 -0
- data/lib/doorkeeper/oauth/client_credentials_request.rb +2 -4
- data/lib/doorkeeper/oauth/code_request.rb +28 -0
- data/lib/doorkeeper/oauth/code_response.rb +37 -0
- data/lib/doorkeeper/oauth/error_response.rb +23 -9
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +4 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +21 -65
- data/lib/doorkeeper/oauth/pre_authorization.rb +62 -0
- data/lib/doorkeeper/oauth/refresh_token_request.rb +58 -0
- data/lib/doorkeeper/oauth/token_request.rb +28 -0
- data/lib/doorkeeper/oauth/token_response.rb +29 -0
- data/lib/doorkeeper/rails/routes.rb +4 -3
- data/lib/doorkeeper/request.rb +33 -0
- data/lib/doorkeeper/request/authorization_code.rb +23 -0
- data/lib/doorkeeper/request/client_credentials.rb +23 -0
- data/lib/doorkeeper/request/code.rb +24 -0
- data/lib/doorkeeper/request/password.rb +23 -0
- data/lib/doorkeeper/request/refresh_token.rb +23 -0
- data/lib/doorkeeper/request/token.rb +24 -0
- data/lib/doorkeeper/server.rb +54 -0
- data/lib/doorkeeper/validations.rb +1 -0
- data/lib/doorkeeper/version.rb +1 -1
- data/lib/generators/doorkeeper/mongo_mapper/indexes_generator.rb +12 -0
- data/lib/generators/doorkeeper/templates/README +15 -1
- data/lib/generators/doorkeeper/templates/indexes.rb +3 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +8 -1
- data/script/run_all +9 -9
- data/spec/controllers/authorizations_controller_spec.rb +8 -19
- data/spec/controllers/token_info_controller_spec.rb +9 -9
- data/spec/controllers/tokens_controller_spec.rb +2 -1
- data/spec/dummy/app/models/user.rb +11 -4
- data/spec/dummy/config/application.rb +8 -1
- data/spec/dummy/config/boot.rb +1 -1
- data/spec/dummy/config/initializers/doorkeeper.rb +9 -1
- data/spec/dummy/config/mongo.yml +11 -0
- data/spec/dummy/config/{mongoid.yml → mongoid2.yml} +3 -1
- data/spec/dummy/config/mongoid3.yml +18 -0
- data/spec/generators/install_generator_spec.rb +1 -0
- data/spec/lib/oauth/authorization_code_request_spec.rb +80 -0
- data/spec/lib/oauth/client_credentials_request_spec.rb +1 -3
- data/spec/lib/oauth/code_request_spec.rb +44 -0
- data/spec/lib/oauth/error_response_spec.rb +7 -7
- data/spec/lib/oauth/password_access_token_request_spec.rb +30 -143
- data/spec/lib/oauth/pre_authorization_spec.rb +80 -0
- data/spec/lib/oauth/refresh_token_request_spec.rb +56 -0
- data/spec/lib/oauth/token_request_spec.rb +46 -0
- data/spec/lib/oauth/{client_credentials/response_spec.rb → token_response_spec.rb} +13 -19
- data/spec/lib/server_spec.rb +24 -0
- data/spec/requests/endpoints/authorization_spec.rb +11 -27
- data/spec/requests/endpoints/token_spec.rb +17 -0
- data/spec/requests/flows/authorization_code_errors_spec.rb +0 -45
- data/spec/requests/flows/authorization_code_spec.rb +12 -2
- data/spec/requests/flows/client_credentials_spec.rb +1 -1
- data/spec/requests/flows/password_spec.rb +1 -0
- data/spec/requests/flows/refresh_token_spec.rb +6 -4
- data/spec/spec_helper_integration.rb +4 -2
- data/spec/support/orm/mongo_mapper.rb +26 -0
- data/spec/support/orm/mongoid.rb +7 -2
- data/spec/validators/redirect_uri_validator_spec.rb +11 -4
- metadata +67 -42
- data/gemfiles/gemfile.rails-3.1.x +0 -17
- data/gemfiles/gemfile.rails-3.2.x +0 -17
- data/lib/doorkeeper/oauth/access_token_request.rb +0 -139
- data/lib/doorkeeper/oauth/authorization_request.rb +0 -114
- data/lib/doorkeeper/oauth/client_credentials/response.rb +0 -42
- data/spec/lib/oauth/access_token_request_spec.rb +0 -246
- data/spec/lib/oauth/authorization_request_spec.rb +0 -287
@@ -1,114 +0,0 @@
|
|
1
|
-
module Doorkeeper::OAuth
|
2
|
-
class AuthorizationRequest
|
3
|
-
include Doorkeeper::Validations
|
4
|
-
include Doorkeeper::OAuth::Authorization::URIBuilder
|
5
|
-
include Doorkeeper::OAuth::Helpers
|
6
|
-
|
7
|
-
ATTRIBUTES = [
|
8
|
-
:response_type,
|
9
|
-
:redirect_uri,
|
10
|
-
:scope,
|
11
|
-
:state
|
12
|
-
]
|
13
|
-
|
14
|
-
validate :client, :error => :invalid_client
|
15
|
-
validate :redirect_uri, :error => :invalid_redirect_uri
|
16
|
-
validate :attributes, :error => :invalid_request
|
17
|
-
validate :response_type, :error => :unsupported_response_type
|
18
|
-
validate :scope, :error => :invalid_scope
|
19
|
-
|
20
|
-
attr_accessor *ATTRIBUTES
|
21
|
-
attr_accessor :resource_owner, :client, :error
|
22
|
-
|
23
|
-
def initialize(client, resource_owner, attributes)
|
24
|
-
ATTRIBUTES.each { |attr| instance_variable_set("@#{attr}", attributes[attr]) }
|
25
|
-
@resource_owner = resource_owner
|
26
|
-
@client = client
|
27
|
-
validate
|
28
|
-
end
|
29
|
-
|
30
|
-
def authorize
|
31
|
-
return false unless valid?
|
32
|
-
@authorization = authorization_method.new(self)
|
33
|
-
@authorization.issue_token
|
34
|
-
end
|
35
|
-
|
36
|
-
def access_token_exists?
|
37
|
-
Doorkeeper::AccessToken.matching_token_for(client, resource_owner, scopes).present?
|
38
|
-
end
|
39
|
-
|
40
|
-
def deny
|
41
|
-
self.error = :access_denied
|
42
|
-
end
|
43
|
-
|
44
|
-
def error_response
|
45
|
-
Doorkeeper::OAuth::ErrorResponse.from_request(self)
|
46
|
-
end
|
47
|
-
|
48
|
-
def success_redirect_uri
|
49
|
-
@authorization.callback
|
50
|
-
end
|
51
|
-
|
52
|
-
def invalid_redirect_uri
|
53
|
-
uri_builder = is_token_request? ? :uri_with_fragment : :uri_with_query
|
54
|
-
send(uri_builder, redirect_uri, error_response.attributes)
|
55
|
-
end
|
56
|
-
|
57
|
-
def redirect_on_error?
|
58
|
-
(error != :invalid_redirect_uri) && (error != :invalid_client)
|
59
|
-
end
|
60
|
-
|
61
|
-
def scopes
|
62
|
-
@scopes ||= if scope.present?
|
63
|
-
Doorkeeper::OAuth::Scopes.from_string(scope)
|
64
|
-
else
|
65
|
-
Doorkeeper.configuration.default_scopes
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def client_id
|
70
|
-
client.uid
|
71
|
-
end
|
72
|
-
|
73
|
-
private
|
74
|
-
|
75
|
-
def validate_attributes
|
76
|
-
response_type.present?
|
77
|
-
end
|
78
|
-
|
79
|
-
def validate_client
|
80
|
-
!!client
|
81
|
-
end
|
82
|
-
|
83
|
-
def validate_redirect_uri
|
84
|
-
return false unless redirect_uri
|
85
|
-
URIChecker.valid_for_authorization?(redirect_uri, client.redirect_uri)
|
86
|
-
end
|
87
|
-
|
88
|
-
def validate_response_type
|
89
|
-
is_code_request? || is_token_request?
|
90
|
-
end
|
91
|
-
|
92
|
-
def validate_scope
|
93
|
-
return true unless scope.present?
|
94
|
-
ScopeChecker.valid?(scope, configuration.scopes)
|
95
|
-
end
|
96
|
-
|
97
|
-
def is_code_request?
|
98
|
-
response_type == "code"
|
99
|
-
end
|
100
|
-
|
101
|
-
def is_token_request?
|
102
|
-
response_type == "token"
|
103
|
-
end
|
104
|
-
|
105
|
-
def configuration
|
106
|
-
Doorkeeper.configuration
|
107
|
-
end
|
108
|
-
|
109
|
-
def authorization_method
|
110
|
-
klass = is_code_request? ? "Code" : "Token"
|
111
|
-
"Doorkeeper::OAuth::Authorization::#{klass}".constantize
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'active_model'
|
2
|
-
|
3
|
-
module Doorkeeper
|
4
|
-
module OAuth
|
5
|
-
class ClientCredentialsRequest
|
6
|
-
class Response
|
7
|
-
include ActiveModel::Serializers::JSON
|
8
|
-
|
9
|
-
self.include_root_in_json = false
|
10
|
-
|
11
|
-
delegate :token, :expires_in, :scopes_string, :to => :@token
|
12
|
-
alias :access_token :token
|
13
|
-
alias :scope :scopes_string
|
14
|
-
|
15
|
-
def initialize(token)
|
16
|
-
@token = token
|
17
|
-
end
|
18
|
-
|
19
|
-
def attributes
|
20
|
-
{
|
21
|
-
'access_token' => token,
|
22
|
-
'token_type' => token_type,
|
23
|
-
'expires_in' => expires_in,
|
24
|
-
'scope' => scopes_string
|
25
|
-
}
|
26
|
-
end
|
27
|
-
|
28
|
-
def status
|
29
|
-
:success
|
30
|
-
end
|
31
|
-
|
32
|
-
def token_type
|
33
|
-
'bearer'
|
34
|
-
end
|
35
|
-
|
36
|
-
def headers
|
37
|
-
{ 'Cache-Control' => 'no-store', 'Pragma' => 'no-cache' }
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,246 +0,0 @@
|
|
1
|
-
require 'spec_helper_integration'
|
2
|
-
|
3
|
-
module Doorkeeper::OAuth
|
4
|
-
describe AccessTokenRequest do
|
5
|
-
let(:client) { FactoryGirl.create(:application) }
|
6
|
-
let(:grant) { FactoryGirl.create(:access_grant, :application => client) }
|
7
|
-
let(:params) {
|
8
|
-
{
|
9
|
-
:code => grant.token,
|
10
|
-
:grant_type => "authorization_code",
|
11
|
-
:redirect_uri => client.redirect_uri
|
12
|
-
}
|
13
|
-
}
|
14
|
-
|
15
|
-
describe "with a valid authorization code and client" do
|
16
|
-
subject { AccessTokenRequest.new(client, params) }
|
17
|
-
|
18
|
-
before { subject.authorize }
|
19
|
-
|
20
|
-
it { should be_valid }
|
21
|
-
its(:token_type) { should == "bearer" }
|
22
|
-
its(:error) { should be_nil }
|
23
|
-
its(:refresh_token) { should be_nil }
|
24
|
-
|
25
|
-
it "has an access token" do
|
26
|
-
subject.access_token.token.should =~ /\w+/
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
describe "creating the access token" do
|
31
|
-
subject { AccessTokenRequest.new(client, params) }
|
32
|
-
|
33
|
-
it "creates with correct params" do
|
34
|
-
Doorkeeper::AccessToken.should_receive(:create!).with({
|
35
|
-
:application_id => client.id,
|
36
|
-
:resource_owner_id => grant.resource_owner_id,
|
37
|
-
:expires_in => 2.hours,
|
38
|
-
:scopes =>"public write",
|
39
|
-
:use_refresh_token => false,
|
40
|
-
})
|
41
|
-
subject.authorize
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe "with a valid authorization code, client and existing valid access token" do
|
46
|
-
subject { AccessTokenRequest.new(client, params) }
|
47
|
-
|
48
|
-
before { subject.authorize }
|
49
|
-
it { should be_valid }
|
50
|
-
its(:error) { should be_nil }
|
51
|
-
|
52
|
-
it "will not create a new token" do
|
53
|
-
subject.should_not_receive(:create_access_token)
|
54
|
-
subject.authorize
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
describe "with a valid authorization code, client and existing expired access token" do
|
59
|
-
before do
|
60
|
-
AccessTokenRequest.new(client, params).authorize
|
61
|
-
last_token = Doorkeeper::AccessToken.last
|
62
|
-
# TODO: make this better, maybe with an expire! method?
|
63
|
-
last_token.update_column :created_at, 10.days.ago
|
64
|
-
end
|
65
|
-
|
66
|
-
it "will create a new token" do
|
67
|
-
grant = FactoryGirl.create(:access_grant, :application => client)
|
68
|
-
authorization = AccessTokenRequest.new(client, params.merge(:code => grant.token))
|
69
|
-
expect {
|
70
|
-
authorization.authorize
|
71
|
-
}.to change { Doorkeeper::AccessToken.count }.by(1)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
describe "finding the current access token" do
|
76
|
-
subject { AccessTokenRequest.new(client, params) }
|
77
|
-
it { should be_valid }
|
78
|
-
its(:error) { should be_nil }
|
79
|
-
|
80
|
-
before { subject.authorize }
|
81
|
-
|
82
|
-
it "should find the access token and not create a new one" do
|
83
|
-
subject.should_not_receive(:create_access_token)
|
84
|
-
access_token = subject.authorize
|
85
|
-
subject.access_token.should eq(access_token)
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
describe "creating the first access_token" do
|
90
|
-
subject { AccessTokenRequest.new(client, params) }
|
91
|
-
it { should be_valid }
|
92
|
-
its(:error) { should be_nil }
|
93
|
-
|
94
|
-
it "should create a new access token" do
|
95
|
-
subject.should_receive(:create_access_token)
|
96
|
-
subject.authorize
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
describe "with errors" do
|
101
|
-
def token(params)
|
102
|
-
AccessTokenRequest.new(client, params)
|
103
|
-
end
|
104
|
-
|
105
|
-
it "includes the error in the response" do
|
106
|
-
access_token = token(params.except(:grant_type))
|
107
|
-
access_token.error_response.name.should == :invalid_request
|
108
|
-
end
|
109
|
-
|
110
|
-
[:grant_type, :code, :redirect_uri].each do |param|
|
111
|
-
describe "when :#{param} is missing" do
|
112
|
-
subject { token(params.except(param)) }
|
113
|
-
its(:error) { should == :invalid_request }
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
describe "when client is not present" do
|
118
|
-
subject { AccessTokenRequest.new(nil, params) }
|
119
|
-
its(:error) { should == :invalid_client }
|
120
|
-
end
|
121
|
-
|
122
|
-
describe "when :code does not exist" do
|
123
|
-
subject { token(params.merge(:code => "inexistent")) }
|
124
|
-
its(:error) { should == :invalid_grant }
|
125
|
-
end
|
126
|
-
|
127
|
-
describe "when :redirect_uri does not match with grant's one" do
|
128
|
-
subject { token(params.merge(:redirect_uri => "another")) }
|
129
|
-
its(:error) { should == :invalid_grant }
|
130
|
-
end
|
131
|
-
|
132
|
-
describe "when :grant_type is not 'authorization_code'" do
|
133
|
-
subject { token(params.merge(:grant_type => "invalid")) }
|
134
|
-
its(:error) { should == :unsupported_grant_type }
|
135
|
-
end
|
136
|
-
|
137
|
-
describe "when granted application does not match" do
|
138
|
-
subject { token(params) }
|
139
|
-
|
140
|
-
before do
|
141
|
-
grant.application = FactoryGirl.create(:application)
|
142
|
-
grant.save!
|
143
|
-
end
|
144
|
-
|
145
|
-
its(:error) { should == :invalid_grant }
|
146
|
-
end
|
147
|
-
|
148
|
-
describe "when :code is expired" do
|
149
|
-
it "error is :invalid_grant" do
|
150
|
-
grant # create grant instance
|
151
|
-
Timecop.freeze(Time.now + 700.seconds) do
|
152
|
-
expired = token(params)
|
153
|
-
expired.error.should == :invalid_grant
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
describe AccessTokenRequest, "refresh token" do
|
161
|
-
let(:client) { FactoryGirl.create(:application) }
|
162
|
-
let(:access) { FactoryGirl.create(:access_token, :application => client, :use_refresh_token => true) }
|
163
|
-
let(:params) {
|
164
|
-
{
|
165
|
-
:refresh_token => access.refresh_token,
|
166
|
-
:grant_type => "refresh_token",
|
167
|
-
}
|
168
|
-
}
|
169
|
-
|
170
|
-
before do
|
171
|
-
Doorkeeper.configure {
|
172
|
-
orm DOORKEEPER_ORM
|
173
|
-
use_refresh_token
|
174
|
-
}
|
175
|
-
end
|
176
|
-
|
177
|
-
describe "with a valid authorization code and client" do
|
178
|
-
subject { AccessTokenRequest.new(client, params) }
|
179
|
-
|
180
|
-
before do
|
181
|
-
subject.authorize
|
182
|
-
end
|
183
|
-
|
184
|
-
it { should be_valid }
|
185
|
-
its(:token_type) { should == "bearer" }
|
186
|
-
its(:error) { should be_nil }
|
187
|
-
its(:refresh_token) { should_not be_nil }
|
188
|
-
|
189
|
-
it "has an access token" do
|
190
|
-
subject.access_token.token.should =~ /\w+/
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
describe "with errors" do
|
195
|
-
def token(params)
|
196
|
-
AccessTokenRequest.new(client, params)
|
197
|
-
end
|
198
|
-
|
199
|
-
it "includes the error in the response" do
|
200
|
-
access_token = token(params.except(:grant_type))
|
201
|
-
access_token.error_response.name.should == :invalid_request
|
202
|
-
end
|
203
|
-
|
204
|
-
[:grant_type, :refresh_token].each do |param|
|
205
|
-
describe "when :#{param} is missing" do
|
206
|
-
subject { token(params.except(param)) }
|
207
|
-
its(:error) { should == :invalid_request }
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
describe "when client is not present" do
|
212
|
-
subject { AccessTokenRequest.new(nil, params) }
|
213
|
-
its(:error) { should == :invalid_client }
|
214
|
-
end
|
215
|
-
|
216
|
-
describe "when :refresh_token does not exist" do
|
217
|
-
subject { token(params.merge(:refresh_token => "inexistent")) }
|
218
|
-
its(:error) { should == :invalid_grant }
|
219
|
-
end
|
220
|
-
|
221
|
-
describe "when :grant_type is not 'refresh_token'" do
|
222
|
-
subject { token(params.merge(:grant_type => "invalid")) }
|
223
|
-
its(:error) { should == :invalid_request }
|
224
|
-
end
|
225
|
-
|
226
|
-
describe "when granted application does not match" do
|
227
|
-
subject { token(params) }
|
228
|
-
|
229
|
-
before do
|
230
|
-
access.application = FactoryGirl.create(:application)
|
231
|
-
access.save!
|
232
|
-
end
|
233
|
-
|
234
|
-
its(:error) { should == :invalid_grant }
|
235
|
-
end
|
236
|
-
|
237
|
-
describe "when :refresh_token is revoked" do
|
238
|
-
it "error is :invalid_grant" do
|
239
|
-
access.revoke # create grant instance
|
240
|
-
revoked = token(params)
|
241
|
-
revoked.error.should == :invalid_grant
|
242
|
-
end
|
243
|
-
end
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
@@ -1,287 +0,0 @@
|
|
1
|
-
require 'spec_helper_integration'
|
2
|
-
|
3
|
-
module Doorkeeper::OAuth
|
4
|
-
describe AuthorizationRequest do
|
5
|
-
let(:resource_owner) { double(:resource_owner, :id => 1) }
|
6
|
-
let(:client) { FactoryGirl.create(:application) }
|
7
|
-
let(:base_attributes) do
|
8
|
-
{
|
9
|
-
:redirect_uri => client.redirect_uri,
|
10
|
-
:scope => "public write",
|
11
|
-
:state => "return-this"
|
12
|
-
}
|
13
|
-
end
|
14
|
-
|
15
|
-
before :each do
|
16
|
-
Doorkeeper.configuration.stub(:confirm_application_owner?).and_return(false)
|
17
|
-
Doorkeeper.configuration.stub(:default_scopes).and_return(Doorkeeper::OAuth::Scopes.from_string('public write'))
|
18
|
-
end
|
19
|
-
|
20
|
-
describe "with a code response_type" do
|
21
|
-
let(:attributes) { base_attributes.merge!(:response_type => "code") }
|
22
|
-
|
23
|
-
describe "with valid attributes" do
|
24
|
-
subject { AuthorizationRequest.new(client, resource_owner, attributes) }
|
25
|
-
|
26
|
-
describe "after authorization" do
|
27
|
-
before { subject.authorize }
|
28
|
-
|
29
|
-
its(:response_type) { should == "code" }
|
30
|
-
its(:client_id) { should == client.uid }
|
31
|
-
its(:scope) { should == "public write" }
|
32
|
-
its(:state) { should == "return-this" }
|
33
|
-
its(:error) { should be_nil }
|
34
|
-
|
35
|
-
describe ".success_redirect_uri" do
|
36
|
-
let(:query) { URI.parse(subject.success_redirect_uri).query }
|
37
|
-
|
38
|
-
it "includes the grant code" do
|
39
|
-
query.should =~ %r{code=\w+}
|
40
|
-
end
|
41
|
-
|
42
|
-
it "includes the state previous assumed" do
|
43
|
-
query.should =~ %r{state=return-this}
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
describe :authorize do
|
49
|
-
let(:authorization_request) { AuthorizationRequest.new(client, resource_owner, attributes) }
|
50
|
-
subject { authorization_request.authorize }
|
51
|
-
|
52
|
-
it "returns Doorkeeper::AccessGrant object" do
|
53
|
-
subject.is_a? Doorkeeper::AccessGrant
|
54
|
-
end
|
55
|
-
|
56
|
-
it "returns instance saved in the database" do
|
57
|
-
subject.should be_persisted
|
58
|
-
end
|
59
|
-
|
60
|
-
it "returns object that has scopes attribute same as scope attribute of authorization request" do
|
61
|
-
subject.scopes == authorization_request.scope
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
describe "with a redirect_uri with query params" do
|
67
|
-
let(:original_query_params) { "abc=123&def=456" }
|
68
|
-
let(:attributes_with_query_params) {
|
69
|
-
u = URI.parse(client.redirect_uri)
|
70
|
-
u.query = original_query_params
|
71
|
-
attributes[:redirect_uri] = u.to_s
|
72
|
-
attributes
|
73
|
-
}
|
74
|
-
subject { AuthorizationRequest.new(client, resource_owner, attributes_with_query_params) }
|
75
|
-
|
76
|
-
it "preservers the original query when error"
|
77
|
-
|
78
|
-
describe "after authorization" do
|
79
|
-
before { subject.authorize }
|
80
|
-
|
81
|
-
describe ".success_redirect_uri" do
|
82
|
-
let(:query) { URI.parse(subject.success_redirect_uri).query }
|
83
|
-
|
84
|
-
it "includes the grant code" do
|
85
|
-
query.should =~ %r{code=\w+}
|
86
|
-
end
|
87
|
-
|
88
|
-
it "includes the state previous assumed" do
|
89
|
-
query.should =~ %r{state=return-this}
|
90
|
-
end
|
91
|
-
|
92
|
-
it "preserves the original query parameters" do
|
93
|
-
query.should =~ /abc=123/
|
94
|
-
query.should =~ /def=456/
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
describe "if no scope given" do
|
101
|
-
it "sets the scope to the default one" do
|
102
|
-
request = AuthorizationRequest.new(client, resource_owner, attributes.except(:scope))
|
103
|
-
request.scopes.to_s.should == "public write"
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
describe "with errors" do
|
108
|
-
before do
|
109
|
-
Doorkeeper::AccessGrant.should_not_receive(:create)
|
110
|
-
end
|
111
|
-
|
112
|
-
describe "when :response_type is missing" do
|
113
|
-
subject { auth(attributes.except(:response_type)) }
|
114
|
-
its(:error) { should == :invalid_request }
|
115
|
-
end
|
116
|
-
|
117
|
-
describe "when :redirect_uri is missing" do
|
118
|
-
subject { auth(attributes.except(:redirect_uri)) }
|
119
|
-
its(:error) { should == :invalid_redirect_uri }
|
120
|
-
end
|
121
|
-
|
122
|
-
describe "when client is not present" do
|
123
|
-
subject { AuthorizationRequest.new(nil, resource_owner, attributes) }
|
124
|
-
its(:error) { should == :invalid_client }
|
125
|
-
end
|
126
|
-
|
127
|
-
describe "when :redirect_uri mismatches" do
|
128
|
-
subject { auth(attributes.merge(:redirect_uri => "http://example.com/mismatch")) }
|
129
|
-
its(:error) { should == :invalid_redirect_uri }
|
130
|
-
end
|
131
|
-
|
132
|
-
describe "when :redirect_uri contains a fragment" do
|
133
|
-
subject { auth(attributes.merge(:redirect_uri => (client.redirect_uri + "#abc"))) }
|
134
|
-
its(:error) { should == :invalid_redirect_uri }
|
135
|
-
end
|
136
|
-
|
137
|
-
describe "when :redirect_uri is not a valid URI" do
|
138
|
-
subject { auth(attributes.merge(:redirect_uri => "invalid")) }
|
139
|
-
its(:error) { should == :invalid_redirect_uri }
|
140
|
-
end
|
141
|
-
|
142
|
-
describe "when :response_type is not 'code' or 'token'" do
|
143
|
-
subject { auth(attributes.merge(:response_type => "invalid")) }
|
144
|
-
its(:error) { should == :unsupported_response_type }
|
145
|
-
end
|
146
|
-
|
147
|
-
describe "when :scope contains scopes that are note registered in the provider" do
|
148
|
-
subject { auth(attributes.merge(:scope => "public strange")) }
|
149
|
-
its(:error) { should == :invalid_scope }
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
describe "with a token response_type" do
|
155
|
-
before do
|
156
|
-
Doorkeeper.configuration.stub(:access_token_expires_in).and_return(7200)
|
157
|
-
end
|
158
|
-
|
159
|
-
let(:attributes) { base_attributes.merge!(:response_type => "token") }
|
160
|
-
|
161
|
-
describe "with valid attributes" do
|
162
|
-
subject { AuthorizationRequest.new(client, resource_owner, attributes) }
|
163
|
-
|
164
|
-
describe "after authorization" do
|
165
|
-
before { subject.authorize }
|
166
|
-
|
167
|
-
its(:response_type) { should == "token" }
|
168
|
-
its(:scope) { should == "public write" }
|
169
|
-
its(:state) { should == "return-this" }
|
170
|
-
its(:error) { should be_nil }
|
171
|
-
|
172
|
-
describe ".success_redirect_uri" do
|
173
|
-
let(:fragment) { URI.parse(subject.success_redirect_uri).fragment }
|
174
|
-
|
175
|
-
it "has a fragment" do
|
176
|
-
fragment.should_not be_nil
|
177
|
-
end
|
178
|
-
|
179
|
-
it "doesn't have query parameters" do
|
180
|
-
URI.parse(subject.success_redirect_uri).query.should be_nil
|
181
|
-
end
|
182
|
-
|
183
|
-
it "includes the access token" do
|
184
|
-
fragment.should =~ %r{access_token=\w+}
|
185
|
-
end
|
186
|
-
|
187
|
-
it "includes the token type" do
|
188
|
-
fragment.should =~ %r{token_type=bearer}
|
189
|
-
end
|
190
|
-
|
191
|
-
it "includes the expires in" do
|
192
|
-
fragment.should =~ %r{expires_in=\w+}
|
193
|
-
end
|
194
|
-
|
195
|
-
it "includes the state previous assumed" do
|
196
|
-
fragment.should =~ %r{state=return-this}
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
describe :authorize do
|
202
|
-
let(:authorization_request) { AuthorizationRequest.new(client, resource_owner, attributes) }
|
203
|
-
subject { authorization_request.authorize }
|
204
|
-
|
205
|
-
it "returns Doorkeeper::AccessGrant object" do
|
206
|
-
subject.is_a? Doorkeeper::AccessGrant
|
207
|
-
end
|
208
|
-
|
209
|
-
it "returns instance saved in the database" do
|
210
|
-
subject.should be_persisted
|
211
|
-
end
|
212
|
-
|
213
|
-
it "returns object that has scopes attribute same as scope attribute of authorization request" do
|
214
|
-
subject.scopes == authorization_request.scope
|
215
|
-
end
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
describe "if no scope given" do
|
220
|
-
it "sets the scope to the default one" do
|
221
|
-
request = AuthorizationRequest.new(client, resource_owner, attributes.except(:scope))
|
222
|
-
request.scopes.to_s.should == "public write"
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
describe "with errors" do
|
227
|
-
before do
|
228
|
-
Doorkeeper::AccessGrant.should_not_receive(:create)
|
229
|
-
end
|
230
|
-
|
231
|
-
describe "when :response_type is missing" do
|
232
|
-
subject { auth(attributes.except(:response_type)) }
|
233
|
-
its(:error) { should == :invalid_request }
|
234
|
-
end
|
235
|
-
|
236
|
-
describe "when :redirect_uri is missing" do
|
237
|
-
subject { auth(attributes.except(:redirect_uri)) }
|
238
|
-
its(:error) { should == :invalid_redirect_uri }
|
239
|
-
end
|
240
|
-
|
241
|
-
describe "when client is not present" do
|
242
|
-
subject { AuthorizationRequest.new(nil, resource_owner, attributes) }
|
243
|
-
its(:error) { should == :invalid_client }
|
244
|
-
end
|
245
|
-
|
246
|
-
describe "when :redirect_uri has a fragment" do
|
247
|
-
subject { auth(attributes.merge(:redirect_uri => client.redirect_uri + "#xyz")) }
|
248
|
-
its(:error) { should == :invalid_redirect_uri }
|
249
|
-
end
|
250
|
-
|
251
|
-
describe "when :redirect_uri is a relative URI" do
|
252
|
-
subject { auth(attributes.merge(:redirect_uri => "/abcdef")) }
|
253
|
-
its(:error) { should == :invalid_redirect_uri }
|
254
|
-
end
|
255
|
-
|
256
|
-
describe "when :redirect_uri mismatches" do
|
257
|
-
subject { auth(attributes.merge(:redirect_uri => "http://example.com/mismatch")) }
|
258
|
-
its(:error) { should == :invalid_redirect_uri }
|
259
|
-
end
|
260
|
-
|
261
|
-
describe "when :redirect_uri contains a fragment" do
|
262
|
-
subject { auth(attributes.merge(:redirect_uri => (client.redirect_uri + "#abc"))) }
|
263
|
-
its(:error) { should == :invalid_redirect_uri }
|
264
|
-
end
|
265
|
-
|
266
|
-
describe "when :redirect_uri is not a valid URI" do
|
267
|
-
subject { auth(attributes.merge(:redirect_uri => "invalid")) }
|
268
|
-
its(:error) { should == :invalid_redirect_uri }
|
269
|
-
end
|
270
|
-
|
271
|
-
describe "when :response_type is not 'code' or 'token'" do
|
272
|
-
subject { auth(attributes.merge(:response_type => "invalid")) }
|
273
|
-
its(:error) { should == :unsupported_response_type }
|
274
|
-
end
|
275
|
-
|
276
|
-
describe "when :scope contains scopes that are note registered in the provider" do
|
277
|
-
subject { auth(attributes.merge(:scope => "public strange")) }
|
278
|
-
its(:error) { should == :invalid_scope }
|
279
|
-
end
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
def auth(attributes)
|
284
|
-
AuthorizationRequest.new(client, resource_owner, attributes)
|
285
|
-
end
|
286
|
-
end
|
287
|
-
end
|