grape_oauth2 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +11 -11
  3. data/Gemfile +23 -23
  4. data/Rakefile +11 -11
  5. data/grape_oauth2.gemspec +26 -27
  6. data/lib/grape_oauth2.rb +129 -129
  7. data/lib/grape_oauth2/configuration.rb +143 -143
  8. data/lib/grape_oauth2/configuration/class_accessors.rb +36 -36
  9. data/lib/grape_oauth2/configuration/validation.rb +71 -71
  10. data/lib/grape_oauth2/endpoints/authorize.rb +34 -34
  11. data/lib/grape_oauth2/endpoints/token.rb +72 -72
  12. data/lib/grape_oauth2/gem_version.rb +24 -24
  13. data/lib/grape_oauth2/generators/authorization.rb +44 -44
  14. data/lib/grape_oauth2/generators/base.rb +26 -26
  15. data/lib/grape_oauth2/generators/token.rb +62 -62
  16. data/lib/grape_oauth2/helpers/access_token_helpers.rb +52 -54
  17. data/lib/grape_oauth2/helpers/oauth_params.rb +41 -41
  18. data/lib/grape_oauth2/mixins/active_record/access_grant.rb +47 -47
  19. data/lib/grape_oauth2/mixins/active_record/access_token.rb +75 -75
  20. data/lib/grape_oauth2/mixins/active_record/client.rb +36 -35
  21. data/lib/grape_oauth2/mixins/mongoid/access_grant.rb +58 -58
  22. data/lib/grape_oauth2/mixins/mongoid/access_token.rb +88 -88
  23. data/lib/grape_oauth2/mixins/mongoid/client.rb +44 -41
  24. data/lib/grape_oauth2/mixins/sequel/access_grant.rb +68 -68
  25. data/lib/grape_oauth2/mixins/sequel/access_token.rb +86 -86
  26. data/lib/grape_oauth2/mixins/sequel/client.rb +54 -46
  27. data/lib/grape_oauth2/responses/authorization.rb +11 -10
  28. data/lib/grape_oauth2/responses/base.rb +56 -56
  29. data/lib/grape_oauth2/responses/token.rb +10 -10
  30. data/lib/grape_oauth2/scopes.rb +74 -74
  31. data/lib/grape_oauth2/strategies/authorization_code.rb +38 -38
  32. data/lib/grape_oauth2/strategies/base.rb +47 -47
  33. data/lib/grape_oauth2/strategies/client_credentials.rb +20 -20
  34. data/lib/grape_oauth2/strategies/password.rb +22 -22
  35. data/lib/grape_oauth2/strategies/refresh_token.rb +47 -47
  36. data/lib/grape_oauth2/unique_token.rb +20 -20
  37. data/lib/grape_oauth2/version.rb +14 -14
  38. data/spec/configuration/config_spec.rb +231 -231
  39. data/spec/configuration/version_spec.rb +12 -12
  40. data/spec/dummy/endpoints/custom_authorization.rb +25 -25
  41. data/spec/dummy/endpoints/custom_token.rb +35 -35
  42. data/spec/dummy/endpoints/status.rb +25 -25
  43. data/spec/dummy/grape_oauth2_config.rb +11 -11
  44. data/spec/dummy/orm/active_record/app/config/db.rb +7 -7
  45. data/spec/dummy/orm/active_record/app/models/access_code.rb +3 -3
  46. data/spec/dummy/orm/active_record/app/models/access_token.rb +3 -3
  47. data/spec/dummy/orm/active_record/app/models/application.rb +3 -3
  48. data/spec/dummy/orm/active_record/app/models/application_record.rb +3 -3
  49. data/spec/dummy/orm/active_record/app/models/user.rb +10 -10
  50. data/spec/dummy/orm/active_record/app/twitter.rb +36 -36
  51. data/spec/dummy/orm/active_record/config.ru +7 -7
  52. data/spec/dummy/orm/active_record/db/schema.rb +53 -53
  53. data/spec/dummy/orm/mongoid/app/config/db.rb +6 -6
  54. data/spec/dummy/orm/mongoid/app/config/mongoid.yml +21 -21
  55. data/spec/dummy/orm/mongoid/app/models/access_code.rb +3 -3
  56. data/spec/dummy/orm/mongoid/app/models/access_token.rb +3 -3
  57. data/spec/dummy/orm/mongoid/app/models/application.rb +3 -3
  58. data/spec/dummy/orm/mongoid/app/models/user.rb +11 -11
  59. data/spec/dummy/orm/mongoid/app/twitter.rb +34 -34
  60. data/spec/dummy/orm/mongoid/config.ru +5 -5
  61. data/spec/dummy/orm/sequel/app/config/db.rb +1 -1
  62. data/spec/dummy/orm/sequel/app/models/access_code.rb +4 -4
  63. data/spec/dummy/orm/sequel/app/models/access_token.rb +4 -4
  64. data/spec/dummy/orm/sequel/app/models/application.rb +4 -4
  65. data/spec/dummy/orm/sequel/app/models/application_record.rb +2 -2
  66. data/spec/dummy/orm/sequel/app/models/user.rb +11 -11
  67. data/spec/dummy/orm/sequel/app/twitter.rb +47 -47
  68. data/spec/dummy/orm/sequel/config.ru +5 -5
  69. data/spec/dummy/orm/sequel/db/schema.rb +50 -50
  70. data/spec/lib/scopes_spec.rb +50 -50
  71. data/spec/mixins/active_record/access_token_spec.rb +185 -185
  72. data/spec/mixins/active_record/client_spec.rb +104 -95
  73. data/spec/mixins/mongoid/access_token_spec.rb +185 -185
  74. data/spec/mixins/mongoid/client_spec.rb +104 -95
  75. data/spec/mixins/sequel/access_token_spec.rb +185 -185
  76. data/spec/mixins/sequel/client_spec.rb +105 -96
  77. data/spec/requests/flows/authorization_code_spec.rb +67 -67
  78. data/spec/requests/flows/client_credentials_spec.rb +101 -101
  79. data/spec/requests/flows/password_spec.rb +210 -210
  80. data/spec/requests/flows/refresh_token_spec.rb +222 -222
  81. data/spec/requests/flows/revoke_token_spec.rb +103 -103
  82. data/spec/requests/protected_resources_spec.rb +64 -64
  83. data/spec/spec_helper.rb +60 -60
  84. data/spec/support/api_helper.rb +11 -11
  85. metadata +50 -52
  86. data/.rspec +0 -2
  87. data/.rubocop.yml +0 -18
  88. data/.travis.yml +0 -42
  89. data/README.md +0 -820
  90. data/gemfiles/active_record.rb +0 -25
  91. data/gemfiles/mongoid.rb +0 -14
  92. data/gemfiles/sequel.rb +0 -24
  93. data/grape_oauth2.png +0 -0
@@ -1,103 +1,103 @@
1
- require 'spec_helper'
2
-
3
- describe 'Token Endpoint' do
4
- describe 'POST /oauth/revoke' do
5
- describe 'Revoke Token flow' do
6
- context 'with valid params' do
7
- let(:api_url) { '/api/v1/oauth/revoke' }
8
- let(:application) { Application.create(name: 'App1') }
9
- let(:user) { User.create(username: 'test', password: '12345678') }
10
-
11
- let(:headers) { { 'HTTP_AUTHORIZATION' => ('Basic ' + Base64::encode64("#{application.key}:#{application.secret}")) } }
12
-
13
- describe 'for public token' do
14
- context 'when request is invalid' do
15
- before { AccessToken.create_for(application, user) }
16
-
17
- it 'does nothing' do
18
- expect {
19
- post api_url, { token: 'invalid token' }, headers
20
- }.not_to change { AccessToken.count }
21
-
22
- expect(json_body).to eq({})
23
- expect(last_response.status).to eq 200
24
-
25
- expect(AccessToken.last).not_to be_revoked
26
- end
27
-
28
- it 'returns an error with invalid token_type_hint' do
29
- expect {
30
- post api_url, { token: AccessToken.last.token, token_type_hint: 'undefined' }, headers
31
- }.not_to change { AccessToken.count }
32
-
33
- expect(last_response.status).to eq 400
34
- end
35
- end
36
-
37
- context 'with valid data' do
38
- # Token doesn't belongs to anybody
39
- before { AccessToken.create_for(nil, nil) }
40
-
41
- it 'revokes Access Token by its token' do
42
- expect {
43
- post api_url, { token: AccessToken.last.token }, headers
44
- }.to change { AccessToken.where(revoked_at: nil).count }.from(1).to(0)
45
-
46
- expect(json_body).to eq({})
47
- expect(last_response.status).to eq 200
48
-
49
- expect(AccessToken.last).to be_revoked
50
- end
51
-
52
- it 'revokes Access Token by its refresh token' do
53
- refresh_token = SecureRandom.hex(16)
54
- AccessToken.last.update(refresh_token: refresh_token)
55
-
56
- expect {
57
- post api_url, { token: refresh_token, token_type_hint: 'refresh_token' }, headers
58
- }.to change { AccessToken.where(revoked_at: nil).count }.from(1).to(0)
59
-
60
- expect(json_body).to eq({})
61
- expect(last_response.status).to eq 200
62
-
63
- expect(AccessToken.last).to be_revoked
64
- end
65
- end
66
- end
67
-
68
- describe 'for private token' do
69
- before { AccessToken.create_for(application, user) }
70
-
71
- context 'with valid data' do
72
- it 'revokes token with client authorization' do
73
- expect {
74
- post api_url, { token: AccessToken.last.token}, headers
75
- }.to change { AccessToken.where(revoked_at: nil).count }.from(1).to(0)
76
- end
77
- end
78
-
79
- context 'with invalid data' do
80
- it 'does not revokes Access Token when credentials is invalid' do
81
- expect {
82
- post api_url, token: AccessToken.last.token
83
- }.to_not change { AccessToken.where(revoked_at: nil).count }
84
-
85
- expect(json_body[:error]).to eq('invalid_client')
86
- end
87
-
88
- it 'does not revokes Access Token when token was issued to another client' do
89
- another_client = Application.create(name: 'Some')
90
- AccessToken.last.update(client_id: another_client.id)
91
-
92
- expect {
93
- post api_url, token: AccessToken.last.token
94
- }.to_not change { AccessToken.where(revoked_at: nil).count }
95
-
96
- expect(json_body[:error]).to eq('invalid_client')
97
- end
98
- end
99
- end
100
- end
101
- end
102
- end
103
- end
1
+ require 'spec_helper'
2
+
3
+ describe 'Token Endpoint' do
4
+ describe 'POST /oauth/revoke' do
5
+ describe 'Revoke Token flow' do
6
+ context 'with valid params' do
7
+ let(:api_url) { '/api/v1/oauth/revoke' }
8
+ let(:application) { Application.create(name: 'App1') }
9
+ let(:user) { User.create(username: 'test', password: '12345678') }
10
+
11
+ let(:headers) { { 'HTTP_AUTHORIZATION' => ('Basic ' + Base64::encode64("#{application.key}:#{application.secret}")) } }
12
+
13
+ describe 'for public token' do
14
+ context 'when request is invalid' do
15
+ before { AccessToken.create_for(application, user) }
16
+
17
+ it 'does nothing' do
18
+ expect {
19
+ post api_url, { token: 'invalid token' }, headers
20
+ }.not_to change { AccessToken.count }
21
+
22
+ expect(json_body).to eq({})
23
+ expect(last_response.status).to eq 200
24
+
25
+ expect(AccessToken.last).not_to be_revoked
26
+ end
27
+
28
+ it 'returns an error with invalid token_type_hint' do
29
+ expect {
30
+ post api_url, { token: AccessToken.last.token, token_type_hint: 'undefined' }, headers
31
+ }.not_to change { AccessToken.count }
32
+
33
+ expect(last_response.status).to eq 400
34
+ end
35
+ end
36
+
37
+ context 'with valid data' do
38
+ # Token doesn't belongs to anybody
39
+ before { AccessToken.create_for(nil, nil) }
40
+
41
+ it 'revokes Access Token by its token' do
42
+ expect {
43
+ post api_url, { token: AccessToken.last.token }, headers
44
+ }.to change { AccessToken.where(revoked_at: nil).count }.from(1).to(0)
45
+
46
+ expect(json_body).to eq({})
47
+ expect(last_response.status).to eq 200
48
+
49
+ expect(AccessToken.last).to be_revoked
50
+ end
51
+
52
+ it 'revokes Access Token by its refresh token' do
53
+ refresh_token = SecureRandom.hex(16)
54
+ AccessToken.last.update(refresh_token: refresh_token)
55
+
56
+ expect {
57
+ post api_url, { token: refresh_token, token_type_hint: 'refresh_token' }, headers
58
+ }.to change { AccessToken.where(revoked_at: nil).count }.from(1).to(0)
59
+
60
+ expect(json_body).to eq({})
61
+ expect(last_response.status).to eq 200
62
+
63
+ expect(AccessToken.last).to be_revoked
64
+ end
65
+ end
66
+ end
67
+
68
+ describe 'for private token' do
69
+ before { AccessToken.create_for(application, user) }
70
+
71
+ context 'with valid data' do
72
+ it 'revokes token with client authorization' do
73
+ expect {
74
+ post api_url, { token: AccessToken.last.token}, headers
75
+ }.to change { AccessToken.where(revoked_at: nil).count }.from(1).to(0)
76
+ end
77
+ end
78
+
79
+ context 'with invalid data' do
80
+ it 'does not revokes Access Token when credentials is invalid' do
81
+ expect {
82
+ post api_url, token: AccessToken.last.token
83
+ }.to_not change { AccessToken.where(revoked_at: nil).count }
84
+
85
+ expect(json_body[:error]).to eq('invalid_client')
86
+ end
87
+
88
+ it 'does not revokes Access Token when token was issued to another client' do
89
+ another_client = Application.create(name: 'Some')
90
+ AccessToken.last.update(client_id: another_client.id)
91
+
92
+ expect {
93
+ post api_url, token: AccessToken.last.token
94
+ }.to_not change { AccessToken.where(revoked_at: nil).count }
95
+
96
+ expect(json_body[:error]).to eq('invalid_client')
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -1,64 +1,64 @@
1
- require 'spec_helper'
2
-
3
- describe 'GET Protected Resources' do
4
- let(:application) { Application.create(name: 'App1') }
5
- let(:user) { User.create(username: 'Jack Sparrow', password: '12345678') }
6
- let(:access_token) { AccessToken.create_for(application, user) }
7
-
8
- context 'with invalid data' do
9
- it 'returns Unauthorized without Access Token' do
10
- get 'api/v1/status'
11
-
12
- expect(last_response.status).to eq 401
13
-
14
- expect(json_body[:error]).to eq('unauthorized')
15
- expect(last_response.headers['WWW-Authenticate']).to eq('Bearer realm="Custom Realm"')
16
- end
17
-
18
- it 'returns Unauthorized when token scopes are blank' do
19
- get 'api/v1/status/single_scope', access_token: access_token.token
20
-
21
- expect(last_response.status).to eq 403
22
-
23
- expect(json_body[:error]).not_to be_blank
24
- end
25
-
26
- it "returns Unauthorized when token scopes doesn't match required scopes" do
27
- access_token.update(scopes: 'read')
28
- get 'api/v1/status/multiple_scopes', access_token: access_token.token
29
-
30
- expect(last_response.status).to eq 403
31
-
32
- expect(json_body[:error]).not_to be_blank
33
- end
34
- end
35
-
36
- context 'with valid data' do
37
- it "returns status for endpoint that doesn't requires any scope" do
38
- get 'api/v1/status', access_token: access_token.token
39
-
40
- expect(last_response.status).to eq 200
41
-
42
- expect(json_body[:value]).to eq('Nice day!')
43
- expect(json_body[:current_user]).to eq('Jack Sparrow')
44
- end
45
-
46
- it 'returns status for endpoint with specific scope' do
47
- access_token.update(scopes: 'read public')
48
- get 'api/v1/status/single_scope', access_token: access_token.token
49
-
50
- expect(last_response.status).to eq 200
51
-
52
- expect(json_body[:value]).to eq('Access granted')
53
- end
54
-
55
- it 'returns status for endpoint with specific set of scopes' do
56
- access_token.update(scopes: 'read write public')
57
- get 'api/v1/status/multiple_scopes', access_token: access_token.token
58
-
59
- expect(last_response.status).to eq 200
60
-
61
- expect(json_body[:value]).to eq('Access granted')
62
- end
63
- end
64
- end
1
+ require 'spec_helper'
2
+
3
+ describe 'GET Protected Resources' do
4
+ let(:application) { Application.create(name: 'App1') }
5
+ let(:user) { User.create(username: 'Jack Sparrow', password: '12345678') }
6
+ let(:access_token) { AccessToken.create_for(application, user) }
7
+
8
+ context 'with invalid data' do
9
+ it 'returns Unauthorized without Access Token' do
10
+ get 'api/v1/status'
11
+
12
+ expect(last_response.status).to eq 401
13
+
14
+ expect(json_body[:error]).to eq('unauthorized')
15
+ expect(last_response.headers['WWW-Authenticate']).to eq('Bearer realm="Custom Realm"')
16
+ end
17
+
18
+ it 'returns Unauthorized when token scopes are blank' do
19
+ get 'api/v1/status/single_scope', access_token: access_token.token
20
+
21
+ expect(last_response.status).to eq 403
22
+
23
+ expect(json_body[:error]).not_to be_blank
24
+ end
25
+
26
+ it "returns Unauthorized when token scopes doesn't match required scopes" do
27
+ access_token.update(scopes: 'read')
28
+ get 'api/v1/status/multiple_scopes', access_token: access_token.token
29
+
30
+ expect(last_response.status).to eq 403
31
+
32
+ expect(json_body[:error]).not_to be_blank
33
+ end
34
+ end
35
+
36
+ context 'with valid data' do
37
+ it "returns status for endpoint that doesn't requires any scope" do
38
+ get 'api/v1/status', access_token: access_token.token
39
+
40
+ expect(last_response.status).to eq 200
41
+
42
+ expect(json_body[:value]).to eq('Nice day!')
43
+ expect(json_body[:current_user]).to eq('Jack Sparrow')
44
+ end
45
+
46
+ it 'returns status for endpoint with specific scope' do
47
+ access_token.update(scopes: 'read public')
48
+ get 'api/v1/status/single_scope', access_token: access_token.token
49
+
50
+ expect(last_response.status).to eq 200
51
+
52
+ expect(json_body[:value]).to eq('Access granted')
53
+ end
54
+
55
+ it 'returns status for endpoint with specific set of scopes' do
56
+ access_token.update(scopes: 'read write public')
57
+ get 'api/v1/status/multiple_scopes', access_token: access_token.token
58
+
59
+ expect(last_response.status).to eq 200
60
+
61
+ expect(json_body[:value]).to eq('Access granted')
62
+ end
63
+ end
64
+ end
@@ -1,60 +1,60 @@
1
- ENV['RAILS_ENV'] ||= 'test'
2
- ENV['ORM'] ||= 'active_record'
3
-
4
- puts "Configured ORM: '#{ENV['ORM']}'"
5
-
6
- require 'coveralls'
7
-
8
- if Coveralls.should_run?
9
- Coveralls.wear!
10
- else
11
- require 'simplecov'
12
- SimpleCov.start
13
- end
14
-
15
- require 'bundler/setup'
16
- Bundler.setup
17
-
18
- require 'rack/test'
19
- require 'database_cleaner'
20
-
21
- ORM_GEMS_MAPPING = {
22
- 'sequel' => 'sequel',
23
- 'active_record' => 'active_record',
24
- 'mongoid' => 'mongoid'
25
- }.freeze
26
-
27
- require ORM_GEMS_MAPPING[ENV['ORM']]
28
-
29
- require 'grape_oauth2'
30
-
31
- # Require Rack app by ORM
32
- require File.expand_path("../dummy/orm/#{ENV['ORM']}/app/twitter", __FILE__)
33
-
34
- TWITTER_APP = Rack::Builder.parse_file(File.expand_path("../dummy/orm/#{ENV['ORM']}/config.ru", __FILE__)).first
35
-
36
- require 'support/api_helper'
37
-
38
- RSpec.configure do |config|
39
- config.include ApiHelper
40
-
41
- config.filter_run_excluding skip_if: true
42
-
43
- config.order = 'random'
44
-
45
- config.before(:suite) do
46
- if ENV['ORM'] == 'mongoid'
47
- DatabaseCleaner[:mongoid].strategy = :truncation
48
- DatabaseCleaner[:mongoid].clean_with :truncation
49
- else
50
- DatabaseCleaner.strategy = :transaction
51
- DatabaseCleaner.clean_with(:deletion)
52
- end
53
- end
54
-
55
- config.around(:example) do |example|
56
- DatabaseCleaner.cleaning do
57
- example.run
58
- end
59
- end
60
- end
1
+ ENV['RAILS_ENV'] ||= 'test'
2
+ ENV['ORM'] ||= 'active_record'
3
+
4
+ puts "Configured ORM: '#{ENV['ORM']}'"
5
+
6
+ require 'coveralls'
7
+
8
+ if Coveralls.should_run?
9
+ Coveralls.wear!
10
+ else
11
+ require 'simplecov'
12
+ SimpleCov.start
13
+ end
14
+
15
+ require 'bundler/setup'
16
+ Bundler.setup
17
+
18
+ require 'rack/test'
19
+ require 'database_cleaner'
20
+
21
+ ORM_GEMS_MAPPING = {
22
+ 'sequel' => 'sequel',
23
+ 'active_record' => 'active_record',
24
+ 'mongoid' => 'mongoid'
25
+ }.freeze
26
+
27
+ require ORM_GEMS_MAPPING[ENV['ORM']]
28
+
29
+ require 'grape_oauth2'
30
+
31
+ # Require Rack app by ORM
32
+ require File.expand_path("../dummy/orm/#{ENV['ORM']}/app/twitter", __FILE__)
33
+
34
+ TWITTER_APP = Rack::Builder.parse_file(File.expand_path("../dummy/orm/#{ENV['ORM']}/config.ru", __FILE__)).first
35
+
36
+ require 'support/api_helper'
37
+
38
+ RSpec.configure do |config|
39
+ config.include ApiHelper
40
+
41
+ config.filter_run_excluding skip_if: true
42
+
43
+ config.order = 'random'
44
+
45
+ config.before(:suite) do
46
+ if ENV['ORM'] == 'mongoid'
47
+ DatabaseCleaner[:mongoid].strategy = :truncation
48
+ DatabaseCleaner[:mongoid].clean_with :truncation
49
+ else
50
+ DatabaseCleaner.strategy = :transaction
51
+ DatabaseCleaner.clean_with(:deletion)
52
+ end
53
+ end
54
+
55
+ config.around(:example) do |example|
56
+ DatabaseCleaner.cleaning do
57
+ example.run
58
+ end
59
+ end
60
+ end