doorkeeper 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. data/.gitignore +12 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +8 -0
  4. data/CHANGELOG.md +98 -0
  5. data/Gemfile +6 -0
  6. data/README.md +42 -6
  7. data/app/controllers/doorkeeper/application_controller.rb +4 -11
  8. data/app/controllers/doorkeeper/applications_controller.rb +7 -1
  9. data/app/controllers/doorkeeper/authorizations_controller.rb +11 -1
  10. data/app/controllers/doorkeeper/authorized_applications_controller.rb +3 -3
  11. data/app/controllers/doorkeeper/tokens_controller.rb +19 -5
  12. data/app/models/doorkeeper/access_grant.rb +28 -0
  13. data/app/models/doorkeeper/access_token.rb +65 -0
  14. data/app/models/doorkeeper/application.rb +54 -0
  15. data/app/views/doorkeeper/applications/index.html.erb +1 -1
  16. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  17. data/app/views/doorkeeper/authorizations/new.html.erb +15 -15
  18. data/app/views/doorkeeper/authorized_applications/index.html.erb +1 -2
  19. data/config/locales/en.yml +3 -0
  20. data/doorkeeper.gemspec +28 -0
  21. data/gemfiles/gemfile.rails-3.1.x +7 -0
  22. data/gemfiles/gemfile.rails-3.2.x +7 -0
  23. data/lib/doorkeeper/config.rb +73 -12
  24. data/lib/doorkeeper/doorkeeper_for.rb +19 -15
  25. data/lib/doorkeeper/engine.rb +28 -0
  26. data/lib/doorkeeper/models/scopes.rb +13 -0
  27. data/lib/doorkeeper/oauth/access_token_request.rb +9 -20
  28. data/lib/doorkeeper/oauth/authorization/code.rb +1 -1
  29. data/lib/doorkeeper/oauth/authorization/token.rb +2 -2
  30. data/lib/doorkeeper/oauth/authorization_request.rb +18 -23
  31. data/lib/doorkeeper/oauth/client/credentials.rb +21 -0
  32. data/lib/doorkeeper/oauth/client/methods.rb +18 -0
  33. data/lib/doorkeeper/oauth/client.rb +27 -0
  34. data/lib/doorkeeper/oauth/client_credentials/creator.rb +29 -0
  35. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +35 -0
  36. data/lib/doorkeeper/oauth/client_credentials/response.rb +42 -0
  37. data/lib/doorkeeper/oauth/client_credentials/validation.rb +33 -0
  38. data/lib/doorkeeper/oauth/client_credentials_request.rb +46 -0
  39. data/lib/doorkeeper/oauth/error.rb +9 -0
  40. data/lib/doorkeeper/oauth/error_response.rb +30 -0
  41. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -2
  42. data/lib/doorkeeper/oauth/password_access_token_request.rb +130 -0
  43. data/lib/doorkeeper/oauth/scopes.rb +60 -0
  44. data/lib/doorkeeper/version.rb +1 -1
  45. data/lib/doorkeeper.rb +23 -3
  46. data/lib/generators/doorkeeper/install_generator.rb +1 -0
  47. data/lib/generators/doorkeeper/templates/initializer.rb +12 -7
  48. data/lib/generators/doorkeeper/templates/migration.rb +1 -1
  49. data/lib/generators/doorkeeper/views_generator.rb +15 -0
  50. data/script/rails +6 -0
  51. data/script/run_all +11 -0
  52. data/spec/controllers/applications_controller_spec.rb +18 -0
  53. data/spec/controllers/authorizations_controller_spec.rb +131 -0
  54. data/spec/controllers/protected_resources_controller_spec.rb +308 -0
  55. data/spec/controllers/tokens_controller_spec.rb +34 -0
  56. data/spec/dummy/Rakefile +7 -0
  57. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  58. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  59. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  60. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +12 -0
  61. data/spec/dummy/app/controllers/home_controller.rb +17 -0
  62. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +11 -0
  63. data/spec/dummy/app/helpers/application_helper.rb +5 -0
  64. data/spec/dummy/app/models/user.rb +11 -0
  65. data/spec/dummy/app/views/home/index.html.erb +0 -0
  66. data/spec/dummy/app/views/layouts/application.html.erb +16 -0
  67. data/spec/dummy/config/application.rb +53 -0
  68. data/spec/dummy/config/boot.rb +10 -0
  69. data/spec/dummy/config/database.yml +15 -0
  70. data/spec/dummy/config/environment.rb +5 -0
  71. data/spec/dummy/config/environments/development.rb +30 -0
  72. data/spec/dummy/config/environments/production.rb +60 -0
  73. data/spec/dummy/config/environments/test.rb +39 -0
  74. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  75. data/spec/dummy/config/initializers/doorkeeper.rb +41 -0
  76. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  77. data/spec/dummy/config/initializers/session_store.rb +8 -0
  78. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  79. data/spec/dummy/config/locales/doorkeeper.en.yml +5 -0
  80. data/spec/dummy/config/routes.rb +8 -0
  81. data/spec/dummy/config.ru +4 -0
  82. data/spec/dummy/db/migrate/20111122132257_create_users.rb +9 -0
  83. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +5 -0
  84. data/spec/dummy/db/migrate/20120524202412_create_doorkeeper_tables.rb +42 -0
  85. data/spec/dummy/db/schema.rb +62 -0
  86. data/spec/dummy/public/404.html +26 -0
  87. data/spec/dummy/public/422.html +26 -0
  88. data/spec/dummy/public/500.html +26 -0
  89. data/spec/dummy/public/favicon.ico +0 -0
  90. data/spec/dummy/script/rails +6 -0
  91. data/spec/factories/access_grant.rb +9 -0
  92. data/spec/factories/access_token.rb +7 -0
  93. data/spec/factories/application.rb +6 -0
  94. data/spec/generators/install_generator_spec.rb +35 -0
  95. data/spec/generators/templates/routes.rb +3 -0
  96. data/spec/generators/views_generator_spec.rb +27 -0
  97. data/spec/lib/config_spec.rb +87 -0
  98. data/spec/lib/models/expirable_spec.rb +49 -0
  99. data/spec/lib/models/revocable_spec.rb +31 -0
  100. data/spec/lib/models/scopes_spec.rb +32 -0
  101. data/spec/lib/oauth/access_token_request_spec.rb +240 -0
  102. data/spec/lib/oauth/authorization/uri_builder_spec.rb +37 -0
  103. data/spec/lib/oauth/authorization_request_spec.rb +286 -0
  104. data/spec/lib/oauth/client/credentials_spec.rb +47 -0
  105. data/spec/lib/oauth/client/methods_spec.rb +54 -0
  106. data/spec/lib/oauth/client_credentials/creator_spec.rb +47 -0
  107. data/spec/lib/oauth/client_credentials/issuer_spec.rb +57 -0
  108. data/spec/lib/oauth/client_credentials/response_spec.rb +58 -0
  109. data/spec/lib/oauth/client_credentials/validation_spec.rb +29 -0
  110. data/spec/lib/oauth/client_credentials_integration_spec.rb +27 -0
  111. data/spec/lib/oauth/client_credentials_request_spec.rb +60 -0
  112. data/spec/lib/oauth/client_spec.rb +42 -0
  113. data/spec/lib/oauth/error_response_spec.rb +40 -0
  114. data/spec/lib/oauth/error_spec.rb +19 -0
  115. data/spec/lib/oauth/helpers/scope_checker_spec.rb +74 -0
  116. data/spec/lib/oauth/helpers/unique_token_spec.rb +38 -0
  117. data/spec/lib/oauth/helpers/uri_checker_spec.rb +64 -0
  118. data/spec/lib/oauth/password_access_token_request_spec.rb +152 -0
  119. data/spec/lib/oauth/scopes_spec.rb +115 -0
  120. data/spec/models/doorkeeper/access_grant_spec.rb +36 -0
  121. data/spec/models/doorkeeper/access_token_spec.rb +113 -0
  122. data/spec/models/doorkeeper/application_spec.rb +129 -0
  123. data/spec/requests/applications/applications_request_spec.rb +92 -0
  124. data/spec/requests/applications/authorized_applications_spec.rb +30 -0
  125. data/spec/requests/endpoints/authorization_spec.rb +63 -0
  126. data/spec/requests/endpoints/token_spec.rb +29 -0
  127. data/spec/requests/flows/authorization_code_errors_spec.rb +111 -0
  128. data/spec/requests/flows/authorization_code_spec.rb +125 -0
  129. data/spec/requests/flows/client_credentials_spec.rb +56 -0
  130. data/spec/requests/flows/implicit_grant_errors_spec.rb +31 -0
  131. data/spec/requests/flows/implicit_grant_spec.rb +19 -0
  132. data/spec/requests/flows/password_spec.rb +52 -0
  133. data/spec/requests/flows/refresh_token_spec.rb +66 -0
  134. data/spec/requests/flows/skip_authorization_spec.rb +40 -0
  135. data/spec/requests/protected_resources/private_api_spec.rb +43 -0
  136. data/spec/spec_helper.rb +1 -0
  137. data/spec/spec_helper_integration.rb +28 -0
  138. data/spec/support/dependencies/database_cleaner.rb +16 -0
  139. data/spec/support/dependencies/factory_girl.rb +5 -0
  140. data/spec/support/helpers/access_token_request_helper.rb +11 -0
  141. data/spec/support/helpers/authorization_request_helper.rb +32 -0
  142. data/spec/support/helpers/config_helper.rb +9 -0
  143. data/spec/support/helpers/model_helper.rb +45 -0
  144. data/spec/support/helpers/request_spec_helper.rb +72 -0
  145. data/spec/support/helpers/url_helper.rb +51 -0
  146. data/spec/support/shared/controllers_shared_context.rb +60 -0
  147. data/spec/support/shared/models_shared_examples.rb +44 -0
  148. metadata +163 -57
  149. data/app/controllers/doorkeeper/application_controller.rbc +0 -675
  150. data/app/controllers/doorkeeper/applications_controller.rbc +0 -954
  151. data/app/controllers/doorkeeper/authorizations_controller.rbc +0 -659
  152. data/app/controllers/doorkeeper/authorized_applications_controller.rbc +0 -393
  153. data/app/controllers/doorkeeper/tokens_controller.rbc +0 -423
  154. data/app/helpers/doorkeeper/application_helper.rbc +0 -127
  155. data/app/models/access_grant.rb +0 -31
  156. data/app/models/access_grant.rbc +0 -821
  157. data/app/models/access_token.rb +0 -70
  158. data/app/models/access_token.rbc +0 -979
  159. data/app/models/application.rb +0 -45
  160. data/app/models/application.rbc +0 -753
  161. data/config/initializers/form_errors.rbc +0 -272
  162. data/config/routes.rbc +0 -366
  163. data/lib/doorkeeper/config/scope.rb +0 -11
  164. data/lib/doorkeeper/config/scopes.rb +0 -61
  165. data/lib/doorkeeper/config/scopes_builder.rb +0 -18
  166. data/lib/doorkeeper/config.rbc +0 -1385
  167. data/lib/doorkeeper/doorkeeper_for.rbc +0 -1029
  168. data/lib/doorkeeper/engine.rbc +0 -318
  169. data/lib/doorkeeper/oauth/access_token_request.rbc +0 -2042
  170. data/lib/doorkeeper/oauth/authorization_request.rbc +0 -2272
  171. data/lib/doorkeeper/oauth/random_string.rbc +0 -437
  172. data/lib/doorkeeper/validations.rbc +0 -774
  173. data/lib/doorkeeper/version.rbc +0 -130
  174. data/lib/doorkeeper.rbc +0 -407
  175. data/lib/generators/doorkeeper/install_generator.rbc +0 -453
  176. data/lib/tasks/doorkeeper_tasks.rake.compiled.rbc +0 -40
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ .bundle/
2
+ .rbx
3
+ *.rbc
4
+ log/*.log
5
+ pkg/
6
+ spec/dummy/db/*.sqlite3
7
+ spec/dummy/log/*.log
8
+ spec/dummy/tmp/
9
+ Gemfile.lock
10
+ gemfiles/*.lock
11
+ spec/generators/tmp
12
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ rvm:
2
+ - 1.9.3
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - rbx
6
+ gemfile:
7
+ - gemfiles/gemfile.rails-3.1.x
8
+ - gemfiles/gemfile.rails-3.2.x
data/CHANGELOG.md ADDED
@@ -0,0 +1,98 @@
1
+ # Changelog
2
+
3
+ ## 0.4.0
4
+
5
+ - deprecation
6
+ - Deprecate authorization_scopes
7
+ - database changes
8
+ - AccessToken#resource_owner_id is not nullable
9
+ - enhancements
10
+ - [#83] Add Resource Owner Password Credentials flow [@jaimeiniesta](https://github.com/jaimeiniesta)
11
+ - [#76] Allow token expiration to be disabled [@mattgreen](https://github.com/mattgreen)
12
+ - [#b6470a] Add Client Credentials flow
13
+ - internals
14
+ - [#2ece8d, #f93778] Introduce Client and ErrorResponse classes
15
+
16
+ ## 0.3.4
17
+
18
+ - Fix attr_accessible for rails 3.2.x
19
+
20
+ ## 0.3.3
21
+
22
+ - [#86] shrink gem package size
23
+
24
+ ## 0.3.2
25
+
26
+ - enhancements
27
+ - [#54] Ignore Authorization: headers that are not Bearer [@miyagawa](https://github.com/miyagawa)
28
+ - [#58, #64] Add destroy action to applications endpoint [@jaimeiniesta](https://github.com/jaimeiniesta), [@davidfrey](https://github.com/davidfrey)
29
+ - [#63] TokensController responds with `401 unauthorized` [@jaimeiniesta](https://github.com/jaimeiniesta)
30
+ - [#67, #72] Fix for mass-assignment [@cicloid](https://github.com/cicloid)
31
+ - internals
32
+ - [#49] Add Gemnasium status image to README [@laserlemon](https://github.com/laserlemon)
33
+ - [#50] Fix typos [@tomekw](https://github.com/tomekw)
34
+ - [#51] Updated the factory_girl_rails dependency, fix expires_in response which returned a float number instead of integer [@antekpiechnik](https://github.com/antekpiechnik)
35
+ - [#62] Typos, .gitignore [@jaimeiniesta](https://github.com/jaimeiniesta)
36
+ - [#65] Change _path redirections to _url redirections [@jaimeiniesta](https://github.com/jaimeiniesta)
37
+ - [#75] Fix unknown method #authenticate_admin! [@mattgreen](https://github.com/mattgreen)
38
+ - Remove application link in authorized app view
39
+
40
+ ## 0.3.1
41
+
42
+ - enhancements
43
+ - [#48] Add if, else options to doorkeeper_for
44
+ - Add views generator
45
+ - internals
46
+ - Namespace models
47
+
48
+ ## 0.3.0
49
+
50
+ - enhancements
51
+ - [#17, #31] Add support for client credentials in basic auth header [@GoldsteinTechPartners](https://github.com/GoldsteinTechPartners)
52
+ - [#28] Add indices to migration [@GoldsteinTechPartners](https://github.com/GoldsteinTechPartners)
53
+ - [#29] Allow doorkeeper to run with rails 3.2 [@john-griffin](https://github.com/john-griffin)
54
+ - [#30] Improve client's redirect uri validation [@GoldsteinTechPartners](https://github.com/GoldsteinTechPartners)
55
+ - [#32] Add token (implicit grant) flow [@GoldsteinTechPartners](https://github.com/GoldsteinTechPartners)
56
+ - [#34] Add support for custom unathorized responses [@GoldsteinTechPartners](https://github.com/GoldsteinTechPartners)
57
+ - [#36] Remove repetitions from the Authorised Applications view [@carvil](https://github.com/carvil)
58
+ - When user revoke an application, all tokens for that application are revoked
59
+ - Error messages now can be translated
60
+ - Install generator copies the error messages localization file
61
+ - internals
62
+ - Fix deprecation warnings in ActiveSupport::Base64
63
+ - Remove deprecation in doorkeeper_for that handles hash arguments
64
+ - Depends on railties instead of whole rails framework
65
+ - CI now integrates with rails 3.1 and 3.2
66
+
67
+ ## 0.2.0
68
+
69
+ - enhancements
70
+ - [#4] Add authorized applications endpoint
71
+ - [#5, #11] Add access token scopes
72
+ - [#10] Add access token expiration by default
73
+ - [#9, #12] Add refresh token flow
74
+ - internals
75
+ - [#7] Improve configuration options with :default
76
+ - Improve configuration options with :builder
77
+ - Refactor config class
78
+ - Improve coverage of authorization request integration
79
+ - bug fixes
80
+ - [#6, #20] Fix access token response headers
81
+ - Fix issue with state parameter
82
+ - deprecation
83
+ - deprecate :only and :except options in doorkeeper_for
84
+
85
+ ## 0.1.1
86
+
87
+ - enhancements
88
+ - [#3] Authorization code must be short lived and single use
89
+ - [#2] Improve views provided by doorkeeper
90
+ - [#1] Skips authorization form if the client has been authorized by the resource owner
91
+ - Improve readme
92
+ - bugfixes
93
+ - Fix issue when creating the access token (wrong client id)
94
+
95
+ ## 0.1.0
96
+
97
+ - Authorization Code flow
98
+ - OAuth applications endpoint
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ # jquery-rails is used by the dummy application
6
+ gem "jquery-rails"
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Doorkeeper - awesome oauth provider for your Rails app.
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/applicake/doorkeeper.png)](http://travis-ci.org/applicake/doorkeeper)
4
+ [![Dependency Status](https://gemnasium.com/applicake/doorkeeper.png)](https://gemnasium.com/applicake/doorkeeper)
4
5
 
5
6
  Doorkeeper is a gem that makes it easy to introduce OAuth 2 provider functionality to your application.
6
7
 
@@ -13,7 +14,7 @@ For more information about the supported features, check out the related [page i
13
14
  Put this in your Gemfile:
14
15
 
15
16
  ``` ruby
16
- gem 'doorkeeper', '~> 0.3.0'
17
+ gem 'doorkeeper', '~> 0.4.0'
17
18
  ```
18
19
 
19
20
  Run the installation generator with:
@@ -48,11 +49,13 @@ You need to configure Doorkeeper in order to provide resource_owner model and au
48
49
  ``` ruby
49
50
  Doorkeeper.configure do
50
51
  resource_owner_authenticator do |routes|
51
- current_user || redirect_to('/sign_in', :alert => "Needs sign in.") # returns nil if current_user is not logged in
52
+ current_user || redirect_to(routes.login_url) # returns nil if current_user is not logged in
52
53
  end
53
54
  end
54
55
  ```
55
56
 
57
+ This block runs into the context of your Rails application, and it has access to `current_user` method, for example.
58
+
56
59
  If you use [devise](https://github.com/plataformatec/devise), you may want to use warden to authenticate the block:
57
60
 
58
61
  ``` ruby
@@ -61,6 +64,8 @@ resource_owner_authenticator do |routes|
61
64
  end
62
65
  ```
63
66
 
67
+ If you are not using devise, you may want to check other ways of authentication [here](https://github.com/applicake/doorkeeper/wiki/Authenticating-using-Clearance-DIY).
68
+
64
69
  ## Protecting resources with OAuth (a.k.a your API endpoint)
65
70
 
66
71
  To protect your API with OAuth, doorkeeper only requires you to call `doorkeeper_for` helper, specifying the actions you want to protect.
@@ -70,7 +75,7 @@ For example, if you have a products controller under api/v1, you can require the
70
75
  ``` ruby
71
76
  class Api::V1::ProductsController < Api::V1::ApiController
72
77
  doorkeeper_for :all # Require access token for all actions
73
- doorkeeper_for :all, :except => :index # All actions except show
78
+ doorkeeper_for :all, :except => :index # All actions except index
74
79
  doorkeeper_for :index, :show # Only for index and show action
75
80
 
76
81
  # your actions
@@ -79,10 +84,29 @@ end
79
84
 
80
85
  You don't need to setup any before filter, `doorkeeper_for` will handle that for you.
81
86
 
87
+ You can pass `if` or `unless` blocks that would specify when doorkeeper has to guard the access.
88
+
89
+ ``` ruby
90
+ class Api::V1::ProductsController < Api::V1::ApiController
91
+ doorkeeper_for :all, :if => lambda { request.xhr? }
92
+ end
93
+ ```
94
+
82
95
  ### Access Token Scopes
83
96
 
84
97
  You can also require the access token to have specific scopes in certain actions:
85
98
 
99
+ First configure the scopes in `initializers/doorkeeper.rb`
100
+
101
+ ```ruby
102
+ Doorkeeper.configure do
103
+ default_scope :public # if no scope was requested, this will be the default
104
+ optional_scope :admin, :write
105
+ end
106
+ ```
107
+
108
+ The in your controllers:
109
+
86
110
  ```ruby
87
111
  class Api::V1::ProductsController < Api::V1::ApiController
88
112
  doorkeeper_for :index, :show, :scopes => [:public]
@@ -117,12 +141,24 @@ end
117
141
 
118
142
  In this example, we're returning the credentials (`me.json`) of the access token owner.
119
143
 
144
+ ## Upgrading
145
+
146
+ If you want to upgrade doorkeeper to a new version, check out the [upgrading notes](https://github.com/applicake/doorkeeper/wiki/Migration-from-old-versions) and take a look at the [changelog](https://github.com/applicake/doorkeeper/blob/master/CHANGELOG.md).
147
+
120
148
  ## Other resources
121
149
 
150
+ ### Wiki
151
+
152
+ You can find everything about doorkeeper in our [wiki here](https://github.com/applicake/doorkeeper/wiki).
153
+
122
154
  ### Live demo
123
155
 
124
156
  Check out this [live demo](http://doorkeeper-provider.herokuapp.com) hosted on heroku. For more demos check out [the wiki](https://github.com/applicake/doorkeeper/wiki/Example-Applications).
125
157
 
158
+ ### Screencast
159
+
160
+ Check out this screencast from [railscasts.com](http://railscasts.com/): [#353 OAuth with Doorkeeper](http://railscasts.com/episodes/353-oauth-with-doorkeeper)
161
+
126
162
  ### Client applications
127
163
 
128
164
  After you set up the provider, you may want to create a client application to test the integration. Check out these [client examples](https://github.com/applicake/doorkeeper/wiki/Example-Applications) in our wiki or follow this [tutorial here](https://github.com/applicake/doorkeeper/wiki/Testing-your-provider-with-OAuth2-gem).
@@ -135,14 +171,14 @@ Also, check out our [contributing guidelines page](https://github.com/applicake/
135
171
 
136
172
  ### Supported ruby versions
137
173
 
138
- All supported ruby versions are [listed here](https://github.com/applicake/doorkeeper/wiki/Supported-Ruby-versions)
174
+ All supported ruby versions are [listed here](https://github.com/applicake/doorkeeper/wiki/Supported-Ruby-&-Rails-versions).
139
175
 
140
176
  ## Additional information
141
177
 
142
178
  ### Maintainers
143
179
 
144
- - Felipe Elias Philipp ([github.com/felipeelias](https://github.com/felipeelias))
145
- - Piotr Jakubowski ([github.com/piotrj](https://github.com/piotrj))
180
+ - Felipe Elias Philipp ([github.com/felipeelias](https://github.com/felipeelias), [twitter.com/felipeelias](https://twitter.com/felipeelias))
181
+ - Piotr Jakubowski ([github.com/piotrj](https://github.com/piotrj), [twitter.com/piotrjakubowski](https://twitter.com/piotrjakubowski))
146
182
 
147
183
  ### Contributors
148
184
 
@@ -2,17 +2,6 @@ module Doorkeeper
2
2
  class ApplicationController < ActionController::Base
3
3
  private
4
4
 
5
- def parse_client_info_from_basic_auth
6
- auth_header = request.env['HTTP_AUTHORIZATION']
7
- return unless auth_header && auth_header =~ /^Basic (.*)/m
8
- client_info = Base64.decode64($1).split(/:/, 2)
9
- client_id = client_info[0]
10
- client_secret = client_info[1]
11
- return if client_id.nil? || client_secret.nil?
12
- params[:client_id] = client_id
13
- params[:client_secret] = client_secret
14
- end
15
-
16
5
  def authenticate_resource_owner!
17
6
  current_resource_owner
18
7
  end
@@ -21,6 +10,10 @@ module Doorkeeper
21
10
  instance_exec(main_app, &Doorkeeper.configuration.authenticate_resource_owner)
22
11
  end
23
12
 
13
+ def resource_owner_from_credentials
14
+ instance_exec(main_app, &Doorkeeper.configuration.resource_owner_from_credentials)
15
+ end
16
+
24
17
  def authenticate_admin!
25
18
  if block = Doorkeeper.configuration.authenticate_admin
26
19
  instance_exec(main_app, &block)
@@ -1,5 +1,5 @@
1
1
  module Doorkeeper
2
- class ApplicationsController < ApplicationController
2
+ class ApplicationsController < Doorkeeper::ApplicationController
3
3
  respond_to :html
4
4
 
5
5
  before_filter :authenticate_admin!
@@ -31,5 +31,11 @@ module Doorkeeper
31
31
  flash[:notice] = "Application updated" if @application.update_attributes(params[:application])
32
32
  respond_with @application
33
33
  end
34
+
35
+ def destroy
36
+ @application = Application.find(params[:id])
37
+ flash[:notice] = "Application deleted" if @application.destroy
38
+ redirect_to applications_url
39
+ end
34
40
  end
35
41
  end
@@ -10,6 +10,7 @@ class Doorkeeper::AuthorizationsController < Doorkeeper::ApplicationController
10
10
  elsif authorization.redirect_on_error?
11
11
  redirect_to authorization.invalid_redirect_uri
12
12
  else
13
+ @error = authorization.error_response
13
14
  render :error
14
15
  end
15
16
  end
@@ -20,6 +21,7 @@ class Doorkeeper::AuthorizationsController < Doorkeeper::ApplicationController
20
21
  elsif authorization.redirect_on_error?
21
22
  redirect_to authorization.invalid_redirect_uri
22
23
  else
24
+ @error = authorization.error_response
23
25
  render :error
24
26
  end
25
27
  end
@@ -31,7 +33,15 @@ class Doorkeeper::AuthorizationsController < Doorkeeper::ApplicationController
31
33
 
32
34
  private
33
35
 
36
+ def authorization_params
37
+ params.has_key?(:authorization) ? params[:authorization] : params
38
+ end
39
+
40
+ def client
41
+ @client ||= Doorkeeper::OAuth::Client.find(authorization_params[:client_id])
42
+ end
43
+
34
44
  def authorization
35
- @authorization ||= Doorkeeper::OAuth::AuthorizationRequest.new(current_resource_owner, params)
45
+ @authorization ||= Doorkeeper::OAuth::AuthorizationRequest.new(client, current_resource_owner, authorization_params)
36
46
  end
37
47
  end
@@ -2,11 +2,11 @@ class Doorkeeper::AuthorizedApplicationsController < Doorkeeper::ApplicationCont
2
2
  before_filter :authenticate_resource_owner!
3
3
 
4
4
  def index
5
- @applications = Application.authorized_for(current_resource_owner)
5
+ @applications = Doorkeeper::Application.authorized_for(current_resource_owner)
6
6
  end
7
7
 
8
8
  def destroy
9
- AccessToken.revoke_all_for params[:id], current_resource_owner
10
- redirect_to authorized_applications_path, :notice => "Application revoked."
9
+ Doorkeeper::AccessToken.revoke_all_for params[:id], current_resource_owner
10
+ redirect_to authorized_applications_url, :notice => "Application revoked."
11
11
  end
12
12
  end
@@ -1,7 +1,4 @@
1
1
  class Doorkeeper::TokensController < Doorkeeper::ApplicationController
2
-
3
- before_filter :parse_client_info_from_basic_auth, :only => :create
4
-
5
2
  def create
6
3
  response.headers.merge!({
7
4
  'Pragma' => 'no-cache',
@@ -10,13 +7,30 @@ class Doorkeeper::TokensController < Doorkeeper::ApplicationController
10
7
  if token.authorize
11
8
  render :json => token.authorization
12
9
  else
13
- render :json => token.error_response
10
+ render :json => token.error_response, :status => token.error_response.status
14
11
  end
15
12
  end
16
13
 
17
14
  private
18
15
 
16
+ def client
17
+ @client ||= Doorkeeper::OAuth::Client.authenticate(credentials)
18
+ end
19
+
20
+ def credentials
21
+ methods = Doorkeeper.configuration.client_credentials_methods
22
+ @credentials ||= Doorkeeper::OAuth::Client::Credentials.from_request(request, *methods)
23
+ end
24
+
19
25
  def token
20
- @token ||= Doorkeeper::OAuth::AccessTokenRequest.new(params)
26
+ case params[:grant_type]
27
+ when 'password'
28
+ owner = resource_owner_from_credentials
29
+ @token ||= Doorkeeper::OAuth::PasswordAccessTokenRequest.new(client, owner, params)
30
+ when 'client_credentials'
31
+ @token ||= Doorkeeper::OAuth::ClientCredentialsRequest.new(Doorkeeper.configuration, client, params)
32
+ else
33
+ @token ||= Doorkeeper::OAuth::AccessTokenRequest.new(client, params)
34
+ end
21
35
  end
22
36
  end
@@ -0,0 +1,28 @@
1
+ module Doorkeeper
2
+ class AccessGrant < ActiveRecord::Base
3
+ include Doorkeeper::OAuth::Helpers
4
+ include Doorkeeper::Models::Expirable
5
+ include Doorkeeper::Models::Revocable
6
+ include Doorkeeper::Models::Scopes
7
+
8
+ self.table_name = :oauth_access_grants
9
+
10
+ belongs_to :application
11
+
12
+ attr_accessible :resource_owner_id, :application_id, :expires_in, :redirect_uri, :scopes
13
+
14
+ validates :resource_owner_id, :application_id, :token, :expires_in, :redirect_uri, :presence => true
15
+
16
+ before_validation :generate_token, :on => :create
17
+
18
+ def accessible?
19
+ !expired? && !revoked?
20
+ end
21
+
22
+ private
23
+
24
+ def generate_token
25
+ self.token = UniqueToken.generate_for :token, self.class
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,65 @@
1
+ module Doorkeeper
2
+ class AccessToken < ActiveRecord::Base
3
+ include Doorkeeper::OAuth::Helpers
4
+ include Doorkeeper::Models::Expirable
5
+ include Doorkeeper::Models::Revocable
6
+ include Doorkeeper::Models::Scopes
7
+
8
+ self.table_name = :oauth_access_tokens
9
+
10
+ belongs_to :application
11
+
12
+ scope :accessible, where(:revoked_at => nil)
13
+
14
+ validates :application_id, :token, :presence => true
15
+
16
+ attr_accessor :use_refresh_token
17
+ attr_accessible :application_id, :resource_owner_id, :expires_in, :scopes, :use_refresh_token
18
+
19
+ before_validation :generate_token, :on => :create
20
+ before_validation :generate_refresh_token, :on => :create, :if => :use_refresh_token?
21
+
22
+ def self.revoke_all_for(application_id, resource_owner)
23
+ where(:application_id => application_id,
24
+ :resource_owner_id => resource_owner.id).delete_all
25
+ end
26
+
27
+ def self.matching_token_for(application, resource_owner_or_id, scopes)
28
+ token = last_authorized_token_for(application, resource_owner_or_id)
29
+ token if token && ScopeChecker.matches?(token.scopes, scopes)
30
+ end
31
+
32
+ def self.last_authorized_token_for(application, resource_owner_or_id)
33
+ resource_owner_id = resource_owner_or_id.kind_of?(ActiveRecord::Base) ? resource_owner_or_id.id : resource_owner_or_id
34
+ accessible.
35
+ where(:application_id => application.id,
36
+ :resource_owner_id => resource_owner_id).
37
+ order("created_at desc").
38
+ limit(1).
39
+ first
40
+ end
41
+ private_class_method :last_authorized_token_for
42
+
43
+ def token_type
44
+ "bearer"
45
+ end
46
+
47
+ def accessible?
48
+ !expired? && !revoked?
49
+ end
50
+
51
+ def use_refresh_token?
52
+ self.use_refresh_token
53
+ end
54
+
55
+ private
56
+
57
+ def generate_refresh_token
58
+ self.refresh_token = UniqueToken.generate_for :refresh_token, self.class
59
+ end
60
+
61
+ def generate_token
62
+ self.token = UniqueToken.generate_for :token, self.class
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,54 @@
1
+ module Doorkeeper
2
+ class Application < ActiveRecord::Base
3
+ include Doorkeeper::OAuth::Helpers
4
+
5
+ self.table_name = :oauth_applications
6
+
7
+ has_many :access_grants, :dependent => :destroy
8
+ has_many :access_tokens, :dependent => :destroy
9
+ has_many :authorized_tokens, :class_name => "AccessToken", :conditions => { :revoked_at => nil }
10
+ has_many :authorized_applications, :through => :authorized_tokens, :source => :application
11
+
12
+ validates :name, :secret, :redirect_uri, :presence => true
13
+ validates :uid, :presence => true, :uniqueness => true
14
+ validate :validate_redirect_uri
15
+
16
+ before_validation :generate_uid, :generate_secret, :on => :create
17
+
18
+ attr_accessible :name, :redirect_uri
19
+
20
+ def self.authenticate(uid, secret)
21
+ find_by_uid_and_secret(uid, secret)
22
+ end
23
+
24
+ def self.column_names_with_table
25
+ self.column_names.map { |c| "oauth_applications.#{c}" }
26
+ end
27
+
28
+ def self.authorized_for(resource_owner)
29
+ joins(:authorized_applications).
30
+ where(:oauth_access_tokens => { :resource_owner_id => resource_owner.id }).
31
+ group(column_names_with_table.join(','))
32
+ end
33
+
34
+ def validate_redirect_uri
35
+ return unless redirect_uri
36
+ uri = URI.parse(redirect_uri)
37
+ errors.add(:redirect_uri, "cannot contain a fragment.") unless uri.fragment.nil?
38
+ errors.add(:redirect_uri, "must be an absolute URL.") if uri.scheme.nil? || uri.host.nil?
39
+ errors.add(:redirect_uri, "cannot contain a query parameter.") unless uri.query.nil?
40
+ rescue URI::InvalidURIError => e
41
+ errors.add(:redirect_uri, "must be a valid URI.")
42
+ end
43
+
44
+ private
45
+
46
+ def generate_uid
47
+ self.uid = UniqueToken.generate_for :uid, self.class
48
+ end
49
+
50
+ def generate_secret
51
+ self.secret = UniqueToken.generate_for :secret, self.class
52
+ end
53
+ end
54
+ end
@@ -16,7 +16,7 @@
16
16
  </thead>
17
17
  <tbody>
18
18
  <% @applications.each do |application| %>
19
- <tr>
19
+ <tr id="application_<%= application.id %>">
20
20
  <td><%= link_to application.name, application %></td>
21
21
  <td><%= application.redirect_uri %></td>
22
22
  <td><%= link_to 'Edit', edit_application_path(application) %></td>
@@ -1,6 +1,6 @@
1
1
  <div class="span16">
2
2
  <h2>An error has occurred</h2>
3
3
  <p>
4
- <pre><%= t @authorization.error, :scope => [:doorkeeper, :errors, :messages] %></pre>
4
+ <pre><%= @error.description %></pre>
5
5
  </p>
6
6
  </div>
@@ -9,29 +9,29 @@
9
9
  </p>
10
10
  <ul>
11
11
  <% @authorization.scopes.each do |scope| %>
12
- <li><%= scope.description %></li>
12
+ <li><%= t scope, :scope => [:doorkeeper, :scopes] %></li>
13
13
  <% end %>
14
14
  </ul>
15
15
  <% end %>
16
16
 
17
17
  <div class="inline_block">
18
- <%= form_tag authorization_path do %>
19
- <%= hidden_field_tag :client_id, @authorization.client_id %>
20
- <%= hidden_field_tag :redirect_uri, @authorization.redirect_uri %>
21
- <%= hidden_field_tag :state, @authorization.state %>
22
- <%= hidden_field_tag :response_type, @authorization.response_type %>
23
- <%= hidden_field_tag :scope, @authorization.scope %>
24
- <%= submit_tag "Authorize", :class => "btn success" %> or
18
+ <%= form_for @authorization, :as => :authorization, :url => authorization_path, :method => :post do |f| %>
19
+ <%= f.hidden_field :client_id %>
20
+ <%= f.hidden_field :redirect_uri %>
21
+ <%= f.hidden_field :state %>
22
+ <%= f.hidden_field :response_type %>
23
+ <%= f.hidden_field :scope %>
24
+ <%= f.submit "Authorize", :class => "btn success" %> or
25
25
  <% end %>
26
26
  </div>
27
27
  <div class="inline_block">
28
- <%= form_tag authorization_path, :method => :delete do %>
29
- <%= hidden_field_tag :client_id, @authorization.client_id %>
30
- <%= hidden_field_tag :redirect_uri, @authorization.redirect_uri %>
31
- <%= hidden_field_tag :state, @authorization.state %>
32
- <%= hidden_field_tag :response_type, @authorization.response_type %>
33
- <%= hidden_field_tag :scope, @authorization.scope %>
34
- <%= button_tag "Deny", :class => "btn" %>
28
+ <%= form_for @authorization, :as => :authorization, :url => authorization_path, :method => :delete do |f| %>
29
+ <%= f.hidden_field :client_id %>
30
+ <%= f.hidden_field :redirect_uri %>
31
+ <%= f.hidden_field :state %>
32
+ <%= f.hidden_field :response_type %>
33
+ <%= f.hidden_field :scope %>
34
+ <%= f.submit "Deny", :class => "btn" %>
35
35
  <% end %>
36
36
  </div>
37
37
  </div>
@@ -15,12 +15,11 @@
15
15
  <tbody>
16
16
  <% @applications.each do |application| %>
17
17
  <tr>
18
- <td><%= link_to application.name, application %></td>
18
+ <td><%= application.name %></td>
19
19
  <td><%= application.created_at %></td>
20
20
  <td><%= link_to 'Revoke', authorized_application_path(application), :confirm => 'Are you sure?', :method => :delete, :class => 'btn danger' %></td>
21
21
  </tr>
22
22
  <% end %>
23
23
  </tbody>
24
24
  </table>
25
-
26
25
  </div>
@@ -18,3 +18,6 @@ en:
18
18
  invalid_client: 'Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method.'
19
19
  invalid_grant: 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.'
20
20
  unsupported_grant_type: 'The authorization grant type is not supported by the authorization server.'
21
+
22
+ # Password Access token errors
23
+ invalid_resource_owner: 'The provided resource owner credentials are not valid, or resource owner cannot be found'
@@ -0,0 +1,28 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ require "doorkeeper/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "doorkeeper"
7
+ s.version = Doorkeeper::VERSION
8
+ s.authors = ["Felipe Elias Philipp", "Piotr Jakubowski"]
9
+ s.email = ["felipe@applicake.com", "piotr.jakubowski@applicake.com"]
10
+ s.homepage = "https://github.com/applicake/doorkeeper"
11
+ s.summary = "Doorkeeper is an OAuth 2 provider for Rails."
12
+ s.description = "Doorkeeper is an OAuth 2 provider for Rails."
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- test/*`.split("\n")
16
+ s.require_paths = ["lib"]
17
+
18
+ s.add_dependency "railties", "~> 3.1"
19
+
20
+ s.add_development_dependency "sqlite3", "~> 1.3.5"
21
+ s.add_development_dependency "rspec-rails", "~> 2.10.0"
22
+ s.add_development_dependency "capybara", "~> 1.1.2"
23
+ s.add_development_dependency "generator_spec", "~> 0.8.5"
24
+ s.add_development_dependency "factory_girl", "~> 2.6.4"
25
+ s.add_development_dependency "timecop", "~> 0.3.5"
26
+ s.add_development_dependency "database_cleaner", "~> 0.7.1"
27
+ s.add_development_dependency "bcrypt-ruby", "~> 3.0.1"
28
+ end
@@ -0,0 +1,7 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rails', '~> 3.1.0'
4
+ gem 'jquery-rails'
5
+ gem 'doorkeeper', :path => '../'
6
+
7
+ gemspec :path => '../'