doorkeeper 0.7.4 → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/Gemfile +0 -2
- data/README.md +1 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +2 -0
- data/app/views/doorkeeper/applications/_delete_form.html.erb +16 -0
- data/app/views/doorkeeper/applications/index.html.erb +6 -2
- data/app/views/doorkeeper/applications/show.html.erb +1 -1
- data/app/views/doorkeeper/authorized_applications/index.html.erb +1 -1
- data/app/views/layouts/doorkeeper/application.html.erb +0 -1
- data/doorkeeper.gemspec +0 -1
- data/lib/doorkeeper/doorkeeper_for.rb +2 -2
- data/lib/doorkeeper/models/access_token.rb +5 -2
- data/lib/doorkeeper/models/application.rb +2 -2
- data/lib/doorkeeper/oauth/password_access_token_request.rb +13 -8
- data/lib/doorkeeper/oauth/refresh_token_request.rb +38 -12
- data/lib/doorkeeper/oauth/token_response.rb +1 -1
- data/lib/doorkeeper/request/password.rb +5 -5
- data/lib/doorkeeper/request/refresh_token.rb +5 -5
- data/lib/doorkeeper/version.rb +1 -1
- data/lib/generators/doorkeeper/templates/migration.rb +1 -1
- data/spec/controllers/applications_controller_spec.rb +9 -0
- data/spec/controllers/protected_resources_controller_spec.rb +2 -2
- data/spec/controllers/tokens_controller_spec.rb +1 -1
- data/spec/dummy/app/views/layouts/application.html.erb +0 -2
- data/spec/dummy/config/environments/test.rb +11 -2
- data/spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb +1 -1
- data/spec/dummy/db/schema.rb +1 -1
- data/spec/factories/access_token.rb +4 -0
- data/spec/lib/models/revocable_spec.rb +2 -2
- data/spec/lib/oauth/authorization_code_request_spec.rb +1 -1
- data/spec/lib/oauth/client/credentials_spec.rb +2 -2
- data/spec/lib/oauth/client/methods_spec.rb +4 -4
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +4 -4
- data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -2
- data/spec/lib/oauth/client_credentials_request_spec.rb +4 -4
- data/spec/lib/oauth/client_spec.rb +5 -5
- data/spec/lib/oauth/code_request_spec.rb +3 -3
- data/spec/lib/oauth/error_response_spec.rb +3 -3
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +2 -2
- data/spec/lib/oauth/password_access_token_request_spec.rb +26 -10
- data/spec/lib/oauth/pre_authorization_spec.rb +2 -2
- data/spec/lib/oauth/refresh_token_request_spec.rb +52 -10
- data/spec/lib/oauth/token_request_spec.rb +3 -3
- data/spec/lib/oauth/token_response_spec.rb +8 -5
- data/spec/lib/oauth/token_spec.rb +8 -8
- data/spec/lib/server_spec.rb +1 -1
- data/spec/models/doorkeeper/access_token_spec.rb +6 -9
- data/spec/models/doorkeeper/application_spec.rb +16 -1
- data/spec/requests/applications/applications_request_spec.rb +3 -3
- data/spec/requests/flows/password_spec.rb +20 -0
- data/spec/requests/protected_resources/private_api_spec.rb +8 -0
- metadata +5 -21
- data/app/assets/javascripts/doorkeeper/application.js +0 -2
- data/spec/dummy/app/assets/javascripts/application.js +0 -9
- data/spec/dummy/app/assets/stylesheets/application.css +0 -7
@@ -28,7 +28,7 @@ describe Doorkeeper::TokensController do
|
|
28
28
|
|
29
29
|
it "returns the error response" do
|
30
30
|
pending 'verify need of these specs'
|
31
|
-
token.stub(:error_response =>
|
31
|
+
token.stub(:error_response => double(:to_json => [], :status => :unauthorized))
|
32
32
|
post :create
|
33
33
|
expect(response.status).to eq 401
|
34
34
|
end
|
@@ -11,8 +11,17 @@ Dummy::Application.configure do
|
|
11
11
|
config.serve_static_assets = true
|
12
12
|
config.static_cache_control = "public, max-age=3600"
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
if Rails.version.to_i < 4
|
15
|
+
# Log error messages when you accidentally call methods on nil
|
16
|
+
config.whiny_nils = true
|
17
|
+
end
|
18
|
+
|
19
|
+
if Rails.version.to_i >= 4
|
20
|
+
# Do not eager load code on boot. This avoids loading your whole application
|
21
|
+
# just for the purpose of running a single test. If you are using a tool that
|
22
|
+
# preloads Rails for running tests, you may have to set it to true.
|
23
|
+
config.eager_load = false
|
24
|
+
end
|
16
25
|
|
17
26
|
# Show full error reports and disable caching
|
18
27
|
config.consider_all_requests_local = true
|
@@ -25,7 +25,7 @@ class CreateDoorkeeperTables < ActiveRecord::Migration
|
|
25
25
|
|
26
26
|
create_table :oauth_access_tokens do |t|
|
27
27
|
t.integer :resource_owner_id
|
28
|
-
t.integer :application_id
|
28
|
+
t.integer :application_id
|
29
29
|
t.string :token, :null => false
|
30
30
|
t.string :refresh_token
|
31
31
|
t.integer :expires_in
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -28,7 +28,7 @@ ActiveRecord::Schema.define(:version => 20130902175349) do
|
|
28
28
|
|
29
29
|
create_table "oauth_access_tokens", :force => true do |t|
|
30
30
|
t.integer "resource_owner_id"
|
31
|
-
t.integer "application_id"
|
31
|
+
t.integer "application_id"
|
32
32
|
t.string "token", :null => false
|
33
33
|
t.string "refresh_token"
|
34
34
|
t.integer "expires_in"
|
@@ -11,7 +11,7 @@ describe 'Revocable' do
|
|
11
11
|
|
12
12
|
describe :revoke do
|
13
13
|
it "updates :revoked_at attribute with current time" do
|
14
|
-
clock = double :now =>
|
14
|
+
clock = double :now => double
|
15
15
|
subject.should_receive(:update_column).with(:revoked_at, clock.now)
|
16
16
|
subject.revoke(clock)
|
17
17
|
end
|
@@ -19,7 +19,7 @@ describe 'Revocable' do
|
|
19
19
|
|
20
20
|
describe :revoked? do
|
21
21
|
it "is revoked if :revoked_at is set" do
|
22
|
-
subject.stub :revoked_at =>
|
22
|
+
subject.stub :revoked_at => double
|
23
23
|
subject.should be_revoked
|
24
24
|
end
|
25
25
|
|
@@ -2,7 +2,7 @@ require 'spec_helper_integration'
|
|
2
2
|
|
3
3
|
module Doorkeeper::OAuth
|
4
4
|
describe AuthorizationCodeRequest do
|
5
|
-
let(:server) {
|
5
|
+
let(:server) { double :server, :access_token_expires_in => 2.days, :refresh_token_enabled? => false }
|
6
6
|
let(:grant) { FactoryGirl.create :access_grant }
|
7
7
|
let(:client) { grant.application }
|
8
8
|
|
@@ -10,7 +10,7 @@ class Doorkeeper::OAuth::Client
|
|
10
10
|
end
|
11
11
|
|
12
12
|
describe :from_request do
|
13
|
-
let(:request) {
|
13
|
+
let(:request) { double.as_null_object }
|
14
14
|
|
15
15
|
let(:method) do
|
16
16
|
lambda { |request| return 'uid', 'secret' }
|
@@ -27,7 +27,7 @@ class Doorkeeper::OAuth::Client
|
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'stops at the first credentials found' do
|
30
|
-
not_called_method =
|
30
|
+
not_called_method = double
|
31
31
|
not_called_method.should_not_receive(:call)
|
32
32
|
credentials = Credentials.from_request request, lambda { |r| }, method, not_called_method
|
33
33
|
end
|
@@ -15,7 +15,7 @@ class Doorkeeper::OAuth::Client
|
|
15
15
|
|
16
16
|
describe :from_params do
|
17
17
|
it 'returns credentials from parameters when Authorization header is not available' do
|
18
|
-
request =
|
18
|
+
request = double :parameters => { :client_id => client_id, :client_secret => client_secret }
|
19
19
|
uid, secret = subject.from_params(request)
|
20
20
|
|
21
21
|
uid.should == "some-uid"
|
@@ -23,7 +23,7 @@ class Doorkeeper::OAuth::Client
|
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'is blank when there are no credentials' do
|
26
|
-
request =
|
26
|
+
request = double :parameters => {}
|
27
27
|
uid, secret = subject.from_params(request)
|
28
28
|
|
29
29
|
uid.should be_blank
|
@@ -35,7 +35,7 @@ class Doorkeeper::OAuth::Client
|
|
35
35
|
let(:credentials) { Base64.encode64("#{client_id}:#{client_secret}") }
|
36
36
|
|
37
37
|
it 'decodes the credentials' do
|
38
|
-
request =
|
38
|
+
request = double :authorization => "Basic #{credentials}"
|
39
39
|
uid, secret = subject.from_basic(request)
|
40
40
|
|
41
41
|
uid.should == "some-uid"
|
@@ -43,7 +43,7 @@ class Doorkeeper::OAuth::Client
|
|
43
43
|
end
|
44
44
|
|
45
45
|
it 'is blank if Authorization is not Basic' do
|
46
|
-
request =
|
46
|
+
request = double :authorization => "#{credentials}"
|
47
47
|
uid, secret = subject.from_basic(request)
|
48
48
|
|
49
49
|
uid.should be_blank
|
@@ -4,14 +4,14 @@ require 'doorkeeper/oauth/client_credentials/issuer'
|
|
4
4
|
|
5
5
|
class Doorkeeper::OAuth::ClientCredentialsRequest
|
6
6
|
describe Issuer do
|
7
|
-
let(:creator) {
|
8
|
-
let(:server) {
|
9
|
-
let(:validation) {
|
7
|
+
let(:creator) { double :acces_token_creator }
|
8
|
+
let(:server) { double :server, :access_token_expires_in => 100 }
|
9
|
+
let(:validation) { double :validation, :valid? => true }
|
10
10
|
|
11
11
|
subject { Issuer.new(server, validation) }
|
12
12
|
|
13
13
|
describe :create do
|
14
|
-
let(:client) {
|
14
|
+
let(:client) { double :client, :id => 'some-id' }
|
15
15
|
let(:scopes) { 'some scope' }
|
16
16
|
|
17
17
|
it 'creates and sets the token' do
|
@@ -4,8 +4,8 @@ require 'doorkeeper/oauth/client_credentials/validation'
|
|
4
4
|
|
5
5
|
class Doorkeeper::OAuth::ClientCredentialsRequest
|
6
6
|
describe Validation do
|
7
|
-
let(:server) {
|
8
|
-
let(:request) {
|
7
|
+
let(:server) { double :server, :scopes => nil }
|
8
|
+
let(:request) { double :request, :client => double, :original_scopes => nil }
|
9
9
|
|
10
10
|
subject { Validation.new(server, request) }
|
11
11
|
|
@@ -5,9 +5,9 @@ require 'doorkeeper/oauth/client_credentials_request'
|
|
5
5
|
|
6
6
|
module Doorkeeper::OAuth
|
7
7
|
describe ClientCredentialsRequest do
|
8
|
-
let(:server) {
|
9
|
-
let(:client) {
|
10
|
-
let(:token_creator) {
|
8
|
+
let(:server) { double :default_scopes => nil }
|
9
|
+
let(:client) { double }
|
10
|
+
let(:token_creator) { double :issuer, :create => true, :token => double }
|
11
11
|
|
12
12
|
subject { ClientCredentialsRequest.new(server, client) }
|
13
13
|
|
@@ -27,7 +27,7 @@ module Doorkeeper::OAuth
|
|
27
27
|
|
28
28
|
context 'if issue was not created' do
|
29
29
|
before do
|
30
|
-
subject.issuer =
|
30
|
+
subject.issuer = double :create => false, :error => :invalid
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'has an error response' do
|
@@ -6,10 +6,10 @@ require 'doorkeeper/oauth/client'
|
|
6
6
|
module Doorkeeper::OAuth
|
7
7
|
describe Client do
|
8
8
|
describe :find do
|
9
|
-
let(:method) {
|
9
|
+
let(:method) { double }
|
10
10
|
|
11
11
|
it 'finds the client via uid' do
|
12
|
-
client =
|
12
|
+
client = double
|
13
13
|
method.should_receive(:call).with('uid').and_return(client)
|
14
14
|
Client.find('uid', method).should be_a(Client)
|
15
15
|
end
|
@@ -23,14 +23,14 @@ module Doorkeeper::OAuth
|
|
23
23
|
describe :authenticate do
|
24
24
|
it 'returns the authenticated client via credentials' do
|
25
25
|
credentials = Client::Credentials.new("some-uid", "some-secret")
|
26
|
-
authenticator =
|
27
|
-
authenticator.should_receive(:call).with("some-uid", "some-secret").and_return(
|
26
|
+
authenticator = double
|
27
|
+
authenticator.should_receive(:call).with("some-uid", "some-secret").and_return(double)
|
28
28
|
Client.authenticate(credentials, authenticator).should be_a(Client)
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'retunrs nil if client was not authenticated' do
|
32
32
|
credentials = Client::Credentials.new("some-uid", "some-secret")
|
33
|
-
authenticator =
|
33
|
+
authenticator = double
|
34
34
|
authenticator.should_receive(:call).with("some-uid", "some-secret").and_return(nil)
|
35
35
|
Client.authenticate(credentials, authenticator).should be_nil
|
36
36
|
end
|
@@ -3,8 +3,8 @@ require 'spec_helper_integration'
|
|
3
3
|
module Doorkeeper::OAuth
|
4
4
|
describe CodeRequest do
|
5
5
|
let(:pre_auth) do
|
6
|
-
|
7
|
-
:client =>
|
6
|
+
double(:pre_auth, {
|
7
|
+
:client => double(:application, :id => 9990),
|
8
8
|
:redirect_uri => 'http://tst.com/cb',
|
9
9
|
:scopes => nil,
|
10
10
|
:state => nil,
|
@@ -13,7 +13,7 @@ module Doorkeeper::OAuth
|
|
13
13
|
})
|
14
14
|
end
|
15
15
|
|
16
|
-
let(:owner) {
|
16
|
+
let(:owner) { double :owner, :id => 8900 }
|
17
17
|
|
18
18
|
subject do
|
19
19
|
CodeRequest.new(pre_auth, owner)
|
@@ -9,17 +9,17 @@ module Doorkeeper::OAuth
|
|
9
9
|
|
10
10
|
describe :from_request do
|
11
11
|
it 'has the error from request' do
|
12
|
-
error = ErrorResponse.from_request
|
12
|
+
error = ErrorResponse.from_request double(:error => :some_error)
|
13
13
|
error.name.should == :some_error
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'ignores state if request does not respond to state' do
|
17
|
-
error = ErrorResponse.from_request
|
17
|
+
error = ErrorResponse.from_request double(:error => :some_error)
|
18
18
|
error.state.should be_nil
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'has state if request responds to state' do
|
22
|
-
error = ErrorResponse.from_request
|
22
|
+
error = ErrorResponse.from_request double(:error => :some_error, :state => :hello)
|
23
23
|
error.state.should == :hello
|
24
24
|
end
|
25
25
|
end
|
@@ -34,8 +34,8 @@ module Doorkeeper::OAuth::Helpers
|
|
34
34
|
end
|
35
35
|
|
36
36
|
it "is false when any of attributes is nil" do
|
37
|
-
ScopeChecker.matches?(nil,
|
38
|
-
ScopeChecker.matches?(
|
37
|
+
ScopeChecker.matches?(nil, double).should be_false
|
38
|
+
ScopeChecker.matches?(double, nil).should be_false
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -2,30 +2,46 @@ require 'spec_helper_integration'
|
|
2
2
|
|
3
3
|
module Doorkeeper::OAuth
|
4
4
|
describe PasswordAccessTokenRequest do
|
5
|
-
let(:server) {
|
5
|
+
let(:server) { double :server, :default_scopes => Doorkeeper::OAuth::Scopes.new, :access_token_expires_in => 2.hours, :refresh_token_enabled? => false }
|
6
|
+
let(:credentials) { Client::Credentials.new(client.uid, client.secret) }
|
6
7
|
let(:client) { FactoryGirl.create(:application) }
|
7
|
-
let(:owner) {
|
8
|
+
let(:owner) { double :owner, :id => 99 }
|
8
9
|
|
9
10
|
subject do
|
10
|
-
PasswordAccessTokenRequest.new(server,
|
11
|
+
PasswordAccessTokenRequest.new(server, credentials, owner)
|
11
12
|
end
|
12
13
|
|
13
14
|
it 'issues a new token for the client' do
|
14
|
-
expect
|
15
|
+
expect {
|
15
16
|
subject.authorize
|
16
|
-
|
17
|
+
}.to change { client.access_tokens.count }.by(1)
|
17
18
|
end
|
18
19
|
|
19
|
-
it
|
20
|
+
it 'issues a new token without a client' do
|
21
|
+
expect {
|
22
|
+
subject.credentials = nil
|
23
|
+
subject.authorize
|
24
|
+
}.to change { Doorkeeper::AccessToken.count }.by(1)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'does not issue a new token with an invalid client' do
|
28
|
+
expect {
|
29
|
+
subject.client = nil
|
30
|
+
subject.authorize
|
31
|
+
}.to_not change { Doorkeeper::AccessToken.count }
|
32
|
+
|
33
|
+
subject.error.should == :invalid_client
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'requires the owner' do
|
20
37
|
subject.resource_owner = nil
|
21
38
|
subject.validate
|
22
39
|
subject.error.should == :invalid_resource_owner
|
23
40
|
end
|
24
41
|
|
25
|
-
it '
|
26
|
-
subject.
|
27
|
-
subject.
|
28
|
-
subject.error.should == :invalid_client
|
42
|
+
it 'optionally accepts the client' do
|
43
|
+
subject.credentials = nil
|
44
|
+
subject.should be_valid
|
29
45
|
end
|
30
46
|
|
31
47
|
describe "with scopes" do
|
@@ -2,8 +2,8 @@ require "spec_helper_integration"
|
|
2
2
|
|
3
3
|
module Doorkeeper::OAuth
|
4
4
|
describe PreAuthorization do
|
5
|
-
let(:server) {
|
6
|
-
let(:client) {
|
5
|
+
let(:server) { double :server, :default_scopes => Scopes.new, :scopes => Scopes.from_string('public') }
|
6
|
+
let(:client) { double :client, :redirect_uri => 'http://tst.com/auth' }
|
7
7
|
|
8
8
|
let :attributes do
|
9
9
|
{
|
@@ -2,24 +2,25 @@ require 'spec_helper_integration'
|
|
2
2
|
|
3
3
|
module Doorkeeper::OAuth
|
4
4
|
describe RefreshTokenRequest do
|
5
|
-
let(:server) {
|
5
|
+
let(:server) { double :server, :access_token_expires_in => 2.minutes }
|
6
6
|
let!(:refresh_token) { FactoryGirl.create(:access_token, :use_refresh_token => true) }
|
7
7
|
let(:client) { refresh_token.application }
|
8
|
+
let(:credentials) { Client::Credentials.new(client.uid, client.secret) }
|
8
9
|
|
9
|
-
subject
|
10
|
-
RefreshTokenRequest.new server, refresh_token,
|
11
|
-
|
10
|
+
subject {
|
11
|
+
RefreshTokenRequest.new server, refresh_token, credentials
|
12
|
+
}
|
12
13
|
|
13
14
|
it 'issues a new token for the client' do
|
14
|
-
expect
|
15
|
+
expect {
|
15
16
|
subject.authorize
|
16
|
-
|
17
|
+
}.to change { client.access_tokens.count }.by(1)
|
17
18
|
end
|
18
19
|
|
19
20
|
it 'revokes the previous token' do
|
20
|
-
expect
|
21
|
+
expect {
|
21
22
|
subject.authorize
|
22
|
-
|
23
|
+
}.to change { refresh_token.revoked? }.from(false).to(true)
|
23
24
|
end
|
24
25
|
|
25
26
|
it 'requires the refresh token' do
|
@@ -28,7 +29,7 @@ module Doorkeeper::OAuth
|
|
28
29
|
subject.error.should == :invalid_request
|
29
30
|
end
|
30
31
|
|
31
|
-
it 'requires
|
32
|
+
it 'requires credentials to be valid if provided' do
|
32
33
|
subject.client = nil
|
33
34
|
subject.validate
|
34
35
|
subject.error.should == :invalid_client
|
@@ -37,7 +38,7 @@ module Doorkeeper::OAuth
|
|
37
38
|
it "requires the token's client and current client to match" do
|
38
39
|
subject.client = FactoryGirl.create(:application)
|
39
40
|
subject.validate
|
40
|
-
subject.error.should == :
|
41
|
+
subject.error.should == :invalid_grant
|
41
42
|
end
|
42
43
|
|
43
44
|
it 'rejects revoked tokens' do
|
@@ -52,5 +53,46 @@ module Doorkeeper::OAuth
|
|
52
53
|
subject.validate
|
53
54
|
subject.should be_valid
|
54
55
|
end
|
56
|
+
|
57
|
+
context 'clientless access tokens' do
|
58
|
+
let!(:refresh_token) { FactoryGirl.create(:clientless_access_token, :use_refresh_token => true) }
|
59
|
+
|
60
|
+
subject {
|
61
|
+
RefreshTokenRequest.new server, refresh_token, nil
|
62
|
+
}
|
63
|
+
|
64
|
+
it 'issues a new token without a client' do
|
65
|
+
expect {
|
66
|
+
subject.authorize
|
67
|
+
}.to change { Doorkeeper::AccessToken.count }.by(1)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'with scopes' do
|
72
|
+
let!(:refresh_token) { FactoryGirl.create(:access_token, :use_refresh_token => true, :scopes => 'public write') }
|
73
|
+
let(:parameters) { {} }
|
74
|
+
subject {
|
75
|
+
RefreshTokenRequest.new server, refresh_token, credentials, parameters
|
76
|
+
}
|
77
|
+
|
78
|
+
it 'transfers scopes from the old token to the new token' do
|
79
|
+
subject.authorize
|
80
|
+
Doorkeeper::AccessToken.last.scopes.should == [:public, :write]
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'reduces scopes to the provided scopes' do
|
84
|
+
parameters[:scopes] = 'public'
|
85
|
+
subject.authorize
|
86
|
+
Doorkeeper::AccessToken.last.scopes.should == [:public]
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'validates that scopes are included in the original access token' do
|
90
|
+
parameters[:scopes] = 'public update'
|
91
|
+
|
92
|
+
subject.validate
|
93
|
+
subject.error.should == :invalid_scope
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
55
97
|
end
|
56
98
|
end
|