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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2eb5da9c49a3a0600451b34d688aec2da2dbf1df
4
- data.tar.gz: 9f9db27f7d5278e3c213818861ffcbbefdd10272
3
+ metadata.gz: 9c87a791f0146a97560be08975e4e0fd05b72e2d
4
+ data.tar.gz: 19030e24765e04a10ef4338dee46b6d9faf13620
5
5
  SHA512:
6
- metadata.gz: 80d9b5f9faca1ee0b45a824d0938bbbf6f644062093e098297b263a9849b6c7447f5ab639839048345b19e046a76a23e2eeb8cc5c54d5700a4735104af47efb9
7
- data.tar.gz: 852f0663b33a4fb1ace5ab88dbac330e1b7fcdc5ac28f59b5d6397dbe7562adf38ffc975680603f9f99057c7bb86ad76d3884dba0e71ed66a51fa56762e3c8d9
6
+ metadata.gz: 1a12c6bec0463233f4b7dd69dfc33f88b2a3b42e94fe9fb9bc542c94aadd51f2c39c29f73921616424493d68bc3100f6f937c032119438e72d9a083a4607c13b
7
+ data.tar.gz: 1b7ce3260177a092ed16e511750f751ec3f8f172cd372c0b31de46d65eaab2c04a5f7d9524c6344dd5ee73938275651d78181f8a0618fee5fb83cfbd99c9b90b
@@ -1,5 +1,29 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.0.rc1
4
+
5
+ - bug (spec)
6
+ - [#228] token response `expires_in` value is now in seconds, relative to
7
+ request time
8
+ - [#296] client is optional for password grant type.
9
+ - [#319] If client credentials are present on password grant type they are validated
10
+ - [#326] If client credentials are present in refresh token they are validated
11
+ - [#326] If authenticated client does not match original client that
12
+ obtained a refresh token it responds `invalid_grant` instead of
13
+ `invalid_client`. Previous usage was invalid according to Section 5.2 of
14
+ the spec.
15
+ - [#329] access tokens' `scopes` string wa being compared against
16
+ `default_scopes` symbols, always unauthorizing.
17
+ - enhancements
18
+ - [#293] Adds ActionController::Instrumentation in TokensController
19
+ - [#313] `AccessToken.revoke_all_for` actually revokes all non-revoked
20
+ tokens for an application/owner instead of deleting them.
21
+ [@bryanrite](https://github.com/bryanrite)
22
+ - internals
23
+ - Removes jQuery dependency [fixes #300] [PR #312 is related]
24
+ - [#294] Client uid and secret will be generated only if not present.
25
+ - [#316] Test warnings addressed.
26
+
3
27
  ## 0.7.4
4
28
 
5
29
  - bug
data/Gemfile CHANGED
@@ -4,8 +4,6 @@ ENV['orm'] ||= 'active_record'
4
4
 
5
5
  source 'https://rubygems.org'
6
6
 
7
- gem 'jquery-rails'
8
-
9
7
  # Define Rails version
10
8
  gem 'rails', ENV['rails']
11
9
 
data/README.md CHANGED
@@ -98,7 +98,7 @@ You need to configure Doorkeeper in order to provide resource_owner model and au
98
98
  ``` ruby
99
99
  Doorkeeper.configure do
100
100
  resource_owner_authenticator do
101
- User.find(session[:current_user_id]) || redirect_to(login_url)
101
+ User.find_by_id(session[:current_user_id]) || redirect_to(login_url)
102
102
  end
103
103
  end
104
104
  ```
@@ -1,6 +1,8 @@
1
1
  module Doorkeeper
2
2
  class TokensController < ActionController::Metal
3
3
  include Helpers::Controller
4
+ include ActionController::RackDelegation
5
+ include ActionController::Instrumentation
4
6
 
5
7
  def create
6
8
  response = strategy.authorize
@@ -0,0 +1,16 @@
1
+ <style>
2
+ input[type=submit] {
3
+ padding: 0;
4
+ border: none;
5
+ box-shadow: none;
6
+ background: none;
7
+ color: #0069d6;
8
+ }
9
+ input[type=submit]:hover {
10
+ text-decoration: underline;
11
+ }
12
+ </style>
13
+ <%= form_for [:oauth, application] do |f| %>
14
+ <input type="hidden" name="_method" value="delete">
15
+ <%= f.submit value: 'Remove', onclick: "return confirm('Are you sure?')" %>
16
+ <% end %>
@@ -1,3 +1,8 @@
1
+ <style>
2
+ input[type=submit] {
3
+ margin-top: 15px;
4
+ }
5
+ </style>
1
6
  <div class="span16">
2
7
  <header class="page-header">
3
8
  <h2>Your applications</h2>
@@ -20,10 +25,9 @@
20
25
  <td><%= link_to application.name, [:oauth, application] %></td>
21
26
  <td><%= application.redirect_uri %></td>
22
27
  <td><%= link_to 'Edit', edit_oauth_application_path(application) %></td>
23
- <td><%= link_to 'Destroy', [:oauth, application], :data => { :confirm => 'Are you sure?' }, :method => :delete %></td>
28
+ <td><%= render 'delete_form', application: application %></td>
24
29
  </tr>
25
30
  <% end %>
26
31
  </tbody>
27
32
  </table>
28
-
29
33
  </div>
@@ -22,5 +22,5 @@
22
22
  <h3>Actions</h3>
23
23
  <p><%= link_to 'List all', oauth_applications_path %></p>
24
24
  <p><%= link_to 'Edit', edit_oauth_application_path(@application) %></p>
25
- <p><%= link_to 'Remove', [:oauth, @application], :method => :delete, :data => { :confirm => "Are you sure?" } %></p>
25
+ <p><%= render 'delete_form', application: @application %></p>
26
26
  </div>
@@ -7,7 +7,7 @@
7
7
  <thead>
8
8
  <tr>
9
9
  <th>Application</th>
10
- <th>Authorized at</th>
10
+ <th>Created At</th>
11
11
  <th></th>
12
12
  <th></th>
13
13
  </tr>
@@ -3,7 +3,6 @@
3
3
  <head>
4
4
  <title>Doorkeeper</title>
5
5
  <%= stylesheet_link_tag "doorkeeper/application" %>
6
- <%= javascript_include_tag "doorkeeper/application" %>
7
6
  <%= csrf_meta_tags %>
8
7
  </head>
9
8
  <body>
@@ -17,7 +17,6 @@ Gem::Specification.new do |s|
17
17
  s.require_paths = ["lib"]
18
18
 
19
19
  s.add_dependency "railties", ">= 3.1"
20
- s.add_dependency "jquery-rails", ">= 2.0.2"
21
20
 
22
21
  s.add_development_dependency "sqlite3", "~> 1.3.5"
23
22
  s.add_development_dependency "rspec-rails", ">= 2.11.4"
@@ -23,7 +23,7 @@ module Doorkeeper
23
23
 
24
24
  private
25
25
  def scopes(scopes)
26
- @scopes = scopes
26
+ @scopes = scopes.map(&:to_s)
27
27
  end
28
28
 
29
29
  def if(if_block)
@@ -37,7 +37,7 @@ module Doorkeeper
37
37
  # TODO: move this to Token class
38
38
  def validate_token_scopes(token)
39
39
  return true if @scopes.blank?
40
- token.scopes.any? { |scope| @scopes.include? scope}
40
+ token.scopes.any? { |scope| @scopes.include? scope }
41
41
  end
42
42
  end
43
43
 
@@ -8,7 +8,7 @@ module Doorkeeper
8
8
 
9
9
  belongs_to :application, :class_name => "Doorkeeper::Application", :inverse_of => :access_tokens
10
10
 
11
- validates :application_id, :token, :presence => true
11
+ validates :token, :presence => true
12
12
  validates :token, :uniqueness => true
13
13
  validates :refresh_token, :uniqueness => true, :if => :use_refresh_token?
14
14
 
@@ -29,7 +29,10 @@ module Doorkeeper
29
29
  end
30
30
 
31
31
  def self.revoke_all_for(application_id, resource_owner)
32
- delete_all_for(application_id, resource_owner)
32
+ where(:application_id => application_id,
33
+ :resource_owner_id => resource_owner.id,
34
+ :revoked_at => nil)
35
+ .map(&:revoke)
33
36
  end
34
37
 
35
38
  def self.matching_token_for(application, resource_owner_or_id, scopes)
@@ -30,11 +30,11 @@ module Doorkeeper
30
30
  private
31
31
 
32
32
  def generate_uid
33
- self.uid = UniqueToken.generate
33
+ self.uid ||= UniqueToken.generate
34
34
  end
35
35
 
36
36
  def generate_secret
37
- self.secret = UniqueToken.generate
37
+ self.secret ||= UniqueToken.generate
38
38
  end
39
39
  end
40
40
  end
@@ -7,13 +7,16 @@ module Doorkeeper::OAuth
7
7
  validate :resource_owner, :error => :invalid_resource_owner
8
8
  validate :scopes, :error => :invalid_scope
9
9
 
10
- attr_accessor :server, :resource_owner, :client, :access_token
10
+ attr_accessor :server, :resource_owner, :credentials, :access_token
11
+ attr_accessor :client
11
12
 
12
- def initialize(server, client, resource_owner, parameters = {})
13
+ def initialize(server, credentials, resource_owner, parameters = {})
13
14
  @server = server
14
15
  @resource_owner = resource_owner
15
- @client = client
16
+ @credentials = credentials
16
17
  @original_scopes = parameters[:scope]
18
+
19
+ @client = Doorkeeper::Application.authenticate(credentials.uid, credentials.secret) if credentials
17
20
  end
18
21
 
19
22
  def authorize
@@ -41,8 +44,10 @@ module Doorkeeper::OAuth
41
44
  private
42
45
 
43
46
  def issue_token
47
+ application_id = client.id if client
48
+
44
49
  @access_token = Doorkeeper::AccessToken.create!({
45
- :application_id => client.id,
50
+ :application_id => application_id,
46
51
  :resource_owner_id => resource_owner.id,
47
52
  :scopes => scopes.to_s,
48
53
  :expires_in => server.access_token_expires_in,
@@ -50,10 +55,6 @@ module Doorkeeper::OAuth
50
55
  })
51
56
  end
52
57
 
53
- def validate_client
54
- !!client
55
- end
56
-
57
58
  def validate_scopes
58
59
  return true unless @original_scopes.present?
59
60
  ScopeChecker.valid?(@original_scopes, @server.scopes)
@@ -62,5 +63,9 @@ module Doorkeeper::OAuth
62
63
  def validate_resource_owner
63
64
  !!resource_owner
64
65
  end
66
+
67
+ def validate_client
68
+ !credentials || !!client
69
+ end
65
70
  end
66
71
  end
@@ -2,26 +2,32 @@ module Doorkeeper
2
2
  module OAuth
3
3
  class RefreshTokenRequest
4
4
  include Doorkeeper::Validations
5
+ include Doorkeeper::OAuth::Helpers
5
6
 
6
- validate :token, :error => :invalid_request
7
- validate :client, :error => :invalid_client
7
+ validate :token, :error => :invalid_request
8
+ validate :client, :error => :invalid_client
9
+ validate :client_match, :error => :invalid_grant
10
+ validate :scope, :error => :invalid_scope
8
11
 
9
- attr_accessor :server, :refresh_token, :client, :access_token
12
+ attr_accessor :server, :refresh_token, :credentials, :access_token
13
+ attr_accessor :client
10
14
 
11
- # TODO: refresh token can receive scope as parameters
12
- def initialize(server, refresh_token, client)
13
- @server = server
14
- @refresh_token = refresh_token
15
- @client = client
15
+ def initialize(server, refresh_token, credentials, parameters = {})
16
+ @server = server
17
+ @refresh_token = refresh_token
18
+ @credentials = credentials
19
+ @requested_scopes = parameters[:scopes]
20
+
21
+ @client = Doorkeeper::Application.authenticate(credentials.uid, credentials.secret) if credentials
16
22
  end
17
23
 
18
24
  def authorize
19
25
  validate
20
26
  @response = if valid?
21
27
  revoke_and_create_access_token
22
- OAuth::TokenResponse.new access_token
28
+ TokenResponse.new access_token
23
29
  else
24
- OAuth::ErrorResponse.from_request(self)
30
+ ErrorResponse.from_request self
25
31
  end
26
32
  end
27
33
 
@@ -29,6 +35,14 @@ module Doorkeeper
29
35
  self.error.nil?
30
36
  end
31
37
 
38
+ def scopes
39
+ @scopes ||= if @requested_scopes.present?
40
+ Scopes.from_string @requested_scopes
41
+ else
42
+ refresh_token.scopes
43
+ end
44
+ end
45
+
32
46
  private
33
47
 
34
48
  def revoke_and_create_access_token
@@ -40,7 +54,7 @@ module Doorkeeper
40
54
  @access_token = Doorkeeper::AccessToken.create!({
41
55
  :application_id => refresh_token.application_id,
42
56
  :resource_owner_id => refresh_token.resource_owner_id,
43
- :scopes => refresh_token.scopes_string,
57
+ :scopes => scopes.to_s,
44
58
  :expires_in => server.access_token_expires_in,
45
59
  :use_refresh_token => true
46
60
  })
@@ -51,7 +65,19 @@ module Doorkeeper
51
65
  end
52
66
 
53
67
  def validate_client
54
- client.present? && refresh_token.application_id == client.id
68
+ (!credentials || !!client)
69
+ end
70
+
71
+ def validate_client_match
72
+ !client || refresh_token.application_id == client.id
73
+ end
74
+
75
+ def validate_scope
76
+ if @requested_scopes.present?
77
+ ScopeChecker.valid?(@requested_scopes, refresh_token.scopes)
78
+ else
79
+ true
80
+ end
55
81
  end
56
82
  end
57
83
  end
@@ -11,7 +11,7 @@ module Doorkeeper
11
11
  {
12
12
  'access_token' => token.token,
13
13
  'token_type' => token.token_type,
14
- 'expires_in' => token.expires_in,
14
+ 'expires_in' => token.expires_in_seconds,
15
15
  'refresh_token' => token.refresh_token,
16
16
  'scope' => token.scopes_string
17
17
  }.reject { |_, value| value.blank? }
@@ -2,17 +2,17 @@ module Doorkeeper
2
2
  module Request
3
3
  class Password
4
4
  def self.build(server)
5
- new(server.client, server.resource_owner, server)
5
+ new(server.credentials, server.resource_owner, server)
6
6
  end
7
7
 
8
- attr_accessor :client, :resource_owner, :server
8
+ attr_accessor :credentials, :resource_owner, :server
9
9
 
10
- def initialize(client, resource_owner, server)
11
- @client, @resource_owner, @server = client, resource_owner, server
10
+ def initialize(credentials, resource_owner, server)
11
+ @credentials, @resource_owner, @server = credentials, resource_owner, server
12
12
  end
13
13
 
14
14
  def request
15
- @request ||= OAuth::PasswordAccessTokenRequest.new(Doorkeeper.configuration, client, resource_owner, server.parameters)
15
+ @request ||= OAuth::PasswordAccessTokenRequest.new(Doorkeeper.configuration, credentials, resource_owner, server.parameters)
16
16
  end
17
17
 
18
18
  def authorize
@@ -2,17 +2,17 @@ module Doorkeeper
2
2
  module Request
3
3
  class RefreshToken
4
4
  def self.build(server)
5
- new(server.current_refresh_token, server.client)
5
+ new(server.current_refresh_token, server.credentials, server)
6
6
  end
7
7
 
8
- attr_accessor :refresh_token, :client
8
+ attr_accessor :refresh_token, :credentials, :server
9
9
 
10
- def initialize(refresh_token, client)
11
- @refresh_token, @client = refresh_token, client
10
+ def initialize(refresh_token, credentials, server)
11
+ @refresh_token, @credentials, @server = refresh_token, credentials, server
12
12
  end
13
13
 
14
14
  def request
15
- @request ||= OAuth::RefreshTokenRequest.new(Doorkeeper.configuration, refresh_token, client)
15
+ @request ||= OAuth::RefreshTokenRequest.new(Doorkeeper.configuration, refresh_token, credentials, server.parameters)
16
16
  end
17
17
 
18
18
  def authorize
@@ -1,3 +1,3 @@
1
1
  module Doorkeeper
2
- VERSION = '0.7.4'
2
+ VERSION = '1.0.0.rc1'
3
3
  end
@@ -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
@@ -37,6 +37,15 @@ module Doorkeeper
37
37
  expect(response).to be_redirect
38
38
  end
39
39
 
40
+ it "does not allow mass assignment of uid or secret" do
41
+ application = FactoryGirl.create(:application)
42
+ put :update, id: application.id, application: {
43
+ uid: '1A2B3C4D',
44
+ secret: '1A2B3C4D' }
45
+
46
+ application.reload.uid.should_not eq '1A2B3C4D'
47
+ end
48
+
40
49
  it "updates application" do
41
50
  application = FactoryGirl.create(:application)
42
51
  put :update, id: application.id, application: {
@@ -167,14 +167,14 @@ describe "Doorkeeper_for helper" do
167
167
  let(:token_string) { "1A2DUWE" }
168
168
 
169
169
  it "allows if the token has particular scopes" do
170
- token = double(Doorkeeper::AccessToken, :accessible? => true, :scopes => [:write, :public])
170
+ token = double(Doorkeeper::AccessToken, :accessible? => true, :scopes => ['write', 'public'])
171
171
  Doorkeeper::AccessToken.should_receive(:authenticate).with(token_string).and_return(token)
172
172
  get :index, :access_token => token_string
173
173
  expect(response).to be_success
174
174
  end
175
175
 
176
176
  it "does not allow if the token does not include given scope" do
177
- token = double(Doorkeeper::AccessToken, :accessible? => true, :scopes => [:public])
177
+ token = double(Doorkeeper::AccessToken, :accessible? => true, :scopes => ['public'])
178
178
  Doorkeeper::AccessToken.should_receive(:authenticate).with(token_string).and_return(token)
179
179
  get :index, :access_token => token_string
180
180
  expect(response.status).to eq 401