doorkeeper 3.0.0.rc1 → 3.0.0.rc2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8450a1e6cc7b4a4b841532e3886687149b4d9200
4
- data.tar.gz: 9d80327b747a96da75785cc32d208cbc829b6131
3
+ metadata.gz: 59aa2a41e1765b2d2b43c2f7b0f7f1811291abbb
4
+ data.tar.gz: a169c60170ec494653e248fd49aa78f6224f59e0
5
5
  SHA512:
6
- metadata.gz: 9a23772dc01acb6827089ea7349c4492d08437d57dd5deb3318f1254505f97658a9b4db5276d5dbf033b8f8e99cc281b59c354e4166fffd85b52bbee9a7491c0
7
- data.tar.gz: 749700263b4e424910c5713f923fd82b69737a87d69d472e852f1b6a1bacf330ecef4bd53f94cdae4a153aef371e6a04e2de02ee4a42e436eb61cd4052913365
6
+ metadata.gz: a99804357cd078363aa870de65887a6eb0a532207b220cfea96455a7f9a36737a8ea8ecaaf909f2dbea09fec05aca87b38a4364eb55e79da99dcc76f0b58d113
7
+ data.tar.gz: 441e975743a1aaa331bce2bfb98a333c419a13616075cb863bdca9586608e6daa071ecc08b859be513e63607cecf3083a425cd0eec22e238946c9515f03a339a
data/NEWS.md CHANGED
@@ -4,6 +4,23 @@ User-visible changes worth mentioning.
4
4
 
5
5
  ---
6
6
 
7
+ ## 3.0.0 (rc2)
8
+
9
+ ### Backward incompatible changes
10
+
11
+ - [#678] Change application-specific scopes to take precedence over server-wide
12
+ scopes. This removes the previous behavior where the intersection between
13
+ application and server scopes was used.
14
+
15
+ ### Other changes
16
+
17
+ - [#671] Fixes `NoMethodError - undefined method 'getlocal'` when calling
18
+ the /oauth/token path. Switch from using a DateTime object to update
19
+ AR to using a Time object. (Issue #668)
20
+ - [#677] Support editing application-specific scopes via the standard forms
21
+ - [#682] Pass error hash to Grape `error!`
22
+ - [#683] Generate application secret/UID if fields are blank strings
23
+
7
24
  ## 3.0.0 (rc1)
8
25
 
9
26
  ### Backward incompatible changes
@@ -12,6 +29,9 @@ User-visible changes worth mentioning.
12
29
  https://github.com/doorkeeper-gem/doorkeeper-mongodb. If you use ActiveRecord
13
30
  you don’t need to do any change, otherwise you will need to install the new
14
31
  plugin.
32
+ - [#665] `doorkeeper_unauthorized_render_options(error:)` and
33
+ `doorkeeper_forbidden_render_options(error:)` now accept `error` keyword
34
+ argument.
15
35
 
16
36
  ### Removed deprecations
17
37
 
data/README.md CHANGED
@@ -399,6 +399,7 @@ contributors](https://github.com/doorkeeper-gem/doorkeeper/contributors)!
399
399
 
400
400
  * [The OAuth 2.0 Authorization Framework](http://tools.ietf.org/html/rfc6749)
401
401
  * [OAuth 2.0 Threat Model and Security Considerations](http://tools.ietf.org/html/rfc6819)
402
+ * [OAuth 2.0 Token Revocation](http://tools.ietf.org/html/rfc7009)
402
403
 
403
404
  ### License
404
405
 
@@ -45,9 +45,9 @@ module Doorkeeper
45
45
 
46
46
  def application_params
47
47
  if params.respond_to?(:permit)
48
- params.require(:doorkeeper_application).permit(:name, :redirect_uri)
48
+ params.require(:doorkeeper_application).permit(:name, :redirect_uri, :scopes)
49
49
  else
50
- params[:doorkeeper_application].slice(:name, :redirect_uri) rescue nil
50
+ params[:doorkeeper_application].slice(:name, :redirect_uri, :scopes) rescue nil
51
51
  end
52
52
  end
53
53
  end
@@ -5,7 +5,7 @@ module Doorkeeper::DashboardHelper
5
5
  content_tag(:span, class: 'help-block') do
6
6
  msg.capitalize
7
7
  end
8
- end.reduce(&:join).html_safe
8
+ end.join.html_safe
9
9
  end
10
10
  end
11
11
 
@@ -29,6 +29,6 @@ class RedirectUriValidator < ActiveModel::EachValidator
29
29
 
30
30
  def invalid_ssl_uri?(uri)
31
31
  forces_ssl = Doorkeeper.configuration.force_ssl_in_redirect_uri
32
- forces_ssl && uri.try(:scheme) != 'https'
32
+ forces_ssl && uri.try(:scheme) == 'http'
33
33
  end
34
34
  end
@@ -17,8 +17,8 @@
17
17
  <%= f.text_area :redirect_uri, class: 'form-control' %>
18
18
  <%= doorkeeper_errors_for application, :redirect_uri %>
19
19
  <span class="help-block">
20
- <%= t('doorkeeper.applications.help.redirect_uri') %>
21
- </span>
20
+ <%= t('doorkeeper.applications.help.redirect_uri') %>
21
+ </span>
22
22
  <% if Doorkeeper.configuration.native_redirect_uri %>
23
23
  <span class="help-block">
24
24
  <%= raw t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: "<code>#{ Doorkeeper.configuration.native_redirect_uri }</code>") %>
@@ -27,6 +27,17 @@
27
27
  </div>
28
28
  <% end %>
29
29
 
30
+ <%= content_tag :div, class: "form-group#{' has-error' if application.errors[:scopes].present?}" do %>
31
+ <%= f.label :scopes, class: 'col-sm-2 control-label' %>
32
+ <div class="col-sm-10">
33
+ <%= f.text_field :scopes, class: 'form-control' %>
34
+ <%= doorkeeper_errors_for application, :scopes %>
35
+ <span class="help-block">
36
+ <%= t('doorkeeper.applications.help.scopes') %>
37
+ </span>
38
+ </div>
39
+ <% end %>
40
+
30
41
  <div class="form-group">
31
42
  <div class="col-sm-offset-2 col-sm-10">
32
43
  <%= f.submit t('doorkeeper.applications.buttons.submit'), class: "btn btn-primary" %>
@@ -5,13 +5,14 @@
5
5
  <div class="row">
6
6
  <div class="col-md-8">
7
7
  <h4><%= t('.application_id') %>:</h4>
8
-
9
8
  <p><code id="application_id"><%= @application.uid %></code></p>
10
9
 
11
10
  <h4><%= t('.secret') %>:</h4>
12
-
13
11
  <p><code id="secret"><%= @application.secret %></code></p>
14
12
 
13
+ <h4><%= t('.scopes') %>:</h4>
14
+ <p><code id="scopes"><%= @application.scopes %></code></p>
15
+
15
16
  <h4><%= t('.callback_urls') %>:</h4>
16
17
 
17
18
  <table>
@@ -29,6 +29,7 @@ en:
29
29
  help:
30
30
  redirect_uri: 'Use one line per URI'
31
31
  native_redirect_uri: 'Use %{native_redirect_uri} for local tests'
32
+ scopes: 'Separate scopes with spaces. Leave blank to use the default scopes.'
32
33
  edit:
33
34
  title: 'Edit application'
34
35
  index:
@@ -42,6 +43,7 @@ en:
42
43
  title: 'Application: %{name}'
43
44
  application_id: 'Application Id'
44
45
  secret: 'Secret'
46
+ scopes: 'Scopes'
45
47
  callback_urls: 'Callback urls'
46
48
  actions: 'Actions'
47
49
 
@@ -26,7 +26,7 @@ module Doorkeeper
26
26
  403
27
27
  end
28
28
 
29
- error!({ error: error.description }, status_code)
29
+ error!({ error: error.description }, status_code, error.headers)
30
30
  end
31
31
 
32
32
  private
@@ -39,11 +39,15 @@ module Doorkeeper
39
39
  end
40
40
 
41
41
  def generate_uid
42
- self.uid ||= UniqueToken.generate
42
+ if uid.blank?
43
+ self.uid = UniqueToken.generate
44
+ end
43
45
  end
44
46
 
45
47
  def generate_secret
46
- self.secret ||= UniqueToken.generate
48
+ if secret.blank?
49
+ self.secret = UniqueToken.generate
50
+ end
47
51
  end
48
52
  end
49
53
  end
@@ -1,12 +1,12 @@
1
1
  module Doorkeeper
2
2
  module Models
3
3
  module Revocable
4
- def revoke(clock = DateTime)
4
+ def revoke(clock = Time)
5
5
  update_attribute :revoked_at, clock.now
6
6
  end
7
7
 
8
8
  def revoked?
9
- !!(revoked_at && revoked_at <= DateTime.now)
9
+ !!(revoked_at && revoked_at <= Time.now)
10
10
  end
11
11
  end
12
12
  end
@@ -25,7 +25,7 @@ module Doorkeeper
25
25
 
26
26
  def valid_scopes(server_scopes, application_scopes)
27
27
  if application_scopes.present?
28
- server_scopes & application_scopes
28
+ application_scopes
29
29
  else
30
30
  server_scopes
31
31
  end
@@ -11,12 +11,10 @@ module Doorkeeper
11
11
  end
12
12
  end
13
13
 
14
- def doorkeeper_unauthorized_render_options
15
- nil
14
+ def doorkeeper_unauthorized_render_options(error: nil)
16
15
  end
17
16
 
18
- def doorkeeper_forbidden_render_options
19
- nil
17
+ def doorkeeper_forbidden_render_options(error: nil)
20
18
  end
21
19
 
22
20
  def valid_doorkeeper_token?
@@ -32,7 +30,7 @@ module Doorkeeper
32
30
  end
33
31
 
34
32
  def doorkeeper_render_error_with(error)
35
- options = doorkeeper_render_options || {}
33
+ options = doorkeeper_render_options(error) || {}
36
34
  if options.blank?
37
35
  head error.status
38
36
  else
@@ -50,11 +48,11 @@ module Doorkeeper
50
48
  end
51
49
  end
52
50
 
53
- def doorkeeper_render_options
51
+ def doorkeeper_render_options(error)
54
52
  if doorkeeper_invalid_token_response?
55
- doorkeeper_unauthorized_render_options
53
+ doorkeeper_unauthorized_render_options(error: error)
56
54
  else
57
- doorkeeper_forbidden_render_options
55
+ doorkeeper_forbidden_render_options(error: error)
58
56
  end
59
57
  end
60
58
 
@@ -1,3 +1,3 @@
1
1
  module Doorkeeper
2
- VERSION = '3.0.0.rc1'
2
+ VERSION = '3.0.0.rc2'
3
3
  end
@@ -27,7 +27,15 @@ class CreateDoorkeeperTables < ActiveRecord::Migration
27
27
  create_table :oauth_access_tokens do |t|
28
28
  t.integer :resource_owner_id
29
29
  t.integer :application_id
30
+
31
+ # If you use a custom token generator you may need to change this column
32
+ # from string to text, so that it accepts tokens larger than 255
33
+ # characters. More info on custom token generators in:
34
+ # https://github.com/doorkeeper-gem/doorkeeper/tree/v3.0.0.rc1#custom-access-token-generator
35
+ #
36
+ # t.text :token, null: false
30
37
  t.string :token, null: false
38
+
31
39
  t.string :refresh_token
32
40
  t.integer :expires_in
33
41
  t.datetime :revoked_at
@@ -126,7 +126,17 @@ describe 'doorkeeper authorize filter' do
126
126
 
127
127
  context 'with a JSON custom render', token: :invalid do
128
128
  before do
129
- expect(controller).to receive(:doorkeeper_unauthorized_render_options).and_return(json: ActiveSupport::JSON.encode(error: 'Unauthorized'))
129
+ module ControllerActions
130
+ def doorkeeper_unauthorized_render_options(error: nil)
131
+ { json: ActiveSupport::JSON.encode(error_message: error.description) }
132
+ end
133
+ end
134
+ end
135
+ after do
136
+ module ControllerActions
137
+ def doorkeeper_unauthorized_render_options(error: nil)
138
+ end
139
+ end
130
140
  end
131
141
 
132
142
  it 'it renders a custom JSON response', token: :invalid do
@@ -136,13 +146,23 @@ describe 'doorkeeper authorize filter' do
136
146
  expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
137
147
  parsed_body = JSON.parse(response.body)
138
148
  expect(parsed_body).not_to be_nil
139
- expect(parsed_body['error']).to eq('Unauthorized')
149
+ expect(parsed_body['error_message']).to match('token is invalid')
140
150
  end
141
151
  end
142
152
 
143
153
  context 'with a text custom render', token: :invalid do
144
154
  before do
145
- expect(controller).to receive(:doorkeeper_unauthorized_render_options).and_return(text: 'Unauthorized')
155
+ module ControllerActions
156
+ def doorkeeper_unauthorized_render_options(error: nil)
157
+ { text: 'Unauthorized' }
158
+ end
159
+ end
160
+ end
161
+ after do
162
+ module ControllerActions
163
+ def doorkeeper_unauthorized_render_options(error: nil)
164
+ end
165
+ end
146
166
  end
147
167
 
148
168
  it 'it renders a custom JSON response', token: :invalid do
@@ -0,0 +1,24 @@
1
+ require 'spec_helper_integration'
2
+
3
+ describe Doorkeeper::DashboardHelper do
4
+ describe '.doorkeeper_errors_for' do
5
+ let(:object) { double errors: { method: messages } }
6
+ let(:messages) { ['first message', 'second message'] }
7
+
8
+ context 'when object has errors' do
9
+ it 'returns error messages' do
10
+ messages.each do |message|
11
+ expect(helper.doorkeeper_errors_for(object, :method)).to include(
12
+ message.capitalize
13
+ )
14
+ end
15
+ end
16
+ end
17
+
18
+ context 'when object has no errors' do
19
+ it 'returns nil' do
20
+ expect(helper.doorkeeper_errors_for(object, :amonter_method)).to be_nil
21
+ end
22
+ end
23
+ end
24
+ end
@@ -19,12 +19,12 @@ describe 'Revocable' do
19
19
 
20
20
  describe :revoked? do
21
21
  it 'is revoked if :revoked_at has passed' do
22
- allow(subject).to receive(:revoked_at).and_return(DateTime.now - 1000)
22
+ allow(subject).to receive(:revoked_at).and_return(Time.now - 1000)
23
23
  expect(subject).to be_revoked
24
24
  end
25
25
 
26
26
  it 'is not revoked if :revoked_at has not passed' do
27
- allow(subject).to receive(:revoked_at).and_return(DateTime.now + 1000)
27
+ allow(subject).to receive(:revoked_at).and_return(Time.now + 1000)
28
28
  expect(subject).not_to be_revoked
29
29
  end
30
30
 
@@ -41,12 +41,12 @@ module Doorkeeper::OAuth::Helpers
41
41
  Doorkeeper::OAuth::Scopes.from_string 'common svr'
42
42
  end
43
43
  let(:application_scopes) do
44
- Doorkeeper::OAuth::Scopes.from_string 'common'
44
+ Doorkeeper::OAuth::Scopes.from_string 'app123'
45
45
  end
46
46
 
47
- it 'is valid if scope is included in the server and the application' do
47
+ it 'is valid if scope is included in the application scope list' do
48
48
  expect(ScopeChecker.valid?(
49
- 'common',
49
+ 'app123',
50
50
  server_scopes,
51
51
  application_scopes
52
52
  )).to be_truthy
@@ -84,8 +84,11 @@ module Doorkeeper::OAuth
84
84
 
85
85
  it 'skips token creation if there is a matching one' do
86
86
  allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
87
+ allow(application.scopes).to receive(:has_scopes?).and_return(true)
88
+ allow(application.scopes).to receive(:all?).and_return(true)
87
89
  FactoryGirl.create(:access_token, application_id: pre_auth.client.id,
88
90
  resource_owner_id: owner.id, scopes: 'public')
91
+
89
92
  expect do
90
93
  subject.authorize
91
94
  end.to_not change { Doorkeeper::AccessToken.count }
@@ -55,6 +55,12 @@ module Doorkeeper
55
55
  expect(new_application.uid).not_to be_nil
56
56
  end
57
57
 
58
+ it 'generates uid on create if an empty string' do
59
+ new_application.uid = ''
60
+ new_application.save
61
+ expect(new_application.uid).not_to be_blank
62
+ end
63
+
58
64
  it 'generates uid on create unless one is set' do
59
65
  new_application.uid = uid
60
66
  new_application.save
@@ -93,6 +99,12 @@ module Doorkeeper
93
99
  expect(new_application.secret).not_to be_nil
94
100
  end
95
101
 
102
+ it 'generate secret on create if is blank string' do
103
+ new_application.secret = ''
104
+ new_application.save
105
+ expect(new_application.secret).not_to be_blank
106
+ end
107
+
96
108
  it 'generate secret on create unless one is set' do
97
109
  new_application.secret = secret
98
110
  new_application.save
@@ -55,6 +55,11 @@ describe RedirectUriValidator do
55
55
  expect(subject).to be_valid
56
56
  end
57
57
 
58
+ it 'accepts app redirect uri' do
59
+ subject.redirect_uri = 'some-awesome-app://oauth/callback'
60
+ expect(subject).to be_valid
61
+ end
62
+
58
63
  it 'accepts a non secured protocol when disabled' do
59
64
  subject.redirect_uri = 'http://example.com/callback'
60
65
  allow(Doorkeeper.configuration).to receive(
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: doorkeeper
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.rc1
4
+ version: 3.0.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felipe Elias Philipp
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-05-12 00:00:00.000000000 Z
12
+ date: 2015-07-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties
@@ -134,7 +134,6 @@ files:
134
134
  - ".hound.yml"
135
135
  - ".rspec"
136
136
  - ".travis.yml"
137
- - CHANGELOG.md
138
137
  - CONTRIBUTING.md
139
138
  - Gemfile
140
139
  - MIT-LICENSE
@@ -287,6 +286,7 @@ files:
287
286
  - spec/generators/migration_generator_spec.rb
288
287
  - spec/generators/templates/routes.rb
289
288
  - spec/generators/views_generator_spec.rb
289
+ - spec/helpers/doorkeeper/dashboard_helper_spec.rb
290
290
  - spec/lib/config_spec.rb
291
291
  - spec/lib/doorkeeper_spec.rb
292
292
  - spec/lib/models/expirable_spec.rb
@@ -426,6 +426,7 @@ test_files:
426
426
  - spec/generators/migration_generator_spec.rb
427
427
  - spec/generators/templates/routes.rb
428
428
  - spec/generators/views_generator_spec.rb
429
+ - spec/helpers/doorkeeper/dashboard_helper_spec.rb
429
430
  - spec/lib/config_spec.rb
430
431
  - spec/lib/doorkeeper_spec.rb
431
432
  - spec/lib/models/expirable_spec.rb
data/CHANGELOG.md DELETED
@@ -1 +0,0 @@
1
- Moved to [NEWS.md](https://github.com/doorkeeper-gem/doorkeeper/blob/master/NEWS.md)