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.

Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/Gemfile +0 -2
  4. data/README.md +1 -1
  5. data/app/controllers/doorkeeper/tokens_controller.rb +2 -0
  6. data/app/views/doorkeeper/applications/_delete_form.html.erb +16 -0
  7. data/app/views/doorkeeper/applications/index.html.erb +6 -2
  8. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  9. data/app/views/doorkeeper/authorized_applications/index.html.erb +1 -1
  10. data/app/views/layouts/doorkeeper/application.html.erb +0 -1
  11. data/doorkeeper.gemspec +0 -1
  12. data/lib/doorkeeper/doorkeeper_for.rb +2 -2
  13. data/lib/doorkeeper/models/access_token.rb +5 -2
  14. data/lib/doorkeeper/models/application.rb +2 -2
  15. data/lib/doorkeeper/oauth/password_access_token_request.rb +13 -8
  16. data/lib/doorkeeper/oauth/refresh_token_request.rb +38 -12
  17. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  18. data/lib/doorkeeper/request/password.rb +5 -5
  19. data/lib/doorkeeper/request/refresh_token.rb +5 -5
  20. data/lib/doorkeeper/version.rb +1 -1
  21. data/lib/generators/doorkeeper/templates/migration.rb +1 -1
  22. data/spec/controllers/applications_controller_spec.rb +9 -0
  23. data/spec/controllers/protected_resources_controller_spec.rb +2 -2
  24. data/spec/controllers/tokens_controller_spec.rb +1 -1
  25. data/spec/dummy/app/views/layouts/application.html.erb +0 -2
  26. data/spec/dummy/config/environments/test.rb +11 -2
  27. data/spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb +1 -1
  28. data/spec/dummy/db/schema.rb +1 -1
  29. data/spec/factories/access_token.rb +4 -0
  30. data/spec/lib/models/revocable_spec.rb +2 -2
  31. data/spec/lib/oauth/authorization_code_request_spec.rb +1 -1
  32. data/spec/lib/oauth/client/credentials_spec.rb +2 -2
  33. data/spec/lib/oauth/client/methods_spec.rb +4 -4
  34. data/spec/lib/oauth/client_credentials/issuer_spec.rb +4 -4
  35. data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -2
  36. data/spec/lib/oauth/client_credentials_request_spec.rb +4 -4
  37. data/spec/lib/oauth/client_spec.rb +5 -5
  38. data/spec/lib/oauth/code_request_spec.rb +3 -3
  39. data/spec/lib/oauth/error_response_spec.rb +3 -3
  40. data/spec/lib/oauth/helpers/scope_checker_spec.rb +2 -2
  41. data/spec/lib/oauth/password_access_token_request_spec.rb +26 -10
  42. data/spec/lib/oauth/pre_authorization_spec.rb +2 -2
  43. data/spec/lib/oauth/refresh_token_request_spec.rb +52 -10
  44. data/spec/lib/oauth/token_request_spec.rb +3 -3
  45. data/spec/lib/oauth/token_response_spec.rb +8 -5
  46. data/spec/lib/oauth/token_spec.rb +8 -8
  47. data/spec/lib/server_spec.rb +1 -1
  48. data/spec/models/doorkeeper/access_token_spec.rb +6 -9
  49. data/spec/models/doorkeeper/application_spec.rb +16 -1
  50. data/spec/requests/applications/applications_request_spec.rb +3 -3
  51. data/spec/requests/flows/password_spec.rb +20 -0
  52. data/spec/requests/protected_resources/private_api_spec.rb +8 -0
  53. metadata +5 -21
  54. data/app/assets/javascripts/doorkeeper/application.js +0 -2
  55. data/spec/dummy/app/assets/javascripts/application.js +0 -9
  56. 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 => stub(:to_json => [], :status => :unauthorized))
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
@@ -2,8 +2,6 @@
2
2
  <html>
3
3
  <head>
4
4
  <title>Dummy</title>
5
- <%= stylesheet_link_tag "application" %>
6
- <%= javascript_include_tag "application" %>
7
5
  <%= csrf_meta_tags %>
8
6
  </head>
9
7
  <body>
@@ -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
- # Log error messages when you accidentally call methods on nil
15
- config.whiny_nils = true
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, :null => false
28
+ t.integer :application_id
29
29
  t.string :token, :null => false
30
30
  t.string :refresh_token
31
31
  t.integer :expires_in
@@ -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", :null => false
31
+ t.integer "application_id"
32
32
  t.string "token", :null => false
33
33
  t.string "refresh_token"
34
34
  t.integer "expires_in"
@@ -3,5 +3,9 @@ FactoryGirl.define do
3
3
  sequence(:resource_owner_id) { |n| n }
4
4
  application
5
5
  expires_in 2.hours
6
+
7
+ factory :clientless_access_token do
8
+ application nil
9
+ end
6
10
  end
7
11
  end
@@ -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 => stub
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 => stub
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) { mock :server, :access_token_expires_in => 2.days, :refresh_token_enabled? => false }
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) { stub.as_null_object }
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 = mock
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 = stub :parameters => { :client_id => client_id, :client_secret => client_secret }
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 = stub :parameters => {}
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 = stub :authorization => "Basic #{credentials}"
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 = stub :authorization => "#{credentials}"
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) { mock :acces_token_creator }
8
- let(:server) { mock :server, :access_token_expires_in => 100 }
9
- let(:validation) { mock :validation, :valid? => true }
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) { mock :client, :id => 'some-id' }
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) { mock :server, :scopes => nil }
8
- let(:request) { mock :request, :client => stub, :original_scopes => nil }
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) { stub :default_scopes => nil }
9
- let(:client) { stub }
10
- let(:token_creator) { mock :issuer, :create => true, :token => stub }
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 = stub :create => false, :error => :invalid
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) { mock }
9
+ let(:method) { double }
10
10
 
11
11
  it 'finds the client via uid' do
12
- client = stub
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 = mock
27
- authenticator.should_receive(:call).with("some-uid", "some-secret").and_return(stub)
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 = mock
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
- mock(:pre_auth, {
7
- :client => mock(:application, :id => 9990),
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) { mock :owner, :id => 8900 }
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 stub(:error => :some_error)
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 stub(:error => :some_error)
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 stub(:error => :some_error, :state => :hello)
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, stub).should be_false
38
- ScopeChecker.matches?(stub, nil).should be_false
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) { mock :server, :default_scopes => Doorkeeper::OAuth::Scopes.new, :access_token_expires_in => 2.hours, :refresh_token_enabled? => false }
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) { mock :owner, :id => 99 }
8
+ let(:owner) { double :owner, :id => 99 }
8
9
 
9
10
  subject do
10
- PasswordAccessTokenRequest.new(server, client, owner)
11
+ PasswordAccessTokenRequest.new(server, credentials, owner)
11
12
  end
12
13
 
13
14
  it 'issues a new token for the client' do
14
- expect do
15
+ expect {
15
16
  subject.authorize
16
- end.to change { client.access_tokens.count }.by(1)
17
+ }.to change { client.access_tokens.count }.by(1)
17
18
  end
18
19
 
19
- it "requires the owner" do
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 'requires the client' do
26
- subject.client = nil
27
- subject.validate
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) { mock :server, :default_scopes => Scopes.new, :scopes => Scopes.from_string('public') }
6
- let(:client) { mock :client, :redirect_uri => 'http://tst.com/auth' }
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) { mock :server, :access_token_expires_in => 2.minutes }
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 do
10
- RefreshTokenRequest.new server, refresh_token, client
11
- end
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 do
15
+ expect {
15
16
  subject.authorize
16
- end.to change { client.access_tokens.count }.by(1)
17
+ }.to change { client.access_tokens.count }.by(1)
17
18
  end
18
19
 
19
20
  it 'revokes the previous token' do
20
- expect do
21
+ expect {
21
22
  subject.authorize
22
- end.to change { refresh_token.revoked? }.from(false).to(true)
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 client' do
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 == :invalid_client
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