devise_oauth 2.0.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/.gitignore +7 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +17 -0
  4. data/Gemfile.lock +136 -0
  5. data/README.md +77 -0
  6. data/app/controllers/{oauth → devise/oauth}/access_tokens_controller.rb +0 -0
  7. data/app/controllers/{oauth → devise/oauth}/accesses_controller.rb +0 -0
  8. data/app/controllers/{oauth → devise/oauth}/authorizations_controller.rb +0 -0
  9. data/app/controllers/{oauth → devise/oauth}/clients_controller.rb +0 -0
  10. data/app/models/{oauth → devise/oauth}/access.rb +0 -0
  11. data/app/models/{oauth → devise/oauth}/access_token.rb +0 -0
  12. data/app/models/{oauth → devise/oauth}/authorization.rb +0 -0
  13. data/app/models/{oauth → devise/oauth}/client.rb +0 -0
  14. data/devise_oauth.gemspec +27 -0
  15. data/lib/devise/oauth/engine.rb +7 -2
  16. data/lib/devise/oauth/version.rb +1 -1
  17. data/script/rails +8 -0
  18. data/spec/controllers/access_tokens_controller_spec.rb +208 -0
  19. data/spec/controllers/authorizations_controller_spec.rb +53 -0
  20. data/spec/controllers/protected_resources_controller_spec.rb +79 -0
  21. data/spec/dummy/README.rdoc +261 -0
  22. data/spec/dummy/Rakefile +7 -0
  23. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  24. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  25. data/spec/dummy/app/controllers/application_controller.rb +7 -0
  26. data/spec/dummy/app/controllers/protected_resources_controller.rb +14 -0
  27. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  28. data/spec/dummy/app/mailers/.gitkeep +0 -0
  29. data/spec/dummy/app/models/.gitkeep +0 -0
  30. data/spec/dummy/app/models/ability.rb +15 -0
  31. data/spec/dummy/app/models/user.rb +13 -0
  32. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  33. data/spec/dummy/config.ru +4 -0
  34. data/spec/dummy/config/application.rb +67 -0
  35. data/spec/dummy/config/boot.rb +10 -0
  36. data/spec/dummy/config/database.yml +25 -0
  37. data/spec/dummy/config/environment.rb +5 -0
  38. data/spec/dummy/config/environments/development.rb +37 -0
  39. data/spec/dummy/config/environments/production.rb +67 -0
  40. data/spec/dummy/config/environments/test.rb +37 -0
  41. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  42. data/spec/dummy/config/initializers/devise.rb +216 -0
  43. data/spec/dummy/config/initializers/inflections.rb +15 -0
  44. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  45. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  46. data/spec/dummy/config/initializers/session_store.rb +8 -0
  47. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  48. data/spec/dummy/config/locales/devise.en.yml +57 -0
  49. data/spec/dummy/config/locales/en.yml +5 -0
  50. data/spec/dummy/config/routes.rb +7 -0
  51. data/spec/dummy/db/migrate/20120622183848_devise_create_users.rb +46 -0
  52. data/spec/dummy/db/schema.rb +34 -0
  53. data/spec/dummy/lib/assets/.gitkeep +0 -0
  54. data/spec/dummy/log/.gitkeep +0 -0
  55. data/spec/dummy/public/404.html +26 -0
  56. data/spec/dummy/public/422.html +26 -0
  57. data/spec/dummy/public/500.html +25 -0
  58. data/spec/dummy/public/favicon.ico +0 -0
  59. data/spec/dummy/script/rails +6 -0
  60. data/spec/factories.rb +34 -0
  61. data/spec/models/oauth/access_token_spec.rb +25 -0
  62. data/spec/models/oauth/authorization_spec.rb +19 -0
  63. data/spec/models/oauth/client_spec.rb +31 -0
  64. data/spec/models/user_spec.rb +10 -0
  65. data/spec/spec_helper.rb +39 -0
  66. data/spec/support/match_json.rb +6 -0
  67. metadata +134 -30
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ spec/dummy/db/*.sqlite3
5
+ spec/dummy/log/*.log
6
+ spec/dummy/tmp/
7
+ spec/dummy/.sass-cache
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Declare your gem's dependencies in devise_oauth.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
7
+
8
+ # jquery-rails is used by the dummy application
9
+ gem 'jquery-rails'
10
+ gem 'devise'
11
+
12
+ gem 'database_cleaner'
13
+ gem 'factory_girl_rails'
14
+ gem 'rspec-rails', '>= 2.0'
15
+ gem 'shoulda-matchers'
16
+
17
+ gem 'cancan'
data/Gemfile.lock ADDED
@@ -0,0 +1,136 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ devise_oauth (2.0.1)
5
+ devise (>= 2.1)
6
+ rails (>= 3.2.0)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ actionmailer (3.2.6)
12
+ actionpack (= 3.2.6)
13
+ mail (~> 2.4.4)
14
+ actionpack (3.2.6)
15
+ activemodel (= 3.2.6)
16
+ activesupport (= 3.2.6)
17
+ builder (~> 3.0.0)
18
+ erubis (~> 2.7.0)
19
+ journey (~> 1.0.1)
20
+ rack (~> 1.4.0)
21
+ rack-cache (~> 1.2)
22
+ rack-test (~> 0.6.1)
23
+ sprockets (~> 2.1.3)
24
+ activemodel (3.2.6)
25
+ activesupport (= 3.2.6)
26
+ builder (~> 3.0.0)
27
+ activerecord (3.2.6)
28
+ activemodel (= 3.2.6)
29
+ activesupport (= 3.2.6)
30
+ arel (~> 3.0.2)
31
+ tzinfo (~> 0.3.29)
32
+ activeresource (3.2.6)
33
+ activemodel (= 3.2.6)
34
+ activesupport (= 3.2.6)
35
+ activesupport (3.2.6)
36
+ i18n (~> 0.6)
37
+ multi_json (~> 1.0)
38
+ arel (3.0.2)
39
+ bcrypt-ruby (3.0.1)
40
+ builder (3.0.0)
41
+ cancan (1.6.7)
42
+ database_cleaner (0.8.0)
43
+ devise (2.1.0)
44
+ bcrypt-ruby (~> 3.0)
45
+ orm_adapter (~> 0.0.7)
46
+ railties (~> 3.1)
47
+ warden (~> 1.1.1)
48
+ diff-lcs (1.1.3)
49
+ erubis (2.7.0)
50
+ factory_girl (3.4.0)
51
+ activesupport (>= 3.0.0)
52
+ factory_girl_rails (3.4.0)
53
+ factory_girl (~> 3.4.0)
54
+ railties (>= 3.0.0)
55
+ hike (1.2.1)
56
+ i18n (0.6.0)
57
+ journey (1.0.4)
58
+ jquery-rails (2.0.2)
59
+ railties (>= 3.2.0, < 5.0)
60
+ thor (~> 0.14)
61
+ json (1.7.3)
62
+ mail (2.4.4)
63
+ i18n (>= 0.4.0)
64
+ mime-types (~> 1.16)
65
+ treetop (~> 1.4.8)
66
+ mime-types (1.19)
67
+ multi_json (1.3.6)
68
+ orm_adapter (0.0.7)
69
+ polyglot (0.3.3)
70
+ rack (1.4.1)
71
+ rack-cache (1.2)
72
+ rack (>= 0.4)
73
+ rack-ssl (1.3.2)
74
+ rack
75
+ rack-test (0.6.1)
76
+ rack (>= 1.0)
77
+ rails (3.2.6)
78
+ actionmailer (= 3.2.6)
79
+ actionpack (= 3.2.6)
80
+ activerecord (= 3.2.6)
81
+ activeresource (= 3.2.6)
82
+ activesupport (= 3.2.6)
83
+ bundler (~> 1.0)
84
+ railties (= 3.2.6)
85
+ railties (3.2.6)
86
+ actionpack (= 3.2.6)
87
+ activesupport (= 3.2.6)
88
+ rack-ssl (~> 1.3.2)
89
+ rake (>= 0.8.7)
90
+ rdoc (~> 3.4)
91
+ thor (>= 0.14.6, < 2.0)
92
+ rake (0.9.2.2)
93
+ rdoc (3.12)
94
+ json (~> 1.4)
95
+ rspec (2.10.0)
96
+ rspec-core (~> 2.10.0)
97
+ rspec-expectations (~> 2.10.0)
98
+ rspec-mocks (~> 2.10.0)
99
+ rspec-core (2.10.1)
100
+ rspec-expectations (2.10.0)
101
+ diff-lcs (~> 1.1.3)
102
+ rspec-mocks (2.10.1)
103
+ rspec-rails (2.10.1)
104
+ actionpack (>= 3.0)
105
+ activesupport (>= 3.0)
106
+ railties (>= 3.0)
107
+ rspec (~> 2.10.0)
108
+ shoulda-matchers (1.2.0)
109
+ activesupport (>= 3.0.0)
110
+ sprockets (2.1.3)
111
+ hike (~> 1.2)
112
+ rack (~> 1.0)
113
+ tilt (~> 1.1, != 1.3.0)
114
+ sqlite3 (1.3.6)
115
+ thor (0.15.3)
116
+ tilt (1.3.3)
117
+ treetop (1.4.10)
118
+ polyglot
119
+ polyglot (>= 0.3.1)
120
+ tzinfo (0.3.33)
121
+ warden (1.1.1)
122
+ rack (>= 1.0)
123
+
124
+ PLATFORMS
125
+ ruby
126
+
127
+ DEPENDENCIES
128
+ cancan
129
+ database_cleaner
130
+ devise
131
+ devise_oauth!
132
+ factory_girl_rails
133
+ jquery-rails
134
+ rspec-rails (>= 2.0)
135
+ shoulda-matchers
136
+ sqlite3
data/README.md CHANGED
@@ -1,3 +1,80 @@
1
1
  # Devise::Oauth
2
2
 
3
+ ## Installation
4
+
5
+ Add it to your Gemfile
6
+
7
+ ```ruby
8
+ gem 'devise_oauth'
9
+ ```
10
+
11
+ Mount engine in your routes.rb file
12
+
13
+ ```ruby
14
+ mount Devise::Oauth::Engine => '/oauth'
15
+ ```
16
+
17
+ Define possible scopes in your application.rb
18
+
19
+ ```ruby
20
+ Devise::Oauth.scopes = [:read, :write]
21
+ ```
22
+
23
+ Add strategies to your User model
24
+
25
+ ```ruby
26
+ class User < ActiveRecord::Base
27
+ devise :database_authenticatable,
28
+ #:registerable,
29
+ #:recoverable,
30
+ #:rememberable,
31
+ #:trackable,
32
+ #:omniauthable,
33
+
34
+ # OAuth provider
35
+ :access_token_authenticatable,
36
+ :client_ownable,
37
+ :resource_ownable
38
+ ```
39
+
40
+ Create migration [TODO: write generator]
41
+
42
+ look at `db/migrate/20120622164619_devise_create_oauth.rb` for now
43
+
44
+ ## CanCan support
45
+
46
+ if your app is accessed with `access_token` then we set it as `oauth_token` to current_user
47
+
48
+ ```ruby
49
+ class Ability
50
+ include CanCan::Ability
51
+
52
+ def initialize(user)
53
+ user ||= User.new # guest user (not logged in)
54
+ if user.oauth_token?
55
+ # has access_token, so we set access rights with scope
56
+ setup_client(user)
57
+ else
58
+ # normal user access rights setup
59
+ setup(user)
60
+ end
61
+
62
+ # See the wiki for details: https://github.com/ryanb/cancan/wiki/Defining-Abilities
63
+ end
64
+
65
+ private
66
+
67
+ def setup_client(user)
68
+ if user.oauth_scope? :write
69
+ can :create, :protected_resource
70
+ end
71
+ end
72
+
73
+ def setup(user)
74
+
75
+ end
76
+ end
77
+ ```
78
+
79
+
3
80
  This project rocks and uses MIT-LICENSE.
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,27 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ require "devise/oauth/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "devise_oauth"
7
+ s.version = Devise::Oauth::VERSION
8
+ s.authors = ["Yury Korolev"]
9
+ s.email = ["yury.korolev@gmail.com"]
10
+ s.homepage = "https://github.com/anjlab/devise_oauth"
11
+ s.summary = "Oauth 2.0 provider implementation on top of devise."
12
+ s.description = "The OAuth 2.0 Authorization Framework draft-ietf-oauth-v2-28 implementation on top of devise."
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_dependency "rails", ">= 3.2.0"
20
+ s.add_dependency "devise", ">= 2.1"
21
+
22
+ s.add_development_dependency "sqlite3"
23
+ s.add_development_dependency "factory_girl_rails"
24
+ s.add_development_dependency "rspec-rails", ">= 2.0"
25
+ s.add_development_dependency "database_cleaner"
26
+ s.add_development_dependency "shoulda-matchers"
27
+ end
@@ -1,13 +1,18 @@
1
1
  module Devise::Oauth
2
2
  class Engine < ::Rails::Engine
3
+
4
+ NAME = "oauth"
5
+
3
6
  def table_name_prefix
4
- "oauth"
7
+ NAME
5
8
  end
6
9
 
7
10
  def self.generate_railtie_name(mod)
8
- "oauth"
11
+ NAME
9
12
  end
10
13
 
14
+ engine_name NAME
15
+
11
16
  isolate_namespace Devise::Oauth
12
17
 
13
18
  initializer "devise_oauth.initialize_application", before: :load_config_initializers do |app|
@@ -1,5 +1,5 @@
1
1
  module Devise
2
2
  module Oauth
3
- VERSION = "2.0.0"
3
+ VERSION = "2.0.1"
4
4
  end
5
5
  end
data/script/rails ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
5
+ ENGINE_PATH = File.expand_path('../../lib/devise/oauth/engine', __FILE__)
6
+
7
+ require 'rails/all'
8
+ require 'rails/engine/commands'
@@ -0,0 +1,208 @@
1
+ require 'spec_helper'
2
+
3
+ shared_examples "client is blocked flow" do
4
+ before do
5
+ client.block!
6
+ post :create, attributes
7
+ end
8
+
9
+ it { should respond_with :unprocessable_entity }
10
+ it { should respond_with_content_type :json }
11
+ it "should have error 'invalid_request'" do
12
+ res = JSON.load(response.body)
13
+ res['error'].should == "invalid_request"
14
+ res['error_description'].should == "Client Blocked"
15
+ end
16
+ end
17
+
18
+ shared_examples "access is blocked (resource owner block a client) flow" do
19
+ before do
20
+ access.block!
21
+ post :create, attributes
22
+ end
23
+ it { should respond_with :unprocessable_entity }
24
+ it { should respond_with_content_type :json }
25
+ end
26
+
27
+ shared_examples "invalid client_id flow" do
28
+ before do
29
+ attributes.merge!(client_id: "not_existing")
30
+ post :create, attributes
31
+ end
32
+
33
+ it { should respond_with :unprocessable_entity }
34
+ it { should respond_with_content_type :json }
35
+
36
+ it "should have error 'invalid_request'" do
37
+ res = JSON.load(response.body)
38
+ res['error'].should == "invalid_request"
39
+ res['error_description'].should == "Client not found"
40
+ end
41
+ end
42
+
43
+ describe Devise::Oauth::AccessTokensController do
44
+ before(:each) {
45
+ @routes = Devise::Oauth::Engine.routes
46
+ @user = create(:user)
47
+ @client = create(:client)
48
+ @authorization = create(:authorization, client: @client, resource_owner: @user)
49
+ @access = create(:access, client: @client, resource_owner: @user)
50
+ }
51
+
52
+ let(:user) { @user }
53
+ let(:client) { @client }
54
+ let(:authorization) { @authorization }
55
+ let(:access) { @access}
56
+
57
+ context "Authorization code" do
58
+ let(:attributes) {
59
+ {
60
+ grant_type: "authorization_code",
61
+ client_id: client.identifier,
62
+ client_secret: client.secret,
63
+ code: authorization.code,
64
+ redirect_uri: client.redirect_uris.first
65
+ }
66
+ }
67
+
68
+ context "main flow" do
69
+ before do
70
+ post :create, attributes
71
+ end
72
+ let (:access_token) { @access_token = Devise::Oauth::AccessToken.last }
73
+
74
+ it { should respond_with :ok }
75
+ it { should respond_with_content_type :json }
76
+ it "should create new access token" do
77
+ access_token.should be_present
78
+ end
79
+
80
+ it "has valid access token in response" do
81
+ response.body.should match_json(access_token.token_response)
82
+ end
83
+ end
84
+
85
+ context "not valid code flow" do
86
+ before do
87
+ attributes.merge!(code: "not_existing")
88
+ post :create, attributes
89
+ end
90
+
91
+ it { should respond_with :unprocessable_entity }
92
+ it { should respond_with_content_type :json }
93
+ it "should have error 'invalid_request'" do
94
+ res = JSON.load(response.body)
95
+ res['error'].should == "invalid_request"
96
+ res['error_description'].should == "Authorization not found"
97
+ end
98
+ end
99
+
100
+ context "authorization is expired flow" do
101
+ before do
102
+ authorization.expire!
103
+ post :create, attributes
104
+ end
105
+
106
+ it { should respond_with :unprocessable_entity }
107
+ it { should respond_with_content_type :json }
108
+
109
+ it "should have error 'invalid_request'" do
110
+ res = JSON.load(response.body)
111
+ res['error'].should == "invalid_request"
112
+ res['error_description'].should == 'Authorization expired'
113
+ end
114
+ end
115
+
116
+ it_behaves_like "client is blocked flow"
117
+ it_behaves_like "access is blocked (resource owner block a client) flow"
118
+ it_behaves_like "invalid client_id flow"
119
+ end
120
+
121
+ context "Password credentials" do
122
+ let(:attributes) {
123
+ {
124
+ grant_type: "password",
125
+ client_id: client.identifier,
126
+ client_secret: client.secret,
127
+ username: user.email,
128
+ password: user.password,
129
+ scope: ""
130
+ }
131
+ }
132
+
133
+ context "main flow" do
134
+ before do
135
+ post :create, attributes
136
+ end
137
+ let (:access_token) { @access_token = Devise::Oauth::AccessToken.last }
138
+
139
+ it { should respond_with :ok }
140
+ it { should respond_with_content_type :json }
141
+ it "should create new access token" do
142
+ access_token.should be_present
143
+ end
144
+
145
+ it "has valid access token in response" do
146
+ response.body.should match_json(access_token.token_response)
147
+ end
148
+ end
149
+
150
+ context "not valid user password flow" do
151
+ before do
152
+ attributes.merge!(password: "not_existing")
153
+ post :create, attributes
154
+ end
155
+ ## TODO: bad request? or may be unauthorized?
156
+ it { should respond_with :bad_request }
157
+ it { should respond_with_content_type :json }
158
+ end
159
+
160
+ it_behaves_like "client is blocked flow"
161
+ it_behaves_like "access is blocked (resource owner block a client) flow"
162
+ it_behaves_like "invalid client_id flow"
163
+ end
164
+
165
+ context "Refresh Token" do
166
+ let(:token) { create(:access_token, resource_owner: user, client: client) }
167
+
168
+ let(:attributes) {
169
+ {
170
+ grant_type: "refresh_token",
171
+ refresh_token: token.refresh_token,
172
+ client_id: client.identifier,
173
+ client_secret: client.secret
174
+ }
175
+ }
176
+
177
+ context "main flow" do
178
+ before do
179
+ post :create, attributes
180
+ end
181
+ let (:access_token) { @access_token = Devise::Oauth::AccessToken.last }
182
+
183
+ it { should respond_with :ok }
184
+ it { should respond_with_content_type :json }
185
+ it "should create new access token" do
186
+ access_token.should be_present
187
+ end
188
+
189
+ it "has valid access token in response" do
190
+ response.body.should match_json(access_token.token_response)
191
+ end
192
+ end
193
+
194
+ context "no valid refresh token flow" do
195
+ before do
196
+ attributes.merge!(refresh_token: "not_existing")
197
+ post :create, attributes
198
+ end
199
+ it { should respond_with :bad_request }
200
+ it { should respond_with_content_type :json }
201
+ # page.should have_content "Refresh token not found"
202
+ end
203
+
204
+ it_behaves_like "client is blocked flow"
205
+ it_behaves_like "access is blocked (resource owner block a client) flow"
206
+ it_behaves_like "invalid client_id flow"
207
+ end
208
+ end