doorkeeper 0.3.0 → 0.4.0
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 +12 -0
- data/.rspec +1 -0
- data/.travis.yml +8 -0
- data/CHANGELOG.md +98 -0
- data/Gemfile +6 -0
- data/README.md +42 -6
- data/app/controllers/doorkeeper/application_controller.rb +4 -11
- data/app/controllers/doorkeeper/applications_controller.rb +7 -1
- data/app/controllers/doorkeeper/authorizations_controller.rb +11 -1
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +3 -3
- data/app/controllers/doorkeeper/tokens_controller.rb +19 -5
- data/app/models/doorkeeper/access_grant.rb +28 -0
- data/app/models/doorkeeper/access_token.rb +65 -0
- data/app/models/doorkeeper/application.rb +54 -0
- data/app/views/doorkeeper/applications/index.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +15 -15
- data/app/views/doorkeeper/authorized_applications/index.html.erb +1 -2
- data/config/locales/en.yml +3 -0
- data/doorkeeper.gemspec +28 -0
- data/gemfiles/gemfile.rails-3.1.x +7 -0
- data/gemfiles/gemfile.rails-3.2.x +7 -0
- data/lib/doorkeeper/config.rb +73 -12
- data/lib/doorkeeper/doorkeeper_for.rb +19 -15
- data/lib/doorkeeper/engine.rb +28 -0
- data/lib/doorkeeper/models/scopes.rb +13 -0
- data/lib/doorkeeper/oauth/access_token_request.rb +9 -20
- data/lib/doorkeeper/oauth/authorization/code.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/token.rb +2 -2
- data/lib/doorkeeper/oauth/authorization_request.rb +18 -23
- data/lib/doorkeeper/oauth/client/credentials.rb +21 -0
- data/lib/doorkeeper/oauth/client/methods.rb +18 -0
- data/lib/doorkeeper/oauth/client.rb +27 -0
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +29 -0
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +35 -0
- data/lib/doorkeeper/oauth/client_credentials/response.rb +42 -0
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +33 -0
- data/lib/doorkeeper/oauth/client_credentials_request.rb +46 -0
- data/lib/doorkeeper/oauth/error.rb +9 -0
- data/lib/doorkeeper/oauth/error_response.rb +30 -0
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -2
- data/lib/doorkeeper/oauth/password_access_token_request.rb +130 -0
- data/lib/doorkeeper/oauth/scopes.rb +60 -0
- data/lib/doorkeeper/version.rb +1 -1
- data/lib/doorkeeper.rb +23 -3
- data/lib/generators/doorkeeper/install_generator.rb +1 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +12 -7
- data/lib/generators/doorkeeper/templates/migration.rb +1 -1
- data/lib/generators/doorkeeper/views_generator.rb +15 -0
- data/script/rails +6 -0
- data/script/run_all +11 -0
- data/spec/controllers/applications_controller_spec.rb +18 -0
- data/spec/controllers/authorizations_controller_spec.rb +131 -0
- data/spec/controllers/protected_resources_controller_spec.rb +308 -0
- data/spec/controllers/tokens_controller_spec.rb +34 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +9 -0
- data/spec/dummy/app/assets/stylesheets/application.css +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +12 -0
- data/spec/dummy/app/controllers/home_controller.rb +17 -0
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +11 -0
- data/spec/dummy/app/helpers/application_helper.rb +5 -0
- data/spec/dummy/app/models/user.rb +11 -0
- data/spec/dummy/app/views/home/index.html.erb +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +16 -0
- data/spec/dummy/config/application.rb +53 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +15 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +30 -0
- data/spec/dummy/config/environments/production.rb +60 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/doorkeeper.rb +41 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/doorkeeper.en.yml +5 -0
- data/spec/dummy/config/routes.rb +8 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +9 -0
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +5 -0
- data/spec/dummy/db/migrate/20120524202412_create_doorkeeper_tables.rb +42 -0
- data/spec/dummy/db/schema.rb +62 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/factories/access_grant.rb +9 -0
- data/spec/factories/access_token.rb +7 -0
- data/spec/factories/application.rb +6 -0
- data/spec/generators/install_generator_spec.rb +35 -0
- data/spec/generators/templates/routes.rb +3 -0
- data/spec/generators/views_generator_spec.rb +27 -0
- data/spec/lib/config_spec.rb +87 -0
- data/spec/lib/models/expirable_spec.rb +49 -0
- data/spec/lib/models/revocable_spec.rb +31 -0
- data/spec/lib/models/scopes_spec.rb +32 -0
- data/spec/lib/oauth/access_token_request_spec.rb +240 -0
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +37 -0
- data/spec/lib/oauth/authorization_request_spec.rb +286 -0
- data/spec/lib/oauth/client/credentials_spec.rb +47 -0
- data/spec/lib/oauth/client/methods_spec.rb +54 -0
- data/spec/lib/oauth/client_credentials/creator_spec.rb +47 -0
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +57 -0
- data/spec/lib/oauth/client_credentials/response_spec.rb +58 -0
- data/spec/lib/oauth/client_credentials/validation_spec.rb +29 -0
- data/spec/lib/oauth/client_credentials_integration_spec.rb +27 -0
- data/spec/lib/oauth/client_credentials_request_spec.rb +60 -0
- data/spec/lib/oauth/client_spec.rb +42 -0
- data/spec/lib/oauth/error_response_spec.rb +40 -0
- data/spec/lib/oauth/error_spec.rb +19 -0
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +74 -0
- data/spec/lib/oauth/helpers/unique_token_spec.rb +38 -0
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +64 -0
- data/spec/lib/oauth/password_access_token_request_spec.rb +152 -0
- data/spec/lib/oauth/scopes_spec.rb +115 -0
- data/spec/models/doorkeeper/access_grant_spec.rb +36 -0
- data/spec/models/doorkeeper/access_token_spec.rb +113 -0
- data/spec/models/doorkeeper/application_spec.rb +129 -0
- data/spec/requests/applications/applications_request_spec.rb +92 -0
- data/spec/requests/applications/authorized_applications_spec.rb +30 -0
- data/spec/requests/endpoints/authorization_spec.rb +63 -0
- data/spec/requests/endpoints/token_spec.rb +29 -0
- data/spec/requests/flows/authorization_code_errors_spec.rb +111 -0
- data/spec/requests/flows/authorization_code_spec.rb +125 -0
- data/spec/requests/flows/client_credentials_spec.rb +56 -0
- data/spec/requests/flows/implicit_grant_errors_spec.rb +31 -0
- data/spec/requests/flows/implicit_grant_spec.rb +19 -0
- data/spec/requests/flows/password_spec.rb +52 -0
- data/spec/requests/flows/refresh_token_spec.rb +66 -0
- data/spec/requests/flows/skip_authorization_spec.rb +40 -0
- data/spec/requests/protected_resources/private_api_spec.rb +43 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/spec_helper_integration.rb +28 -0
- data/spec/support/dependencies/database_cleaner.rb +16 -0
- data/spec/support/dependencies/factory_girl.rb +5 -0
- data/spec/support/helpers/access_token_request_helper.rb +11 -0
- data/spec/support/helpers/authorization_request_helper.rb +32 -0
- data/spec/support/helpers/config_helper.rb +9 -0
- data/spec/support/helpers/model_helper.rb +45 -0
- data/spec/support/helpers/request_spec_helper.rb +72 -0
- data/spec/support/helpers/url_helper.rb +51 -0
- data/spec/support/shared/controllers_shared_context.rb +60 -0
- data/spec/support/shared/models_shared_examples.rb +44 -0
- metadata +163 -57
- data/app/controllers/doorkeeper/application_controller.rbc +0 -675
- data/app/controllers/doorkeeper/applications_controller.rbc +0 -954
- data/app/controllers/doorkeeper/authorizations_controller.rbc +0 -659
- data/app/controllers/doorkeeper/authorized_applications_controller.rbc +0 -393
- data/app/controllers/doorkeeper/tokens_controller.rbc +0 -423
- data/app/helpers/doorkeeper/application_helper.rbc +0 -127
- data/app/models/access_grant.rb +0 -31
- data/app/models/access_grant.rbc +0 -821
- data/app/models/access_token.rb +0 -70
- data/app/models/access_token.rbc +0 -979
- data/app/models/application.rb +0 -45
- data/app/models/application.rbc +0 -753
- data/config/initializers/form_errors.rbc +0 -272
- data/config/routes.rbc +0 -366
- data/lib/doorkeeper/config/scope.rb +0 -11
- data/lib/doorkeeper/config/scopes.rb +0 -61
- data/lib/doorkeeper/config/scopes_builder.rb +0 -18
- data/lib/doorkeeper/config.rbc +0 -1385
- data/lib/doorkeeper/doorkeeper_for.rbc +0 -1029
- data/lib/doorkeeper/engine.rbc +0 -318
- data/lib/doorkeeper/oauth/access_token_request.rbc +0 -2042
- data/lib/doorkeeper/oauth/authorization_request.rbc +0 -2272
- data/lib/doorkeeper/oauth/random_string.rbc +0 -437
- data/lib/doorkeeper/validations.rbc +0 -774
- data/lib/doorkeeper/version.rbc +0 -130
- data/lib/doorkeeper.rbc +0 -407
- data/lib/generators/doorkeeper/install_generator.rbc +0 -453
- data/lib/tasks/doorkeeper_tasks.rake.compiled.rbc +0 -40
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require 'spec_helper_integration'
|
|
2
|
+
|
|
3
|
+
class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
4
|
+
describe Creator do
|
|
5
|
+
let(:client) { FactoryGirl.create :application }
|
|
6
|
+
let(:scopes) { Doorkeeper::OAuth::Scopes.from_string('public') }
|
|
7
|
+
|
|
8
|
+
it 'creates a new token' do
|
|
9
|
+
expect do
|
|
10
|
+
subject.call(client, scopes)
|
|
11
|
+
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'returns false if creation fails' do
|
|
15
|
+
Doorkeeper::AccessToken.should_receive(:create).and_return(false)
|
|
16
|
+
created = subject.call(client, scopes)
|
|
17
|
+
created.should be_false
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'does not create a new token if there is an accessible one' do
|
|
21
|
+
subject.call(client, scopes, :expires_in => 10.years)
|
|
22
|
+
expect do
|
|
23
|
+
subject.call(client, scopes)
|
|
24
|
+
end.to_not change { Doorkeeper::AccessToken.count }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'returns the existing token if there is an accessible one' do
|
|
28
|
+
existing = subject.call(client, scopes, :expires_in => 10.years)
|
|
29
|
+
created = subject.call(client, scopes)
|
|
30
|
+
created.should == existing
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'revokes old token if is not accessible' do
|
|
34
|
+
existing = subject.call(client, scopes, :expires_in => -1000)
|
|
35
|
+
subject.call(client, scopes)
|
|
36
|
+
existing.reload.should be_revoked
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'returns a new token when the old one is not accessible' do
|
|
40
|
+
existing = subject.call(client, scopes, :expires_in => -1000)
|
|
41
|
+
|
|
42
|
+
expect do
|
|
43
|
+
subject.call(client, scopes)
|
|
44
|
+
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'active_support/all'
|
|
3
|
+
require 'doorkeeper/oauth/client_credentials/issuer'
|
|
4
|
+
|
|
5
|
+
class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
6
|
+
describe Issuer do
|
|
7
|
+
let(:creator) { mock :acces_token_creator }
|
|
8
|
+
let(:server) { mock :server, :access_token_expires_in => 100 }
|
|
9
|
+
let(:validation) { mock :validation, :valid? => true }
|
|
10
|
+
|
|
11
|
+
subject { Issuer.new(server, validation) }
|
|
12
|
+
|
|
13
|
+
describe :create do
|
|
14
|
+
let(:client) { mock :client, :id => 'some-id' }
|
|
15
|
+
let(:scopes) { 'some scope' }
|
|
16
|
+
|
|
17
|
+
it 'creates and sets the token' do
|
|
18
|
+
creator.should_receive(:call).and_return('token')
|
|
19
|
+
subject.create client, scopes, creator
|
|
20
|
+
|
|
21
|
+
subject.token.should == 'token'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'creates with correct token parameters' do
|
|
25
|
+
creator.should_receive(:call).with(client, scopes, {
|
|
26
|
+
:expires_in => 100,
|
|
27
|
+
:use_refresh_token => false
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
subject.create client, scopes, creator
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'has error set to :server_error if creator fails' do
|
|
34
|
+
creator.should_receive(:call).and_return(false)
|
|
35
|
+
subject.create client, scopes, creator
|
|
36
|
+
|
|
37
|
+
subject.error.should == :server_error
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context 'when validation fails' do
|
|
41
|
+
before do
|
|
42
|
+
validation.stub :valid? => false, :error => :validation_error
|
|
43
|
+
creator.should_not_receive(:create)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'has error set from validation' do
|
|
47
|
+
subject.create client, scopes, creator
|
|
48
|
+
subject.error.should == :validation_error
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'returns false' do
|
|
52
|
+
subject.create(client, scopes, creator).should be_false
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'doorkeeper/oauth/client_credentials/response'
|
|
3
|
+
|
|
4
|
+
class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
5
|
+
describe Response do
|
|
6
|
+
subject { Response.new(stub.as_null_object) }
|
|
7
|
+
|
|
8
|
+
it 'includes access token response headers' do
|
|
9
|
+
headers = subject.headers
|
|
10
|
+
headers.fetch('Cache-Control').should == 'no-store'
|
|
11
|
+
headers.fetch('Pragma').should == 'no-cache'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'status is success' do
|
|
15
|
+
subject.status.should == :success
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'token_type is bearer' do
|
|
19
|
+
subject.token_type.should == 'bearer'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'can be serialized to JSON' do
|
|
23
|
+
subject.should respond_to(:to_json)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context 'attributes' do
|
|
27
|
+
let(:access_token) do
|
|
28
|
+
mock :access_token, {
|
|
29
|
+
:token => 'some-token',
|
|
30
|
+
:expires_in => '3600',
|
|
31
|
+
:scopes_string => 'two scopes'
|
|
32
|
+
}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
subject { Response.new(access_token).attributes }
|
|
36
|
+
|
|
37
|
+
it 'includes :access_token' do
|
|
38
|
+
subject['access_token'].should == 'some-token'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'includes :token_type' do
|
|
42
|
+
subject['token_type'].should == 'bearer'
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'includes :expires_in' do
|
|
46
|
+
subject['expires_in'].should == '3600'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'includes :scope' do
|
|
50
|
+
subject['scope'].should == 'two scopes'
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'does not include refresh_token (disabled in this flow)' do
|
|
54
|
+
subject.should_not have_key('refresh_token')
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'active_support/all'
|
|
3
|
+
require 'doorkeeper/oauth/client_credentials/validation'
|
|
4
|
+
|
|
5
|
+
class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
6
|
+
describe Validation do
|
|
7
|
+
let(:server) { mock :server, :scopes => nil }
|
|
8
|
+
let(:request) { mock :request, :client => stub, :original_scopes => nil }
|
|
9
|
+
|
|
10
|
+
subject { Validation.new(server, request) }
|
|
11
|
+
|
|
12
|
+
it 'is valid with valid request' do
|
|
13
|
+
subject.should be_valid
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'is invalid when client is not present' do
|
|
17
|
+
request.stub :client => nil
|
|
18
|
+
subject.should_not be_valid
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context 'with scopes' do
|
|
22
|
+
it 'is invalid when scopes are not included in the server' do
|
|
23
|
+
server.stub :scopes => Doorkeeper::OAuth::Scopes.from_string('email')
|
|
24
|
+
request.stub :original_scopes => 'invalid'
|
|
25
|
+
subject.should_not be_valid
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'spec_helper_integration'
|
|
2
|
+
|
|
3
|
+
module Doorkeeper::OAuth
|
|
4
|
+
describe ClientCredentialsRequest do
|
|
5
|
+
let(:server) { Doorkeeper.configuration }
|
|
6
|
+
|
|
7
|
+
context 'with a valid request' do
|
|
8
|
+
let(:client) { FactoryGirl.create :application }
|
|
9
|
+
|
|
10
|
+
it 'issues an access token' do
|
|
11
|
+
request = ClientCredentialsRequest.new(server, client, {})
|
|
12
|
+
expect do
|
|
13
|
+
request.authorize
|
|
14
|
+
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe 'with an invalid request' do
|
|
19
|
+
it 'does not issue an access token' do
|
|
20
|
+
request = ClientCredentialsRequest.new(server, nil, {})
|
|
21
|
+
expect do
|
|
22
|
+
request.authorize
|
|
23
|
+
end.to_not change { Doorkeeper::AccessToken.count }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'active_support/all'
|
|
3
|
+
require 'active_model'
|
|
4
|
+
require 'doorkeeper/oauth/client_credentials_request'
|
|
5
|
+
|
|
6
|
+
module Doorkeeper::OAuth
|
|
7
|
+
describe ClientCredentialsRequest do
|
|
8
|
+
let(:server) { stub :default_scopes => nil }
|
|
9
|
+
let(:client) { stub }
|
|
10
|
+
let(:token_creator) { mock :issuer, :create => true, :token => stub }
|
|
11
|
+
|
|
12
|
+
subject { ClientCredentialsRequest.new(server, client) }
|
|
13
|
+
|
|
14
|
+
before do
|
|
15
|
+
subject.issuer = token_creator
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'issues an access token for the current client' do
|
|
19
|
+
token_creator.should_receive(:create).with(client, nil)
|
|
20
|
+
subject.authorize
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'has successful response when issue was created' do
|
|
24
|
+
subject.authorize
|
|
25
|
+
subject.response.should be_a(ClientCredentialsRequest::Response)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'has an error response if issue was not created' do
|
|
29
|
+
subject.issuer = stub :create => false, :error => :invalid
|
|
30
|
+
subject.authorize
|
|
31
|
+
subject.response.should be_a(Doorkeeper::OAuth::ErrorResponse)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'delegates the error to issuer' do
|
|
35
|
+
subject.issuer = stub :create => false, :error => :invalid
|
|
36
|
+
subject.authorize
|
|
37
|
+
subject.error.should == :invalid
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context 'with scopes' do
|
|
41
|
+
let(:default_scopes) { Doorkeeper::OAuth::Scopes.from_string("public email") }
|
|
42
|
+
|
|
43
|
+
before do
|
|
44
|
+
server.stub(:default_scopes).and_return(default_scopes)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'issues an access token with default scopes if none was requested' do
|
|
48
|
+
token_creator.should_receive(:create).with(client, default_scopes)
|
|
49
|
+
subject.authorize
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'issues an access token with requested scopes' do
|
|
53
|
+
subject = ClientCredentialsRequest.new(server, client, :scope => "email")
|
|
54
|
+
subject.issuer = token_creator
|
|
55
|
+
token_creator.should_receive(:create).with(client, Doorkeeper::OAuth::Scopes.from_string("email"))
|
|
56
|
+
subject.authorize
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'active_support/core_ext/module/delegation'
|
|
3
|
+
require 'active_support/core_ext/string'
|
|
4
|
+
require 'doorkeeper/oauth/client'
|
|
5
|
+
|
|
6
|
+
module Doorkeeper::OAuth
|
|
7
|
+
class Doorkeeper::Application
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe Client do
|
|
11
|
+
describe :find do
|
|
12
|
+
let(:uid) { "some-uid" }
|
|
13
|
+
|
|
14
|
+
it 'finds the client via uid' do
|
|
15
|
+
client = stub
|
|
16
|
+
Doorkeeper::Application.should_receive(:find_by_uid).with(uid).and_return(client)
|
|
17
|
+
Client.find(uid).should be_a(Client)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'returns nil if client was not found' do
|
|
21
|
+
Doorkeeper::Application.should_receive(:find_by_uid).with(uid).and_return(nil)
|
|
22
|
+
Client.find(uid).should be_nil
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe :authenticate do
|
|
27
|
+
it 'returns the authenticated client via credentials' do
|
|
28
|
+
credentials = Client::Credentials.new("some-uid", "some-secret")
|
|
29
|
+
authenticator = mock
|
|
30
|
+
authenticator.should_receive(:call).with("some-uid", "some-secret").and_return(stub)
|
|
31
|
+
Client.authenticate(credentials, authenticator).should be_a(Client)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'retunrs nil if client was not authenticated' do
|
|
35
|
+
credentials = Client::Credentials.new("some-uid", "some-secret")
|
|
36
|
+
authenticator = mock
|
|
37
|
+
authenticator.should_receive(:call).with("some-uid", "some-secret").and_return(nil)
|
|
38
|
+
Client.authenticate(credentials, authenticator).should be_nil
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'active_model'
|
|
3
|
+
require 'doorkeeper/oauth/error'
|
|
4
|
+
require 'doorkeeper/oauth/error_response'
|
|
5
|
+
|
|
6
|
+
module Doorkeeper::OAuth
|
|
7
|
+
describe ErrorResponse do
|
|
8
|
+
its(:status) { should == :unauthorized }
|
|
9
|
+
|
|
10
|
+
describe :from_request do
|
|
11
|
+
it 'has the error from request' do
|
|
12
|
+
error = ErrorResponse.from_request stub(:error => :some_error)
|
|
13
|
+
error.name.should == :some_error
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'ignores state if request does not respond to state' do
|
|
17
|
+
error = ErrorResponse.from_request stub(:error => :some_error)
|
|
18
|
+
error.state.should be_nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'has state if request responds to state' do
|
|
22
|
+
error = ErrorResponse.from_request stub(:error => :some_error, :state => :hello)
|
|
23
|
+
error.state.should == :hello
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'ignores empty attributes' do
|
|
28
|
+
subject = ErrorResponse.new(:error => :some_error, :state => nil)
|
|
29
|
+
subject.attributes.should_not have_key(:state)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
context 'json response' do
|
|
33
|
+
subject { ErrorResponse.new(:name => :some_error, :state => :some_state).as_json }
|
|
34
|
+
|
|
35
|
+
it { should have_key('error') }
|
|
36
|
+
it { should have_key('error_description') }
|
|
37
|
+
it { should have_key('state') }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'active_support/i18n'
|
|
3
|
+
require 'doorkeeper/oauth/error'
|
|
4
|
+
|
|
5
|
+
module Doorkeeper::OAuth
|
|
6
|
+
describe Error do
|
|
7
|
+
subject { Error.new(:some_error, :some_state) }
|
|
8
|
+
|
|
9
|
+
it { should respond_to(:name) }
|
|
10
|
+
it { should respond_to(:state) }
|
|
11
|
+
|
|
12
|
+
describe :description do
|
|
13
|
+
it 'is translated from translation messages' do
|
|
14
|
+
I18n.should_receive(:translate).with(:some_error, :scope => [:doorkeeper, :errors, :messages])
|
|
15
|
+
subject.description
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'active_support/core_ext/string'
|
|
3
|
+
require 'doorkeeper/oauth/helpers/scope_checker'
|
|
4
|
+
require 'doorkeeper/oauth/scopes'
|
|
5
|
+
|
|
6
|
+
module Doorkeeper::OAuth::Helpers
|
|
7
|
+
describe ScopeChecker, ".matches?" do
|
|
8
|
+
def new_scope(*args)
|
|
9
|
+
Doorkeeper::OAuth::Scopes.from_array args
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "true if scopes matches" do
|
|
13
|
+
scopes = new_scope :public
|
|
14
|
+
scopes_to_match = new_scope :public
|
|
15
|
+
ScopeChecker.matches?(scopes, scopes_to_match).should be_true
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "is false when scopes differs" do
|
|
19
|
+
scopes = new_scope :public
|
|
20
|
+
scopes_to_match = new_scope :write
|
|
21
|
+
ScopeChecker.matches?(scopes, scopes_to_match).should be_false
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "is false when scope in array is missing" do
|
|
25
|
+
scopes = new_scope :public
|
|
26
|
+
scopes_to_match = new_scope :public, :write
|
|
27
|
+
ScopeChecker.matches?(scopes, scopes_to_match).should be_false
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "is false when scope in string is missing" do
|
|
31
|
+
scopes = new_scope :public, :write
|
|
32
|
+
scopes_to_match = new_scope :public
|
|
33
|
+
ScopeChecker.matches?(scopes, scopes_to_match).should be_false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "is false when any of attributes is nil" do
|
|
37
|
+
ScopeChecker.matches?(nil, stub).should be_false
|
|
38
|
+
ScopeChecker.matches?(stub, nil).should be_false
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe ScopeChecker, ".valid?" do
|
|
43
|
+
let(:server_scopes) { Doorkeeper::OAuth::Scopes.new }
|
|
44
|
+
|
|
45
|
+
it "is valid if scope is present" do
|
|
46
|
+
server_scopes.add :scope
|
|
47
|
+
ScopeChecker.valid?("scope", server_scopes).should be_true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "is invalid if includes tabs space" do
|
|
51
|
+
ScopeChecker.valid?("\tsomething", server_scopes).should be_false
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "is invalid if scope is not present" do
|
|
55
|
+
ScopeChecker.valid?(nil, server_scopes).should be_false
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "is invalid if scope is blank" do
|
|
59
|
+
ScopeChecker.valid?(" ", server_scopes).should be_false
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "is invalid if includes return space" do
|
|
63
|
+
ScopeChecker.valid?("scope\r", server_scopes).should be_false
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "is invalid if includes new lines" do
|
|
67
|
+
ScopeChecker.valid?("scope\nanother", server_scopes).should be_false
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "is invalid if any scope is not included in server scopes" do
|
|
71
|
+
ScopeChecker.valid?("scope another", server_scopes).should be_false
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'doorkeeper/oauth/helpers/unique_token'
|
|
3
|
+
|
|
4
|
+
module Doorkeeper::OAuth::Helpers
|
|
5
|
+
describe UniqueToken do
|
|
6
|
+
let(:klass) { mock }
|
|
7
|
+
|
|
8
|
+
let :generator do
|
|
9
|
+
lambda { |size| "a" * size }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "finds in the collection with given attribute" do
|
|
13
|
+
klass.should_receive(:find_by_attribute).and_return(nil)
|
|
14
|
+
UniqueToken.generate_for(:attribute, klass, :generator => generator)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "is able to customize the generator method" do
|
|
18
|
+
klass.stub(:find_by_attribute).and_return(nil)
|
|
19
|
+
token = UniqueToken.generate_for(:attribute, klass, :generator => generator)
|
|
20
|
+
token.should == "a" * 32
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "is able to customize the size of the token" do
|
|
24
|
+
klass.stub(:find_by_attribute).and_return(nil)
|
|
25
|
+
token = UniqueToken.generate_for(:attribute, klass, :generator => generator, :size => 2)
|
|
26
|
+
token.should == "aa"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "reattempt to create a token if has already found one" do
|
|
30
|
+
existing_tokens = ["a"*32, nil]
|
|
31
|
+
attempted_tokens = ["a"*32, "b"]
|
|
32
|
+
generator = lambda { |size| attempted_tokens.pop }
|
|
33
|
+
klass.stub(:find_by_attribute) { existing_tokens.pop }
|
|
34
|
+
token = UniqueToken.generate_for(:attribute, klass, :generator => generator)
|
|
35
|
+
token.should == "b"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'uri'
|
|
3
|
+
require 'doorkeeper/oauth/helpers/uri_checker'
|
|
4
|
+
|
|
5
|
+
module Doorkeeper::OAuth::Helpers
|
|
6
|
+
describe URIChecker do
|
|
7
|
+
describe ".valid?" do
|
|
8
|
+
it "is valid for valid uris" do
|
|
9
|
+
uri = "http://app.co"
|
|
10
|
+
URIChecker.valid?(uri).should be_true
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "is valid if include path param" do
|
|
14
|
+
uri = "http://app.co/path"
|
|
15
|
+
URIChecker.valid?(uri).should be_true
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "is valid if include query param" do
|
|
19
|
+
uri = "http://app.co/?query=1"
|
|
20
|
+
URIChecker.valid?(uri).should be_true
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "is invalid if uri includes fragment" do
|
|
24
|
+
uri = "http://app.co/test#fragment"
|
|
25
|
+
URIChecker.valid?(uri).should be_false
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "is invalid if scheme is missing" do
|
|
29
|
+
uri = "app.co"
|
|
30
|
+
URIChecker.valid?(uri).should be_false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "is invalid if is a relative uri" do
|
|
34
|
+
uri = "/abc/123"
|
|
35
|
+
URIChecker.valid?(uri).should be_false
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "is invalid if is not a url" do
|
|
39
|
+
uri = "http://"
|
|
40
|
+
URIChecker.valid?(uri).should be_false
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe ".matches?" do
|
|
45
|
+
it "is true if both url matches" do
|
|
46
|
+
uri = client_uri = 'http://app.co/aaa'
|
|
47
|
+
URIChecker.matches?(uri, client_uri).should be_true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "ignores query parameter on comparsion" do
|
|
51
|
+
uri = 'http://app.co/?query=hello'
|
|
52
|
+
client_uri = 'http://app.co'
|
|
53
|
+
URIChecker.matches?(uri, client_uri).should be_true
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe ".valid_for_authorization?" do
|
|
58
|
+
it "is true if valid and matches" do
|
|
59
|
+
uri = client_uri = 'http://app.co/aaa'
|
|
60
|
+
URIChecker.valid_for_authorization?(uri, client_uri).should be_true
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|