doorkeeper 0.5.0 → 0.6.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 (105) hide show
  1. data/.travis.yml +15 -6
  2. data/CHANGELOG.md +19 -1
  3. data/Gemfile +23 -7
  4. data/README.md +62 -27
  5. data/app/controllers/doorkeeper/application_controller.rb +1 -1
  6. data/app/controllers/doorkeeper/authorizations_controller.rb +45 -35
  7. data/app/controllers/doorkeeper/token_info_controller.rb +10 -9
  8. data/app/controllers/doorkeeper/tokens_controller.rb +13 -32
  9. data/app/validators/redirect_uri_validator.rb +11 -0
  10. data/app/views/doorkeeper/applications/_form.html.erb +6 -1
  11. data/app/views/doorkeeper/applications/edit.html.erb +2 -2
  12. data/app/views/doorkeeper/applications/new.html.erb +2 -2
  13. data/app/views/doorkeeper/applications/show.html.erb +4 -1
  14. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  15. data/app/views/doorkeeper/authorizations/new.html.erb +17 -17
  16. data/app/views/doorkeeper/authorizations/show.html.erb +4 -0
  17. data/config/locales/en.yml +10 -0
  18. data/doorkeeper.gemspec +3 -3
  19. data/lib/doorkeeper.rb +11 -2
  20. data/lib/doorkeeper/config.rb +6 -1
  21. data/lib/doorkeeper/errors.rb +15 -0
  22. data/lib/doorkeeper/helpers/controller.rb +24 -0
  23. data/lib/doorkeeper/models/access_grant.rb +1 -1
  24. data/lib/doorkeeper/models/access_token.rb +2 -3
  25. data/lib/doorkeeper/models/active_record/access_token.rb +6 -0
  26. data/lib/doorkeeper/models/mongo_mapper/access_grant.rb +28 -0
  27. data/lib/doorkeeper/models/mongo_mapper/access_token.rb +51 -0
  28. data/lib/doorkeeper/models/mongo_mapper/application.rb +30 -0
  29. data/lib/doorkeeper/models/mongo_mapper/revocable.rb +15 -0
  30. data/lib/doorkeeper/models/{mongoid → mongoid2}/access_grant.rb +1 -1
  31. data/lib/doorkeeper/models/{mongoid → mongoid2}/access_token.rb +6 -0
  32. data/lib/doorkeeper/models/{mongoid → mongoid2}/application.rb +2 -2
  33. data/lib/doorkeeper/models/mongoid3/access_grant.rb +22 -0
  34. data/lib/doorkeeper/models/mongoid3/access_token.rb +41 -0
  35. data/lib/doorkeeper/models/mongoid3/application.rb +22 -0
  36. data/lib/doorkeeper/oauth/authorization/code.rb +9 -17
  37. data/lib/doorkeeper/oauth/authorization/token.rb +8 -18
  38. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +2 -0
  39. data/lib/doorkeeper/oauth/authorization_code_request.rb +82 -0
  40. data/lib/doorkeeper/oauth/client_credentials_request.rb +2 -4
  41. data/lib/doorkeeper/oauth/code_request.rb +28 -0
  42. data/lib/doorkeeper/oauth/code_response.rb +37 -0
  43. data/lib/doorkeeper/oauth/error_response.rb +23 -9
  44. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +4 -0
  45. data/lib/doorkeeper/oauth/password_access_token_request.rb +21 -65
  46. data/lib/doorkeeper/oauth/pre_authorization.rb +62 -0
  47. data/lib/doorkeeper/oauth/refresh_token_request.rb +58 -0
  48. data/lib/doorkeeper/oauth/token_request.rb +28 -0
  49. data/lib/doorkeeper/oauth/token_response.rb +29 -0
  50. data/lib/doorkeeper/rails/routes.rb +4 -3
  51. data/lib/doorkeeper/request.rb +33 -0
  52. data/lib/doorkeeper/request/authorization_code.rb +23 -0
  53. data/lib/doorkeeper/request/client_credentials.rb +23 -0
  54. data/lib/doorkeeper/request/code.rb +24 -0
  55. data/lib/doorkeeper/request/password.rb +23 -0
  56. data/lib/doorkeeper/request/refresh_token.rb +23 -0
  57. data/lib/doorkeeper/request/token.rb +24 -0
  58. data/lib/doorkeeper/server.rb +54 -0
  59. data/lib/doorkeeper/validations.rb +1 -0
  60. data/lib/doorkeeper/version.rb +1 -1
  61. data/lib/generators/doorkeeper/mongo_mapper/indexes_generator.rb +12 -0
  62. data/lib/generators/doorkeeper/templates/README +15 -1
  63. data/lib/generators/doorkeeper/templates/indexes.rb +3 -0
  64. data/lib/generators/doorkeeper/templates/initializer.rb +8 -1
  65. data/script/run_all +9 -9
  66. data/spec/controllers/authorizations_controller_spec.rb +8 -19
  67. data/spec/controllers/token_info_controller_spec.rb +9 -9
  68. data/spec/controllers/tokens_controller_spec.rb +2 -1
  69. data/spec/dummy/app/models/user.rb +11 -4
  70. data/spec/dummy/config/application.rb +8 -1
  71. data/spec/dummy/config/boot.rb +1 -1
  72. data/spec/dummy/config/initializers/doorkeeper.rb +9 -1
  73. data/spec/dummy/config/mongo.yml +11 -0
  74. data/spec/dummy/config/{mongoid.yml → mongoid2.yml} +3 -1
  75. data/spec/dummy/config/mongoid3.yml +18 -0
  76. data/spec/generators/install_generator_spec.rb +1 -0
  77. data/spec/lib/oauth/authorization_code_request_spec.rb +80 -0
  78. data/spec/lib/oauth/client_credentials_request_spec.rb +1 -3
  79. data/spec/lib/oauth/code_request_spec.rb +44 -0
  80. data/spec/lib/oauth/error_response_spec.rb +7 -7
  81. data/spec/lib/oauth/password_access_token_request_spec.rb +30 -143
  82. data/spec/lib/oauth/pre_authorization_spec.rb +80 -0
  83. data/spec/lib/oauth/refresh_token_request_spec.rb +56 -0
  84. data/spec/lib/oauth/token_request_spec.rb +46 -0
  85. data/spec/lib/oauth/{client_credentials/response_spec.rb → token_response_spec.rb} +13 -19
  86. data/spec/lib/server_spec.rb +24 -0
  87. data/spec/requests/endpoints/authorization_spec.rb +11 -27
  88. data/spec/requests/endpoints/token_spec.rb +17 -0
  89. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -45
  90. data/spec/requests/flows/authorization_code_spec.rb +12 -2
  91. data/spec/requests/flows/client_credentials_spec.rb +1 -1
  92. data/spec/requests/flows/password_spec.rb +1 -0
  93. data/spec/requests/flows/refresh_token_spec.rb +6 -4
  94. data/spec/spec_helper_integration.rb +4 -2
  95. data/spec/support/orm/mongo_mapper.rb +26 -0
  96. data/spec/support/orm/mongoid.rb +7 -2
  97. data/spec/validators/redirect_uri_validator_spec.rb +11 -4
  98. metadata +67 -42
  99. data/gemfiles/gemfile.rails-3.1.x +0 -17
  100. data/gemfiles/gemfile.rails-3.2.x +0 -17
  101. data/lib/doorkeeper/oauth/access_token_request.rb +0 -139
  102. data/lib/doorkeeper/oauth/authorization_request.rb +0 -114
  103. data/lib/doorkeeper/oauth/client_credentials/response.rb +0 -42
  104. data/spec/lib/oauth/access_token_request_spec.rb +0 -246
  105. data/spec/lib/oauth/authorization_request_spec.rb +0 -287
@@ -22,6 +22,10 @@ module Doorkeeper
22
22
  def self.as_uri(url)
23
23
  URI.parse(url)
24
24
  end
25
+
26
+ def self.test_uri?(url)
27
+ url == Doorkeeper.configuration.test_redirect_uri
28
+ end
25
29
  end
26
30
  end
27
31
  end
@@ -1,51 +1,31 @@
1
- # coding: utf-8
2
-
3
- # TODO: refactor to DRY up, this is very similar to AccessTokenRequest
4
1
  module Doorkeeper::OAuth
5
2
  class PasswordAccessTokenRequest
6
3
  include Doorkeeper::Validations
7
4
  include Doorkeeper::OAuth::Helpers
8
5
 
9
- ATTRIBUTES = [
10
- :grant_type,
11
- :username,
12
- :password,
13
- :scope,
14
- :refresh_token
15
- ]
16
-
17
- validate :attributes, :error => :invalid_request
18
- validate :grant_type, :error => :unsupported_grant_type
19
6
  validate :client, :error => :invalid_client
20
7
  validate :resource_owner, :error => :invalid_resource_owner
21
- validate :scope, :error => :invalid_scope
8
+ validate :scopes, :error => :invalid_scope
22
9
 
23
- attr_accessor *ATTRIBUTES
24
- attr_accessor :resource_owner, :client
10
+ attr_accessor :server, :resource_owner, :client
25
11
 
26
- def initialize(client, owner, attributes = {})
27
- ATTRIBUTES.each { |attr| instance_variable_set("@#{attr}", attributes[attr]) }
28
- @resource_owner = owner
29
- @client = client
30
- validate
12
+ def initialize(server, client, resource_owner, parameters = {})
13
+ @server = server
14
+ @resource_owner = resource_owner
15
+ @client = client
16
+ @original_scopes = parameters[:scope]
31
17
  end
32
18
 
33
19
  def authorize
34
- if valid?
20
+ validate
21
+ @response = if valid?
35
22
  find_or_create_access_token
23
+ TokenResponse.new access_token
24
+ else
25
+ ErrorResponse.from_request self
36
26
  end
37
27
  end
38
28
 
39
- def authorization
40
- auth = {
41
- 'access_token' => access_token.token,
42
- 'token_type' => access_token.token_type,
43
- 'expires_in' => access_token.expires_in,
44
- }
45
- auth.merge!({'refresh_token' => access_token.refresh_token}) if refresh_token_enabled?
46
- auth
47
- end
48
-
49
29
  def valid?
50
30
  self.error.nil?
51
31
  end
@@ -55,23 +35,15 @@ module Doorkeeper::OAuth
55
35
  @access_token ||= Doorkeeper::AccessToken.matching_token_for client, resource_owner.id, scopes
56
36
  end
57
37
 
58
- def token_type
59
- "bearer"
60
- end
61
-
62
- def error_response
63
- Doorkeeper::OAuth::ErrorResponse.from_request(self)
64
- end
65
-
66
38
  def scopes
67
- @scopes ||= if scope.present?
68
- Doorkeeper::OAuth::Scopes.from_string(scope)
39
+ @scopes ||= if @original_scopes.present?
40
+ Doorkeeper::OAuth::Scopes.from_string(@original_scopes)
69
41
  else
70
- Doorkeeper.configuration.default_scopes
42
+ server.default_scopes
71
43
  end
72
44
  end
73
45
 
74
- private
46
+ private
75
47
 
76
48
  def find_or_create_access_token
77
49
  if access_token
@@ -91,38 +63,22 @@ module Doorkeeper::OAuth
91
63
  :application_id => client.id,
92
64
  :resource_owner_id => resource_owner.id,
93
65
  :scopes => scopes.to_s,
94
- :expires_in => configuration.access_token_expires_in,
95
- :use_refresh_token => refresh_token_enabled?
66
+ :expires_in => server.access_token_expires_in,
67
+ :use_refresh_token => server.refresh_token_enabled?
96
68
  })
97
69
  end
98
70
 
99
- def validate_attributes
100
- grant_type.present?
101
- end
102
-
103
- def refresh_token_enabled?
104
- configuration.refresh_token_enabled?
105
- end
106
-
107
71
  def validate_client
108
72
  !!client
109
73
  end
110
74
 
111
- def validate_scope
112
- return true unless scope.present?
113
- ScopeChecker.valid?(scope, configuration.scopes)
114
- end
115
-
116
- def validate_grant_type
117
- grant_type == 'password'
75
+ def validate_scopes
76
+ return true unless @original_scopes.present?
77
+ ScopeChecker.valid?(@original_scopes, @server.scopes)
118
78
  end
119
79
 
120
80
  def validate_resource_owner
121
81
  !!resource_owner
122
82
  end
123
-
124
- def configuration
125
- Doorkeeper.configuration
126
- end
127
83
  end
128
84
  end
@@ -0,0 +1,62 @@
1
+ module Doorkeeper
2
+ module OAuth
3
+ class PreAuthorization
4
+ include Doorkeeper::Validations
5
+
6
+ validate :response_type, :error => :unsupported_response_type
7
+ validate :client, :error => :invalid_client
8
+ validate :scopes, :error => :invalid_scope
9
+ validate :redirect_uri, :error => :invalid_redirect_uri
10
+
11
+ attr_accessor :server, :client, :response_type, :redirect_uri, :state
12
+ attr_writer :scope
13
+
14
+ def initialize(server, client, attrs = {})
15
+ @server = server
16
+ @client = client
17
+ @response_type = attrs[:response_type]
18
+ @redirect_uri = attrs[:redirect_uri]
19
+ @scope = attrs[:scope]
20
+ @state = attrs[:state]
21
+ end
22
+
23
+ def authorizable?
24
+ valid?
25
+ end
26
+
27
+ def scopes
28
+ Scopes.from_string scope
29
+ end
30
+
31
+ def scope
32
+ @scope.presence || server.default_scopes.to_s
33
+ end
34
+
35
+ def error_response
36
+ Doorkeeper::OAuth::ErrorResponse.from_request(self)
37
+ end
38
+
39
+ private
40
+
41
+ def validate_response_type
42
+ %w[code token].include? response_type
43
+ end
44
+
45
+ def validate_client
46
+ client.present?
47
+ end
48
+
49
+ def validate_scopes
50
+ return true unless scope.present?
51
+ Helpers::ScopeChecker.valid? scope, server.scopes
52
+ end
53
+
54
+ # TODO: test uri should be matched against the client's one
55
+ def validate_redirect_uri
56
+ return false unless redirect_uri.present?
57
+ Helpers::URIChecker.test_uri?(redirect_uri) ||
58
+ Helpers::URIChecker.valid_for_authorization?(redirect_uri, client.redirect_uri)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,58 @@
1
+ module Doorkeeper
2
+ module OAuth
3
+ class RefreshTokenRequest
4
+ include Doorkeeper::Validations
5
+
6
+ validate :token, :error => :invalid_request
7
+ validate :client, :error => :invalid_client
8
+
9
+ attr_accessor :server, :refresh_token, :client, :access_token
10
+
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
16
+ end
17
+
18
+ def authorize
19
+ validate
20
+ @response = if valid?
21
+ revoke_and_create_access_token
22
+ OAuth::TokenResponse.new access_token
23
+ else
24
+ OAuth::ErrorResponse.from_request(self)
25
+ end
26
+ end
27
+
28
+ def valid?
29
+ self.error.nil?
30
+ end
31
+
32
+ private
33
+
34
+ def revoke_and_create_access_token
35
+ refresh_token.revoke
36
+ create_access_token
37
+ end
38
+
39
+ def create_access_token
40
+ @access_token = Doorkeeper::AccessToken.create!({
41
+ :application_id => refresh_token.application_id,
42
+ :resource_owner_id => refresh_token.resource_owner_id,
43
+ :scopes => refresh_token.scopes_string,
44
+ :expires_in => server.access_token_expires_in,
45
+ :use_refresh_token => true
46
+ })
47
+ end
48
+
49
+ def validate_token
50
+ refresh_token.present? && !refresh_token.revoked?
51
+ end
52
+
53
+ def validate_client
54
+ client.present? && refresh_token.application_id == client.id
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,28 @@
1
+ module Doorkeeper
2
+ module OAuth
3
+ class TokenRequest
4
+ attr_accessor :pre_auth, :resource_owner, :client
5
+
6
+ def initialize(pre_auth, resource_owner)
7
+ @pre_auth = pre_auth
8
+ @client = pre_auth.client
9
+ @resource_owner = resource_owner
10
+ end
11
+
12
+ def authorize
13
+ @response = if pre_auth.authorizable?
14
+ auth = Authorization::Token.new(pre_auth, resource_owner)
15
+ auth.issue_token
16
+ CodeResponse.new pre_auth, auth, :response_on_fragment => true
17
+ else
18
+ ErrorResponse.from_request pre_auth, :redirect_uri => pre_auth.redirect_uri, :response_on_fragment => true
19
+ end
20
+ end
21
+
22
+ def deny
23
+ pre_auth.error = :access_denied
24
+ ErrorResponse.from_request(pre_auth, :redirect_uri => pre_auth.redirect_uri, :response_on_fragment => true)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ module Doorkeeper
2
+ module OAuth
3
+ class TokenResponse
4
+ attr_accessor :token
5
+
6
+ def initialize(token)
7
+ @token = token
8
+ end
9
+
10
+ def body
11
+ {
12
+ 'access_token' => token.token,
13
+ 'token_type' => token.token_type,
14
+ 'expires_in' => token.expires_in,
15
+ 'refresh_token' => token.refresh_token,
16
+ 'scope' => token.scopes_string
17
+ }
18
+ end
19
+
20
+ def status
21
+ :ok
22
+ end
23
+
24
+ def headers
25
+ { 'Cache-Control' => 'no-store', 'Pragma' => 'no-cache', 'Content-Type' => 'application/json; charset=utf-8' }
26
+ end
27
+ end
28
+ end
29
+ end
@@ -47,9 +47,10 @@ module Doorkeeper
47
47
 
48
48
  def authorization_routes(mapping)
49
49
  routes.scope :controller => mapping[:controllers] do
50
- routes.match 'authorize', :via => :get, :action => :new, :as => mapping[:as]
51
- routes.match 'authorize', :via => :post, :action => :create, :as => mapping[:as]
52
- routes.match 'authorize', :via => :delete, :action => :destroy, :as => mapping[:as]
50
+ routes.match 'authorize/:code', :via => :get, :action => :show, :as => "#{mapping[:as]}_code"
51
+ routes.match 'authorize', :via => :get, :action => :new, :as => mapping[:as]
52
+ routes.match 'authorize', :via => :post, :action => :create, :as => mapping[:as]
53
+ routes.match 'authorize', :via => :delete, :action => :destroy, :as => mapping[:as]
53
54
  end
54
55
  end
55
56
 
@@ -0,0 +1,33 @@
1
+ require 'doorkeeper/request/authorization_code'
2
+ require 'doorkeeper/request/client_credentials'
3
+ require 'doorkeeper/request/code'
4
+ require 'doorkeeper/request/password'
5
+ require 'doorkeeper/request/refresh_token'
6
+ require 'doorkeeper/request/token'
7
+
8
+ module Doorkeeper
9
+ module Request
10
+ extend self
11
+
12
+ # Available authorization strategies:
13
+ # :code, :token
14
+ def authorization_strategy(strategy)
15
+ get_strategy strategy
16
+ rescue NameError
17
+ raise Errors::InvalidAuthorizationStrategy
18
+ end
19
+
20
+ # Available token strategies:
21
+ # :password, :client_credentials, :authorization_code, :refresh_token
22
+ def token_strategy(strategy)
23
+ get_strategy strategy
24
+ rescue NameError
25
+ raise Errors::InvalidTokenStrategy
26
+ end
27
+
28
+ def get_strategy(strategy)
29
+ raise Errors::MissingRequestStrategy unless strategy.present?
30
+ "Doorkeeper::Request::#{strategy.to_s.camelize}".constantize
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ module Doorkeeper
2
+ module Request
3
+ class AuthorizationCode
4
+ def self.build(server)
5
+ new(server.grant, server.client, server)
6
+ end
7
+
8
+ attr_accessor :grant, :client, :server
9
+
10
+ def initialize(grant, client, server)
11
+ @grant, @client, @server = grant, client, server
12
+ end
13
+
14
+ def request
15
+ @request ||= OAuth::AuthorizationCodeRequest.new(Doorkeeper.configuration, grant, client, server.parameters)
16
+ end
17
+
18
+ def authorize
19
+ request.authorize
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ module Doorkeeper
2
+ module Request
3
+ class ClientCredentials
4
+ def self.build(server)
5
+ new(server.client, server)
6
+ end
7
+
8
+ attr_accessor :client, :server
9
+
10
+ def initialize(client, server)
11
+ @client, @server = client, server
12
+ end
13
+
14
+ def request
15
+ @request ||= OAuth::ClientCredentialsRequest.new(Doorkeeper.configuration, client, server.parameters)
16
+ end
17
+
18
+ def authorize
19
+ request.authorize
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,24 @@
1
+ module Doorkeeper
2
+ module Request
3
+ class Code
4
+ # TODO: this is so wrong!
5
+ def self.build(server)
6
+ new(server.context.send(:pre_auth), server)
7
+ end
8
+
9
+ attr_accessor :pre_auth, :server
10
+
11
+ def initialize(pre_auth, server)
12
+ @pre_auth, @server = pre_auth, server
13
+ end
14
+
15
+ def request
16
+ @request ||= OAuth::CodeRequest.new(pre_auth, server.current_resource_owner)
17
+ end
18
+
19
+ def authorize
20
+ request.authorize
21
+ end
22
+ end
23
+ end
24
+ end