grape_oauth2 0.1.1 → 0.2.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 (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,210 +1,210 @@
1
- require 'spec_helper'
2
-
3
- describe 'Token Endpoint' do
4
- let(:application) { Application.create(name: 'App1') }
5
- let(:user) { User.create(username: 'test', password: '12345678') }
6
-
7
- describe 'Resource Owner Password Credentials flow' do
8
- describe 'POST /oauth/token' do
9
- let(:authentication_url) { '/api/v1/oauth/token' }
10
-
11
- context 'with valid params' do
12
- context 'when request is invalid' do
13
- it 'fails without Grant Type' do
14
- post authentication_url,
15
- username: user.username,
16
- password: '12345678',
17
- client_id: application.key,
18
- client_secret: application.secret
19
-
20
- expect(AccessToken.all).to be_empty
21
-
22
- expect(json_body[:error]).to eq('invalid_request')
23
- expect(last_response.status).to eq 400
24
- end
25
-
26
- it 'fails with invalid Grant Type' do
27
- post authentication_url,
28
- grant_type: 'invalid',
29
- username: user.username,
30
- password: '12345678'
31
-
32
- expect(AccessToken.all).to be_empty
33
-
34
- expect(json_body[:error]).to eq('unsupported_grant_type')
35
- expect(last_response.status).to eq 400
36
- end
37
-
38
- it 'fails without Client Credentials' do
39
- post authentication_url,
40
- grant_type: 'password',
41
- username: user.username,
42
- password: '12345678'
43
-
44
- expect(AccessToken.all).to be_empty
45
-
46
- expect(json_body[:error]).to eq('invalid_request')
47
- expect(last_response.status).to eq 400
48
- end
49
-
50
- it 'fails with invalid Client Credentials' do
51
- post authentication_url,
52
- grant_type: 'password',
53
- username: user.username,
54
- password: '12345678',
55
- client_id: 'blah-blah',
56
- client_secret: application.secret
57
-
58
- expect(AccessToken.all).to be_empty
59
-
60
- expect(json_body[:error]).to eq('invalid_client')
61
- expect(last_response.status).to eq 401
62
- end
63
-
64
- it 'fails without Resource Owner credentials' do
65
- post authentication_url,
66
- grant_type: 'password',
67
- client_id: application.key,
68
- client_secret: application.secret
69
-
70
- expect(json_body[:error]).to eq('invalid_request')
71
- expect(json_body[:error_description]).not_to be_blank
72
- expect(last_response.status).to eq 400
73
- end
74
-
75
- it 'fails with invalid Resource Owner credentials' do
76
- post authentication_url,
77
- grant_type: 'password',
78
- username: 'invalid@example.com',
79
- password: 'invalid',
80
- client_id: application.key,
81
- client_secret: application.secret
82
-
83
- expect(json_body[:error]).to eq('invalid_grant')
84
- expect(json_body[:error_description]).not_to be_blank
85
- expect(last_response.status).to eq 400
86
- end
87
- end
88
-
89
- context 'with valid data' do
90
- context 'when scopes requested' do
91
- it 'returns an Access Token with scopes' do
92
- post authentication_url,
93
- grant_type: 'password',
94
- username: user.username,
95
- password: '12345678',
96
- scope: 'read write',
97
- client_id: application.key,
98
- client_secret: application.secret
99
-
100
- expect(AccessToken.count).to eq 1
101
- expect(AccessToken.first.client_id).to eq application.id
102
-
103
- expect(json_body[:access_token]).to be_present
104
- expect(json_body[:token_type]).to eq 'bearer'
105
- expect(json_body[:expires_in]).to eq 7200
106
- expect(json_body[:refresh_token]).to be_nil
107
- expect(json_body[:scope]).to eq('read write')
108
-
109
- expect(last_response.status).to eq 200
110
- end
111
- end
112
-
113
- context 'without scopes' do
114
- it 'returns an Access Token without scopes' do
115
- post authentication_url,
116
- grant_type: 'password',
117
- username: user.username,
118
- password: '12345678',
119
- client_id: application.key,
120
- client_secret: application.secret
121
-
122
- expect(AccessToken.count).to eq 1
123
- expect(AccessToken.first.client_id).to eq application.id
124
-
125
- expect(json_body[:access_token]).to be_present
126
- expect(json_body[:token_type]).to eq 'bearer'
127
- expect(json_body[:expires_in]).to eq 7200
128
- expect(json_body[:refresh_token]).to be_nil
129
- expect(json_body[:scope]).to be_nil
130
-
131
- expect(last_response.status).to eq 200
132
- end
133
- end
134
- end
135
-
136
- context 'when Token endpoint not mounted' do
137
- before do
138
- Twitter::API.reset!
139
- Twitter::API.change!
140
-
141
- # Mount only Authorization Endpoint
142
- Twitter::API.send(:include, Grape::OAuth2.api(:authorize))
143
- end
144
-
145
- after do
146
- Twitter::API.reset!
147
- Twitter::API.change!
148
-
149
- Twitter::API.send(:include, Grape::OAuth2.api)
150
- Twitter::API.mount(Twitter::Endpoints::Status)
151
- Twitter::API.mount(Twitter::Endpoints::CustomToken)
152
- Twitter::API.mount(Twitter::Endpoints::CustomAuthorization)
153
- end
154
-
155
- it 'returns 404' do
156
- post authentication_url,
157
- grant_type: 'password',
158
- username: user.username,
159
- password: '12345678',
160
- client_id: application.key,
161
- client_secret: application.secret
162
-
163
- expect(last_response.status).to eq 404
164
- end
165
- end
166
- end
167
- end
168
- end
169
-
170
- describe 'POST /oauth/custom_token' do
171
- context 'when block processed successfully' do
172
- it 'returns an access token' do
173
- application.update(name: 'Admin')
174
-
175
- post '/api/v1/oauth/custom_token',
176
- grant_type: 'password',
177
- username: user.username,
178
- password: '12345678',
179
- client_id: application.key,
180
- client_secret: application.secret
181
-
182
- expect(last_response.status).to eq 200
183
-
184
- expect(AccessToken.count).to eq 1
185
- expect(AccessToken.first.client_id).to eq application.id
186
-
187
- expect(json_body[:access_token]).to be_present
188
- expect(json_body[:token_type]).to eq 'bearer'
189
- expect(json_body[:expires_in]).to eq 7200
190
- end
191
- end
192
-
193
- context 'when authentication failed' do
194
- it 'returns an error' do
195
- application.update(name: 'Admin')
196
-
197
- post '/api/v1/oauth/custom_token',
198
- grant_type: 'password',
199
- username: 'invalid@example.com',
200
- password: 'invalid',
201
- client_id: application.key,
202
- client_secret: application.secret
203
-
204
- expect(json_body[:error]).to eq('invalid_grant')
205
- expect(json_body[:error_description]).not_to be_blank
206
- expect(last_response.status).to eq 400
207
- end
208
- end
209
- end
210
- end
1
+ require 'spec_helper'
2
+
3
+ describe 'Token Endpoint' do
4
+ let(:application) { Application.create(name: 'App1') }
5
+ let(:user) { User.create(username: 'test', password: '12345678') }
6
+
7
+ describe 'Resource Owner Password Credentials flow' do
8
+ describe 'POST /oauth/token' do
9
+ let(:authentication_url) { '/api/v1/oauth/token' }
10
+
11
+ context 'with valid params' do
12
+ context 'when request is invalid' do
13
+ it 'fails without Grant Type' do
14
+ post authentication_url,
15
+ username: user.username,
16
+ password: '12345678',
17
+ client_id: application.key,
18
+ client_secret: application.secret
19
+
20
+ expect(AccessToken.all).to be_empty
21
+
22
+ expect(json_body[:error]).to eq('invalid_request')
23
+ expect(last_response.status).to eq 400
24
+ end
25
+
26
+ it 'fails with invalid Grant Type' do
27
+ post authentication_url,
28
+ grant_type: 'invalid',
29
+ username: user.username,
30
+ password: '12345678'
31
+
32
+ expect(AccessToken.all).to be_empty
33
+
34
+ expect(json_body[:error]).to eq('unsupported_grant_type')
35
+ expect(last_response.status).to eq 400
36
+ end
37
+
38
+ it 'fails without Client Credentials' do
39
+ post authentication_url,
40
+ grant_type: 'password',
41
+ username: user.username,
42
+ password: '12345678'
43
+
44
+ expect(AccessToken.all).to be_empty
45
+
46
+ expect(json_body[:error]).to eq('invalid_request')
47
+ expect(last_response.status).to eq 400
48
+ end
49
+
50
+ it 'fails with invalid Client Credentials' do
51
+ post authentication_url,
52
+ grant_type: 'password',
53
+ username: user.username,
54
+ password: '12345678',
55
+ client_id: 'blah-blah',
56
+ client_secret: application.secret
57
+
58
+ expect(AccessToken.all).to be_empty
59
+
60
+ expect(json_body[:error]).to eq('invalid_client')
61
+ expect(last_response.status).to eq 401
62
+ end
63
+
64
+ it 'fails without Resource Owner credentials' do
65
+ post authentication_url,
66
+ grant_type: 'password',
67
+ client_id: application.key,
68
+ client_secret: application.secret
69
+
70
+ expect(json_body[:error]).to eq('invalid_request')
71
+ expect(json_body[:error_description]).not_to be_blank
72
+ expect(last_response.status).to eq 400
73
+ end
74
+
75
+ it 'fails with invalid Resource Owner credentials' do
76
+ post authentication_url,
77
+ grant_type: 'password',
78
+ username: 'invalid@example.com',
79
+ password: 'invalid',
80
+ client_id: application.key,
81
+ client_secret: application.secret
82
+
83
+ expect(json_body[:error]).to eq('invalid_grant')
84
+ expect(json_body[:error_description]).not_to be_blank
85
+ expect(last_response.status).to eq 400
86
+ end
87
+ end
88
+
89
+ context 'with valid data' do
90
+ context 'when scopes requested' do
91
+ it 'returns an Access Token with scopes' do
92
+ post authentication_url,
93
+ grant_type: 'password',
94
+ username: user.username,
95
+ password: '12345678',
96
+ scope: 'read write',
97
+ client_id: application.key,
98
+ client_secret: application.secret
99
+
100
+ expect(AccessToken.count).to eq 1
101
+ expect(AccessToken.first.client_id).to eq application.id
102
+
103
+ expect(json_body[:access_token]).to be_present
104
+ expect(json_body[:token_type]).to eq 'bearer'
105
+ expect(json_body[:expires_in]).to eq 7200
106
+ expect(json_body[:refresh_token]).to be_nil
107
+ expect(json_body[:scope]).to eq('read write')
108
+
109
+ expect(last_response.status).to eq 200
110
+ end
111
+ end
112
+
113
+ context 'without scopes' do
114
+ it 'returns an Access Token without scopes' do
115
+ post authentication_url,
116
+ grant_type: 'password',
117
+ username: user.username,
118
+ password: '12345678',
119
+ client_id: application.key,
120
+ client_secret: application.secret
121
+
122
+ expect(AccessToken.count).to eq 1
123
+ expect(AccessToken.first.client_id).to eq application.id
124
+
125
+ expect(json_body[:access_token]).to be_present
126
+ expect(json_body[:token_type]).to eq 'bearer'
127
+ expect(json_body[:expires_in]).to eq 7200
128
+ expect(json_body[:refresh_token]).to be_nil
129
+ expect(json_body[:scope]).to be_nil
130
+
131
+ expect(last_response.status).to eq 200
132
+ end
133
+ end
134
+ end
135
+
136
+ context 'when Token endpoint not mounted' do
137
+ before do
138
+ Twitter::API.reset!
139
+ Twitter::API.change!
140
+
141
+ # Mount only Authorization Endpoint
142
+ Twitter::API.send(:include, Grape::OAuth2.api(:authorize))
143
+ end
144
+
145
+ after do
146
+ Twitter::API.reset!
147
+ Twitter::API.change!
148
+
149
+ Twitter::API.send(:include, Grape::OAuth2.api)
150
+ Twitter::API.mount(Twitter::Endpoints::Status)
151
+ Twitter::API.mount(Twitter::Endpoints::CustomToken)
152
+ Twitter::API.mount(Twitter::Endpoints::CustomAuthorization)
153
+ end
154
+
155
+ it 'returns 404' do
156
+ post authentication_url,
157
+ grant_type: 'password',
158
+ username: user.username,
159
+ password: '12345678',
160
+ client_id: application.key,
161
+ client_secret: application.secret
162
+
163
+ expect(last_response.status).to eq 404
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+
170
+ describe 'POST /oauth/custom_token' do
171
+ context 'when block processed successfully' do
172
+ it 'returns an access token' do
173
+ application.update(name: 'Admin')
174
+
175
+ post '/api/v1/oauth/custom_token',
176
+ grant_type: 'password',
177
+ username: user.username,
178
+ password: '12345678',
179
+ client_id: application.key,
180
+ client_secret: application.secret
181
+
182
+ expect(last_response.status).to eq 200
183
+
184
+ expect(AccessToken.count).to eq 1
185
+ expect(AccessToken.first.client_id).to eq application.id
186
+
187
+ expect(json_body[:access_token]).to be_present
188
+ expect(json_body[:token_type]).to eq 'bearer'
189
+ expect(json_body[:expires_in]).to eq 7200
190
+ end
191
+ end
192
+
193
+ context 'when authentication failed' do
194
+ it 'returns an error' do
195
+ application.update(name: 'Admin')
196
+
197
+ post '/api/v1/oauth/custom_token',
198
+ grant_type: 'password',
199
+ username: 'invalid@example.com',
200
+ password: 'invalid',
201
+ client_id: application.key,
202
+ client_secret: application.secret
203
+
204
+ expect(json_body[:error]).to eq('invalid_grant')
205
+ expect(json_body[:error_description]).not_to be_blank
206
+ expect(last_response.status).to eq 400
207
+ end
208
+ end
209
+ end
210
+ end
@@ -1,222 +1,222 @@
1
- require 'spec_helper'
2
-
3
- describe 'Token Endpoint' do
4
- describe 'POST /oauth/token' do
5
- describe 'Refresh Token flow' do
6
- context 'with valid params' do
7
- let(:api_url) { '/api/v1/oauth/token' }
8
- let(:application) { Application.create(name: 'App1') }
9
- let(:user) { User.create(username: 'test', password: '12345678') }
10
-
11
- context 'when request is invalid' do
12
- it 'fails without Grant Type' do
13
- post api_url,
14
- client_id: application.key,
15
- client_secret: application.secret
16
-
17
- expect(AccessToken.all).to be_empty
18
-
19
- expect(json_body[:error]).to eq('invalid_request')
20
- expect(last_response.status).to eq 400
21
- end
22
-
23
- it 'fails with invalid Grant Type' do
24
- post api_url,
25
- grant_type: 'invalid'
26
-
27
- expect(AccessToken.all).to be_empty
28
-
29
- expect(json_body[:error]).to eq('unsupported_grant_type')
30
- expect(last_response.status).to eq 400
31
- end
32
-
33
- it 'fails without Client Credentials' do
34
- post api_url,
35
- grant_type: 'refresh_token'
36
-
37
- expect(AccessToken.all).to be_empty
38
-
39
- expect(json_body[:error]).to eq('invalid_request')
40
- expect(last_response.status).to eq 400
41
- end
42
-
43
- it 'fails with invalid Client Credentials' do
44
- post api_url,
45
- grant_type: 'refresh_token',
46
- refresh_token: SecureRandom.hex(6),
47
- client_id: 'blah-blah',
48
- client_secret: application.secret
49
-
50
- expect(AccessToken.all).to be_empty
51
-
52
- expect(json_body[:error]).to eq('invalid_client')
53
- expect(last_response.status).to eq 401
54
- end
55
-
56
- it 'fails when Access Token was issued to another client' do
57
- allow(Grape::OAuth2.config).to receive(:issue_refresh_token).and_return(true)
58
-
59
- another_client = Application.create(name: 'Some')
60
- token = AccessToken.create_for(another_client, user)
61
- expect(token.refresh_token).not_to be_nil
62
-
63
- post api_url,
64
- grant_type: 'refresh_token',
65
- refresh_token: token.refresh_token,
66
- client_id: application.key,
67
- client_secret: application.secret
68
-
69
- expect(json_body[:error]).to eq('unauthorized_client')
70
- expect(last_response.status).to eq 400
71
-
72
- expect(AccessToken.count).to eq(1)
73
- end
74
- end
75
-
76
- context 'with valid data' do
77
- before { allow(Grape::OAuth2.config).to receive(:issue_refresh_token).and_return(true) }
78
-
79
- it 'returns a new Access Token' do
80
- token = AccessToken.create_for(application, user)
81
- expect(token.refresh_token).not_to be_nil
82
-
83
- post api_url,
84
- grant_type: 'refresh_token',
85
- refresh_token: token.refresh_token,
86
- client_id: application.key,
87
- client_secret: application.secret
88
-
89
- expect(last_response.status).to eq 200
90
-
91
- expect(AccessToken.count).to eq 2
92
- expect(AccessToken.last.client_id).to eq application.id
93
- expect(AccessToken.last.resource_owner_id).to eq user.id
94
-
95
- expect(json_body[:access_token]).to eq AccessToken.last.token
96
- expect(json_body[:token_type]).to eq 'bearer'
97
- expect(json_body[:expires_in]).to eq 7200
98
- expect(json_body[:refresh_token]).to eq AccessToken.last.refresh_token
99
- end
100
-
101
- it 'revokes old Access Token if it is configured' do
102
- allow(Grape::OAuth2.config).to receive(:on_refresh).and_return(:revoke!)
103
-
104
- token = AccessToken.create_for(application, user)
105
- expect(token.refresh_token).not_to be_nil
106
-
107
- post api_url,
108
- grant_type: 'refresh_token',
109
- refresh_token: token.refresh_token,
110
- client_id: application.key,
111
- client_secret: application.secret
112
-
113
- expect(last_response.status).to eq 200
114
-
115
- expect(AccessToken.count).to eq 2
116
- expect(AccessToken.last.client).to eq application
117
- expect(AccessToken.last.resource_owner).to eq user
118
-
119
- expect(token.reload.revoked?).to be_truthy
120
-
121
- expect(json_body[:access_token]).to eq AccessToken.last.token
122
- expect(json_body[:refresh_token]).to eq AccessToken.last.refresh_token
123
- end
124
-
125
- it 'destroy old Access Token if it is configured' do
126
- allow(Grape::OAuth2.config).to receive(:on_refresh).and_return(:destroy)
127
-
128
- token = AccessToken.create_for(application, user)
129
- expect(token.refresh_token).not_to be_nil
130
-
131
- post api_url,
132
- grant_type: 'refresh_token',
133
- refresh_token: token.refresh_token,
134
- client_id: application.key,
135
- client_secret: application.secret
136
-
137
- expect(last_response.status).to eq 200
138
-
139
- expect(AccessToken.count).to eq 1
140
- expect(AccessToken.where(token: token.token).first).to be_nil
141
- end
142
-
143
- it 'calls custom block on token refresh if it is configured' do
144
- scopes = 'just for test'
145
- allow(Grape::OAuth2.config).to receive(:on_refresh).and_return(->(token) { token.update(scopes: scopes) })
146
-
147
- token = AccessToken.create_for(application, user)
148
- expect(token.refresh_token).not_to be_nil
149
-
150
- post api_url,
151
- grant_type: 'refresh_token',
152
- refresh_token: token.refresh_token,
153
- client_id: application.key,
154
- client_secret: application.secret
155
-
156
- expect(last_response.status).to eq 200
157
-
158
- expect(AccessToken.count).to eq 2
159
- expect(token.reload.scopes).to eq(scopes)
160
- end
161
-
162
- it 'does nothing on token refresh if :on_refresh is equal to :nothing or nil' do
163
- allow(Grape::OAuth2.config).to receive(:on_refresh).and_return(:nothing)
164
-
165
- token = AccessToken.create_for(application, user)
166
- expect(token.refresh_token).not_to be_nil
167
-
168
- # Check for :nothing
169
- expect(Grape::OAuth2::Strategies::RefreshToken).not_to receive(:run_on_refresh_callback)
170
-
171
- post api_url,
172
- grant_type: 'refresh_token',
173
- refresh_token: token.refresh_token,
174
- client_id: application.key,
175
- client_secret: application.secret
176
-
177
- expect(last_response.status).to eq 200
178
-
179
- allow(Grape::OAuth2.config).to receive(:on_refresh).and_return(nil)
180
-
181
- token = AccessToken.create_for(application, user)
182
- expect(token.refresh_token).not_to be_nil
183
-
184
- # Check for nil
185
- expect(Grape::OAuth2::Strategies::RefreshToken).not_to receive(:run_on_refresh_callback)
186
-
187
- post api_url,
188
- grant_type: 'refresh_token',
189
- refresh_token: token.refresh_token,
190
- client_id: application.key,
191
- client_secret: application.secret
192
-
193
- expect(last_response.status).to eq 200
194
- end
195
-
196
- it 'returns a new Access Token even if used token is expired' do
197
- token = AccessToken.create_for(application, user)
198
- token.update(expires_at: Time.now - 604800) # - 7 days
199
- expect(token.refresh_token).not_to be_nil
200
-
201
- post api_url,
202
- grant_type: 'refresh_token',
203
- refresh_token: token.refresh_token,
204
- client_id: application.key,
205
- client_secret: application.secret
206
-
207
- expect(last_response.status).to eq 200
208
-
209
- expect(AccessToken.count).to eq 2
210
- expect(AccessToken.last.client_id).to eq application.id
211
- expect(AccessToken.last.resource_owner_id).to eq user.id
212
-
213
- expect(json_body[:access_token]).to eq AccessToken.last.token
214
- expect(json_body[:token_type]).to eq 'bearer'
215
- expect(json_body[:expires_in]).to eq 7200
216
- expect(json_body[:refresh_token]).to eq AccessToken.last.refresh_token
217
- end
218
- end
219
- end
220
- end
221
- end
222
- end
1
+ require 'spec_helper'
2
+
3
+ describe 'Token Endpoint' do
4
+ describe 'POST /oauth/token' do
5
+ describe 'Refresh Token flow' do
6
+ context 'with valid params' do
7
+ let(:api_url) { '/api/v1/oauth/token' }
8
+ let(:application) { Application.create(name: 'App1') }
9
+ let(:user) { User.create(username: 'test', password: '12345678') }
10
+
11
+ context 'when request is invalid' do
12
+ it 'fails without Grant Type' do
13
+ post api_url,
14
+ client_id: application.key,
15
+ client_secret: application.secret
16
+
17
+ expect(AccessToken.all).to be_empty
18
+
19
+ expect(json_body[:error]).to eq('invalid_request')
20
+ expect(last_response.status).to eq 400
21
+ end
22
+
23
+ it 'fails with invalid Grant Type' do
24
+ post api_url,
25
+ grant_type: 'invalid'
26
+
27
+ expect(AccessToken.all).to be_empty
28
+
29
+ expect(json_body[:error]).to eq('unsupported_grant_type')
30
+ expect(last_response.status).to eq 400
31
+ end
32
+
33
+ it 'fails without Client Credentials' do
34
+ post api_url,
35
+ grant_type: 'refresh_token'
36
+
37
+ expect(AccessToken.all).to be_empty
38
+
39
+ expect(json_body[:error]).to eq('invalid_request')
40
+ expect(last_response.status).to eq 400
41
+ end
42
+
43
+ it 'fails with invalid Client Credentials' do
44
+ post api_url,
45
+ grant_type: 'refresh_token',
46
+ refresh_token: SecureRandom.hex(6),
47
+ client_id: 'blah-blah',
48
+ client_secret: application.secret
49
+
50
+ expect(AccessToken.all).to be_empty
51
+
52
+ expect(json_body[:error]).to eq('invalid_client')
53
+ expect(last_response.status).to eq 401
54
+ end
55
+
56
+ it 'fails when Access Token was issued to another client' do
57
+ allow(Grape::OAuth2.config).to receive(:issue_refresh_token).and_return(true)
58
+
59
+ another_client = Application.create(name: 'Some')
60
+ token = AccessToken.create_for(another_client, user)
61
+ expect(token.refresh_token).not_to be_nil
62
+
63
+ post api_url,
64
+ grant_type: 'refresh_token',
65
+ refresh_token: token.refresh_token,
66
+ client_id: application.key,
67
+ client_secret: application.secret
68
+
69
+ expect(json_body[:error]).to eq('unauthorized_client')
70
+ expect(last_response.status).to eq 400
71
+
72
+ expect(AccessToken.count).to eq(1)
73
+ end
74
+ end
75
+
76
+ context 'with valid data' do
77
+ before { allow(Grape::OAuth2.config).to receive(:issue_refresh_token).and_return(true) }
78
+
79
+ it 'returns a new Access Token' do
80
+ token = AccessToken.create_for(application, user)
81
+ expect(token.refresh_token).not_to be_nil
82
+
83
+ post api_url,
84
+ grant_type: 'refresh_token',
85
+ refresh_token: token.refresh_token,
86
+ client_id: application.key,
87
+ client_secret: application.secret
88
+
89
+ expect(last_response.status).to eq 200
90
+
91
+ expect(AccessToken.count).to eq 2
92
+ expect(AccessToken.last.client_id).to eq application.id
93
+ expect(AccessToken.last.resource_owner_id).to eq user.id
94
+
95
+ expect(json_body[:access_token]).to eq AccessToken.last.token
96
+ expect(json_body[:token_type]).to eq 'bearer'
97
+ expect(json_body[:expires_in]).to eq 7200
98
+ expect(json_body[:refresh_token]).to eq AccessToken.last.refresh_token
99
+ end
100
+
101
+ it 'revokes old Access Token if it is configured' do
102
+ allow(Grape::OAuth2.config).to receive(:on_refresh).and_return(:revoke!)
103
+
104
+ token = AccessToken.create_for(application, user)
105
+ expect(token.refresh_token).not_to be_nil
106
+
107
+ post api_url,
108
+ grant_type: 'refresh_token',
109
+ refresh_token: token.refresh_token,
110
+ client_id: application.key,
111
+ client_secret: application.secret
112
+
113
+ expect(last_response.status).to eq 200
114
+
115
+ expect(AccessToken.count).to eq 2
116
+ expect(AccessToken.last.client).to eq application
117
+ expect(AccessToken.last.resource_owner).to eq user
118
+
119
+ expect(token.reload.revoked?).to be_truthy
120
+
121
+ expect(json_body[:access_token]).to eq AccessToken.last.token
122
+ expect(json_body[:refresh_token]).to eq AccessToken.last.refresh_token
123
+ end
124
+
125
+ it 'destroy old Access Token if it is configured' do
126
+ allow(Grape::OAuth2.config).to receive(:on_refresh).and_return(:destroy)
127
+
128
+ token = AccessToken.create_for(application, user)
129
+ expect(token.refresh_token).not_to be_nil
130
+
131
+ post api_url,
132
+ grant_type: 'refresh_token',
133
+ refresh_token: token.refresh_token,
134
+ client_id: application.key,
135
+ client_secret: application.secret
136
+
137
+ expect(last_response.status).to eq 200
138
+
139
+ expect(AccessToken.count).to eq 1
140
+ expect(AccessToken.where(token: token.token).first).to be_nil
141
+ end
142
+
143
+ it 'calls custom block on token refresh if it is configured' do
144
+ scopes = 'just for test'
145
+ allow(Grape::OAuth2.config).to receive(:on_refresh).and_return(->(token) { token.update(scopes: scopes) })
146
+
147
+ token = AccessToken.create_for(application, user)
148
+ expect(token.refresh_token).not_to be_nil
149
+
150
+ post api_url,
151
+ grant_type: 'refresh_token',
152
+ refresh_token: token.refresh_token,
153
+ client_id: application.key,
154
+ client_secret: application.secret
155
+
156
+ expect(last_response.status).to eq 200
157
+
158
+ expect(AccessToken.count).to eq 2
159
+ expect(token.reload.scopes).to eq(scopes)
160
+ end
161
+
162
+ it 'does nothing on token refresh if :on_refresh is equal to :nothing or nil' do
163
+ allow(Grape::OAuth2.config).to receive(:on_refresh).and_return(:nothing)
164
+
165
+ token = AccessToken.create_for(application, user)
166
+ expect(token.refresh_token).not_to be_nil
167
+
168
+ # Check for :nothing
169
+ expect(Grape::OAuth2::Strategies::RefreshToken).not_to receive(:run_on_refresh_callback)
170
+
171
+ post api_url,
172
+ grant_type: 'refresh_token',
173
+ refresh_token: token.refresh_token,
174
+ client_id: application.key,
175
+ client_secret: application.secret
176
+
177
+ expect(last_response.status).to eq 200
178
+
179
+ allow(Grape::OAuth2.config).to receive(:on_refresh).and_return(nil)
180
+
181
+ token = AccessToken.create_for(application, user)
182
+ expect(token.refresh_token).not_to be_nil
183
+
184
+ # Check for nil
185
+ expect(Grape::OAuth2::Strategies::RefreshToken).not_to receive(:run_on_refresh_callback)
186
+
187
+ post api_url,
188
+ grant_type: 'refresh_token',
189
+ refresh_token: token.refresh_token,
190
+ client_id: application.key,
191
+ client_secret: application.secret
192
+
193
+ expect(last_response.status).to eq 200
194
+ end
195
+
196
+ it 'returns a new Access Token even if used token is expired' do
197
+ token = AccessToken.create_for(application, user)
198
+ token.update(expires_at: Time.now - 604800) # - 7 days
199
+ expect(token.refresh_token).not_to be_nil
200
+
201
+ post api_url,
202
+ grant_type: 'refresh_token',
203
+ refresh_token: token.refresh_token,
204
+ client_id: application.key,
205
+ client_secret: application.secret
206
+
207
+ expect(last_response.status).to eq 200
208
+
209
+ expect(AccessToken.count).to eq 2
210
+ expect(AccessToken.last.client_id).to eq application.id
211
+ expect(AccessToken.last.resource_owner_id).to eq user.id
212
+
213
+ expect(json_body[:access_token]).to eq AccessToken.last.token
214
+ expect(json_body[:token_type]).to eq 'bearer'
215
+ expect(json_body[:expires_in]).to eq 7200
216
+ expect(json_body[:refresh_token]).to eq AccessToken.last.refresh_token
217
+ end
218
+ end
219
+ end
220
+ end
221
+ end
222
+ end