doorkeeper 4.2.0 → 4.2.5

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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +5 -0
  4. data/.travis.yml +11 -6
  5. data/Appraisals +14 -0
  6. data/Gemfile +4 -8
  7. data/NEWS.md +10 -1
  8. data/README.md +6 -1
  9. data/app/controllers/doorkeeper/applications_controller.rb +1 -5
  10. data/app/views/doorkeeper/applications/_delete_form.html.erb +1 -2
  11. data/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +1 -2
  12. data/config/locales/en.yml +2 -2
  13. data/doorkeeper.gemspec +9 -7
  14. data/gemfiles/rails_4_2.gemfile +11 -0
  15. data/gemfiles/rails_5_0.gemfile +12 -0
  16. data/gemfiles/rails_5_1.gemfile +13 -0
  17. data/lib/doorkeeper.rb +7 -1
  18. data/lib/doorkeeper/config.rb +55 -0
  19. data/lib/doorkeeper/grape/helpers.rb +2 -1
  20. data/lib/doorkeeper/helpers/controller.rb +6 -6
  21. data/lib/doorkeeper/models/access_grant_mixin.rb +12 -0
  22. data/lib/doorkeeper/models/access_token_mixin.rb +117 -1
  23. data/lib/doorkeeper/models/application_mixin.rb +18 -2
  24. data/lib/doorkeeper/models/concerns/accessible.rb +4 -0
  25. data/lib/doorkeeper/models/concerns/expirable.rb +8 -0
  26. data/lib/doorkeeper/models/concerns/revocable.rb +18 -0
  27. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +20 -18
  28. data/lib/doorkeeper/oauth/authorization_code_request.rb +1 -4
  29. data/lib/doorkeeper/oauth/{request_concern.rb → base_request.rb} +3 -1
  30. data/lib/doorkeeper/oauth/base_response.rb +29 -0
  31. data/lib/doorkeeper/oauth/client.rb +0 -1
  32. data/lib/doorkeeper/oauth/client/credentials.rb +17 -6
  33. data/lib/doorkeeper/oauth/client_credentials/creator.rb +1 -1
  34. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +1 -1
  35. data/lib/doorkeeper/oauth/client_credentials/validation.rb +1 -1
  36. data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -4
  37. data/lib/doorkeeper/oauth/code_response.rb +7 -6
  38. data/lib/doorkeeper/oauth/error_response.rb +9 -8
  39. data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -0
  40. data/lib/doorkeeper/oauth/password_access_token_request.rb +1 -3
  41. data/lib/doorkeeper/oauth/refresh_token_request.rb +3 -7
  42. data/lib/doorkeeper/oauth/token.rb +17 -19
  43. data/lib/doorkeeper/oauth/token_request.rb +1 -2
  44. data/lib/doorkeeper/orm/active_record/access_token.rb +17 -0
  45. data/lib/doorkeeper/orm/active_record/application.rb +10 -5
  46. data/lib/doorkeeper/rails/helpers.rb +0 -2
  47. data/lib/doorkeeper/rails/routes.rb +3 -4
  48. data/lib/doorkeeper/rails/routes/mapper.rb +3 -3
  49. data/lib/doorkeeper/rails/routes/mapping.rb +1 -1
  50. data/lib/doorkeeper/request/authorization_code.rb +7 -1
  51. data/lib/doorkeeper/request/refresh_token.rb +1 -1
  52. data/lib/doorkeeper/server.rb +0 -8
  53. data/lib/doorkeeper/version.rb +1 -1
  54. data/spec/controllers/authorizations_controller_spec.rb +17 -3
  55. data/spec/lib/doorkeeper_spec.rb +135 -13
  56. data/spec/lib/oauth/authorization/uri_builder_spec.rb +1 -2
  57. data/spec/lib/oauth/base_request_spec.rb +160 -0
  58. data/spec/lib/oauth/base_response_spec.rb +45 -0
  59. data/spec/lib/oauth/client/credentials_spec.rb +41 -0
  60. data/spec/lib/oauth/error_response_spec.rb +9 -9
  61. data/spec/lib/oauth/invalid_token_response_spec.rb +36 -8
  62. data/spec/lib/server_spec.rb +0 -3
  63. data/spec/requests/endpoints/authorization_spec.rb +5 -6
  64. data/spec/requests/flows/authorization_code_spec.rb +4 -12
  65. data/spec/spec_helper.rb +2 -0
  66. data/spec/spec_helper_integration.rb +5 -0
  67. data/spec/support/helpers/request_spec_helper.rb +12 -4
  68. data/spec/support/http_method_shim.rb +20 -6
  69. metadata +43 -21
  70. data/lib/doorkeeper/oauth/client/methods.rb +0 -18
  71. data/spec/lib/oauth/client/methods_spec.rb +0 -54
@@ -6,8 +6,7 @@ require 'doorkeeper/oauth/authorization/uri_builder'
6
6
 
7
7
  module Doorkeeper::OAuth::Authorization
8
8
  describe URIBuilder do
9
-
10
- subject { Object.new.class.send :include, URIBuilder }
9
+ subject { URIBuilder }
11
10
 
12
11
  describe :uri_with_query do
13
12
  it 'returns the uri with query' do
@@ -0,0 +1,160 @@
1
+ require 'spec_helper_integration'
2
+
3
+ module Doorkeeper::OAuth
4
+ describe BaseRequest do
5
+ let(:access_token) do
6
+ double :access_token,
7
+ token: "some-token",
8
+ expires_in: "3600",
9
+ expires_in_seconds: "300",
10
+ scopes_string: "two scopes",
11
+ refresh_token: "some-refresh-token",
12
+ token_type: "bearer",
13
+ created_at: 0
14
+ end
15
+
16
+ let(:client) do
17
+ double :client,
18
+ id: '1'
19
+ end
20
+
21
+ let(:scopes_array) do
22
+ %w(public write)
23
+ end
24
+
25
+ let(:server) do
26
+ double :server,
27
+ access_token_expires_in: 100,
28
+ custom_access_token_expires_in: ->(_) { nil },
29
+ refresh_token_enabled?: false
30
+ end
31
+
32
+ subject do
33
+ BaseRequest.new
34
+ end
35
+
36
+ describe "#authorize" do
37
+ before do
38
+ allow(subject).to receive(:access_token).and_return(access_token)
39
+ end
40
+
41
+ it "validates itself" do
42
+ expect(subject).to receive(:validate).once
43
+ subject.authorize
44
+ end
45
+
46
+ context "valid" do
47
+ before do
48
+ allow(subject).to receive(:valid?).and_return(true)
49
+ end
50
+
51
+ it "calls callback methods" do
52
+ expect(subject).to receive(:before_successful_response).once
53
+ expect(subject).to receive(:after_successful_response).once
54
+ subject.authorize
55
+ end
56
+
57
+ it "returns a TokenResponse object" do
58
+ result = subject.authorize
59
+
60
+ expect(result).to be_an_instance_of(TokenResponse)
61
+ expect(result.body).to eq(
62
+ TokenResponse.new(access_token).body
63
+ )
64
+ end
65
+ end
66
+
67
+ context "invalid" do
68
+ before do
69
+ allow(subject).to receive(:valid?).and_return(false)
70
+ allow(subject).to receive(:error).and_return("server_error")
71
+ allow(subject).to receive(:state).and_return("hello")
72
+ end
73
+
74
+ it "returns an ErrorResponse object" do
75
+ error_description = I18n.translate(
76
+ "server_error",
77
+ scope: [:doorkeeper, :errors, :messages]
78
+ )
79
+
80
+ result = subject.authorize
81
+
82
+ expect(result).to be_an_instance_of(ErrorResponse)
83
+
84
+ expect(result.body).to eq(
85
+ error: "server_error",
86
+ error_description: error_description,
87
+ state: "hello"
88
+ )
89
+ end
90
+ end
91
+ end
92
+
93
+ describe "#default_scopes" do
94
+ it "delegates to the server" do
95
+ expect(subject).to receive(:server).and_return(server).once
96
+ expect(server).to receive(:default_scopes).once
97
+
98
+ subject.default_scopes
99
+ end
100
+ end
101
+
102
+ describe "#find_or_create_access_token" do
103
+ it "returns an instance of AccessToken" do
104
+ result = subject.find_or_create_access_token(
105
+ client,
106
+ "1",
107
+ "public",
108
+ server
109
+ )
110
+
111
+ expect(result).to be_an_instance_of(Doorkeeper::AccessToken)
112
+ end
113
+ end
114
+
115
+ describe "#scopes" do
116
+ context "@original_scopes is present" do
117
+ before do
118
+ subject.instance_variable_set(:@original_scopes, "public write")
119
+ end
120
+
121
+ it "returns array of @original_scopes" do
122
+ result = subject.scopes
123
+
124
+ expect(result).to eq(scopes_array)
125
+ end
126
+ end
127
+
128
+ context "@original_scopes is not present" do
129
+ before do
130
+ subject.instance_variable_set(:@original_scopes, "")
131
+ end
132
+
133
+ it "calls #default_scopes" do
134
+ allow(subject).to receive(:server).and_return(server).once
135
+ allow(server).to receive(:default_scopes).and_return(scopes_array).once
136
+
137
+ result = subject.scopes
138
+
139
+ expect(result).to eq(scopes_array)
140
+ end
141
+ end
142
+ end
143
+
144
+ describe "#valid?" do
145
+ context "error is nil" do
146
+ it "returns true" do
147
+ allow(subject).to receive(:error).and_return(nil).once
148
+ expect(subject.valid?).to eq(true)
149
+ end
150
+ end
151
+
152
+ context "error is not nil" do
153
+ it "returns false" do
154
+ allow(subject).to receive(:error).and_return(Object.new).once
155
+ expect(subject.valid?).to eq(false)
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper_integration'
2
+
3
+ module Doorkeeper::OAuth
4
+ describe BaseResponse do
5
+ subject do
6
+ BaseResponse.new
7
+ end
8
+
9
+ describe "#body" do
10
+ it "returns an empty Hash" do
11
+ expect(subject.body).to eq({})
12
+ end
13
+ end
14
+
15
+ describe "#description" do
16
+ it "returns an empty String" do
17
+ expect(subject.description).to eq("")
18
+ end
19
+ end
20
+
21
+ describe "#headers" do
22
+ it "returns an empty Hash" do
23
+ expect(subject.headers).to eq({})
24
+ end
25
+ end
26
+
27
+ describe "#redirectable?" do
28
+ it "returns false" do
29
+ expect(subject.redirectable?).to eq(false)
30
+ end
31
+ end
32
+
33
+ describe "#redirect_uri" do
34
+ it "returns an empty String" do
35
+ expect(subject.redirect_uri).to eq("")
36
+ end
37
+ end
38
+
39
+ describe "#status" do
40
+ it "returns :ok" do
41
+ expect(subject.status).to eq(:ok)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -4,6 +4,9 @@ require 'doorkeeper/oauth/client'
4
4
 
5
5
  class Doorkeeper::OAuth::Client
6
6
  describe Credentials do
7
+ let(:client_id) { 'some-uid' }
8
+ let(:client_secret) { 'some-secret' }
9
+
7
10
  it 'is blank when any of the credentials is blank' do
8
11
  expect(Credentials.new(nil, 'something')).to be_blank
9
12
  expect(Credentials.new('something', nil)).to be_blank
@@ -43,5 +46,43 @@ class Doorkeeper::OAuth::Client
43
46
  expect(credentials.secret).to eq('secret')
44
47
  end
45
48
  end
49
+
50
+ describe :from_params do
51
+ it 'returns credentials from parameters when Authorization header is not available' do
52
+ request = double parameters: { client_id: client_id, client_secret: client_secret }
53
+ uid, secret = Credentials.from_params(request)
54
+
55
+ expect(uid).to eq('some-uid')
56
+ expect(secret).to eq('some-secret')
57
+ end
58
+
59
+ it 'is blank when there are no credentials' do
60
+ request = double parameters: {}
61
+ uid, secret = Credentials.from_params(request)
62
+
63
+ expect(uid).to be_blank
64
+ expect(secret).to be_blank
65
+ end
66
+ end
67
+
68
+ describe :from_basic do
69
+ let(:credentials) { Base64.encode64("#{client_id}:#{client_secret}") }
70
+
71
+ it 'decodes the credentials' do
72
+ request = double authorization: "Basic #{credentials}"
73
+ uid, secret = Credentials.from_basic(request)
74
+
75
+ expect(uid).to eq('some-uid')
76
+ expect(secret).to eq('some-secret')
77
+ end
78
+
79
+ it 'is blank if Authorization is not Basic' do
80
+ request = double authorization: "#{credentials}"
81
+ uid, secret = Credentials.from_basic(request)
82
+
83
+ expect(uid).to be_blank
84
+ expect(secret).to be_blank
85
+ end
86
+ end
46
87
  end
47
88
  end
@@ -43,19 +43,19 @@ module Doorkeeper::OAuth
43
43
  end
44
44
  end
45
45
 
46
- describe '.authenticate_info' do
46
+ describe '.headers' do
47
47
  let(:error_response) { ErrorResponse.new(name: :some_error, state: :some_state) }
48
- subject { error_response.authenticate_info }
48
+ subject { error_response.headers }
49
49
 
50
- it { expect(subject).to include("realm=\"#{error_response.realm}\"") }
51
- it { expect(subject).to include("error=\"#{error_response.name}\"") }
52
- it { expect(subject).to include("error_description=\"#{error_response.description}\"") }
53
- end
50
+ it { expect(subject).to include 'WWW-Authenticate' }
54
51
 
55
- describe '.headers' do
56
- subject { ErrorResponse.new(name: :some_error, state: :some_state).headers }
52
+ describe "WWW-Authenticate header" do
53
+ subject { error_response.headers["WWW-Authenticate"] }
57
54
 
58
- it { expect(subject).to include 'WWW-Authenticate' }
55
+ it { expect(subject).to include("realm=\"#{error_response.realm}\"") }
56
+ it { expect(subject).to include("error=\"#{error_response.name}\"") }
57
+ it { expect(subject).to include("error_description=\"#{error_response.description}\"") }
58
+ end
59
59
  end
60
60
  end
61
61
  end
@@ -5,23 +5,51 @@ require 'doorkeeper/oauth/invalid_token_response'
5
5
 
6
6
  module Doorkeeper::OAuth
7
7
  describe InvalidTokenResponse do
8
- describe '#name' do
8
+ describe "#name" do
9
9
  it { expect(subject.name).to eq(:invalid_token) }
10
10
  end
11
11
 
12
- describe '#status' do
12
+ describe "#status" do
13
13
  it { expect(subject.status).to eq(:unauthorized) }
14
14
  end
15
15
 
16
16
  describe :from_access_token do
17
- it 'revoked' do
18
- response = InvalidTokenResponse.from_access_token double(revoked?: true, expired?: true)
19
- expect(response.description).to include('revoked')
17
+ let(:response) { InvalidTokenResponse.from_access_token(access_token) }
18
+
19
+ context "revoked" do
20
+ let(:access_token) { double(revoked?: true, expired?: true) }
21
+
22
+ it "sets a description" do
23
+ expect(response.description).to include("revoked")
24
+ end
25
+
26
+ it "sets the reason" do
27
+ expect(response.reason).to eq(:revoked)
28
+ end
20
29
  end
21
30
 
22
- it 'expired' do
23
- response = InvalidTokenResponse.from_access_token double(revoked?: false, expired?: true)
24
- expect(response.description).to include('expired')
31
+ context "expired" do
32
+ let(:access_token) { double(revoked?: false, expired?: true) }
33
+
34
+ it "sets a description" do
35
+ expect(response.description).to include("expired")
36
+ end
37
+
38
+ it "sets the reason" do
39
+ expect(response.reason).to eq(:expired)
40
+ end
41
+ end
42
+
43
+ context "unkown" do
44
+ let(:access_token) { double(revoked?: false, expired?: false) }
45
+
46
+ it "sets a description" do
47
+ expect(response.description).to include("invalid")
48
+ end
49
+
50
+ it "sets the reason" do
51
+ expect(response.reason).to eq(:unknown)
52
+ end
25
53
  end
26
54
  end
27
55
  end
@@ -1,7 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'active_support/all'
3
- require 'doorkeeper/errors'
4
- require 'doorkeeper/server'
5
2
 
6
3
  describe Doorkeeper::Server do
7
4
  let(:fake_class) { double :fake_class }
@@ -59,13 +59,12 @@ feature 'Authorization endpoint' do
59
59
  end
60
60
 
61
61
  scenario 'raises exception on forged requests' do
62
- skip 'TODO: need to add request helpers to this feature spec'
63
- allow_any_instance_of(ActionController::Base).to receive(:handle_unverified_request)
64
62
  allowing_forgery_protection do
65
- post "/oauth/authorize",
66
- client_id: @client.uid,
67
- redirect_uri: @client.redirect_uri,
68
- response_type: 'code'
63
+ expect {
64
+ page.driver.post authorization_endpoint_url(client_id: @client.uid,
65
+ redirect_uri: @client.redirect_uri,
66
+ response_type: 'code')
67
+ }.to raise_error(ActionController::InvalidAuthenticityToken)
69
68
  end
70
69
  end
71
70
  end
@@ -41,13 +41,11 @@ feature 'Authorization Code Flow' do
41
41
  end
42
42
 
43
43
  scenario 'resource owner requests an access token with authorization code' do
44
- skip 'TODO: need to add request helpers to this feature spec'
45
-
46
44
  visit authorization_endpoint_url(client: @client)
47
45
  click_on 'Authorize'
48
46
 
49
47
  authorization_code = Doorkeeper::AccessGrant.first.token
50
- post token_endpoint_url(code: authorization_code, client: @client)
48
+ create_access_token authorization_code, @client
51
49
 
52
50
  access_token_should_exist_for(@client, @resource_owner)
53
51
 
@@ -84,27 +82,23 @@ feature 'Authorization Code Flow' do
84
82
  end
85
83
 
86
84
  scenario 'new access token matches required scopes' do
87
- skip 'TODO: need to add request helpers to this feature spec'
88
-
89
85
  visit authorization_endpoint_url(client: @client, scope: 'public write')
90
86
  click_on 'Authorize'
91
87
 
92
88
  authorization_code = Doorkeeper::AccessGrant.first.token
93
- post token_endpoint_url(code: authorization_code, client: @client)
89
+ create_access_token authorization_code, @client
94
90
 
95
91
  access_token_should_exist_for(@client, @resource_owner)
96
92
  access_token_should_have_scopes :public, :write
97
93
  end
98
94
 
99
95
  scenario 'returns new token if scopes have changed' do
100
- skip 'TODO: need to add request helpers to this feature spec'
101
-
102
96
  client_is_authorized(@client, @resource_owner, scopes: 'public write')
103
97
  visit authorization_endpoint_url(client: @client, scope: 'public')
104
98
  click_on 'Authorize'
105
99
 
106
100
  authorization_code = Doorkeeper::AccessGrant.first.token
107
- post token_endpoint_url(code: authorization_code, client: @client)
101
+ create_access_token authorization_code, @client
108
102
 
109
103
  expect(Doorkeeper::AccessToken.count).to be(2)
110
104
 
@@ -112,14 +106,12 @@ feature 'Authorization Code Flow' do
112
106
  end
113
107
 
114
108
  scenario 'resource owner authorizes the client with extra scopes' do
115
- skip 'TODO: need to add request helpers to this feature spec'
116
-
117
109
  client_is_authorized(@client, @resource_owner, scopes: 'public')
118
110
  visit authorization_endpoint_url(client: @client, scope: 'public write')
119
111
  click_on 'Authorize'
120
112
 
121
113
  authorization_code = Doorkeeper::AccessGrant.first.token
122
- post token_endpoint_url(code: authorization_code, client: @client)
114
+ create_access_token authorization_code, @client
123
115
 
124
116
  expect(Doorkeeper::AccessToken.count).to be(2)
125
117