Merge remote-tracking branch 'upstream/pull/2051'
[rails.git] / test / integration / oauth_test.rb
1 require "test_helper"
2
3 class OAuthTest < ActionDispatch::IntegrationTest
4   include OAuth::Helper
5
6   def setup
7     stub_hostip_requests
8   end
9
10   def test_oauth10_web_app
11     client = create(:client_application, :callback_url => "http://some.web.app.example.org/callback", :allow_read_prefs => true, :allow_write_api => true, :allow_read_gpx => true)
12
13     post "/login", :params => { :username => client.user.email, :password => "test" }
14     follow_redirect!
15     follow_redirect!
16     assert_response :success
17
18     oauth10_without_callback(client)
19     oauth10_with_callback(client, "http://another.web.app.example.org/callback")
20     oauth10_refused(client)
21   end
22
23   def test_oauth10_desktop_app
24     client = create(:client_application, :allow_read_prefs => true, :allow_write_api => true, :allow_read_gpx => true)
25
26     post "/login", :params => { :username => client.user.email, :password => "test" }
27     follow_redirect!
28     follow_redirect!
29     assert_response :success
30
31     oauth10_without_callback(client)
32     oauth10_refused(client)
33   end
34
35   def test_oauth10a_web_app
36     client = create(:client_application, :callback_url => "http://some.web.app.example.org/callback", :allow_read_prefs => true, :allow_write_api => true, :allow_read_gpx => true)
37
38     post "/login", :params => { :username => client.user.email, :password => "test" }
39     follow_redirect!
40     follow_redirect!
41     assert_response :success
42
43     oauth10a_without_callback(client)
44     oauth10a_with_callback(client, "http://another.web.app.example.org/callback")
45     oauth10a_refused(client)
46   end
47
48   def test_oauth10a_desktop_app
49     client = create(:client_application, :allow_read_prefs => true, :allow_write_api => true, :allow_read_gpx => true)
50
51     post "/login", :params => { :username => client.user.email, :password => "test" }
52     follow_redirect!
53     follow_redirect!
54     assert_response :success
55
56     oauth10a_without_callback(client)
57     oauth10a_refused(client)
58   end
59
60   private
61
62   def oauth10_without_callback(client)
63     token = get_request_token(client)
64
65     get "/oauth/authorize", :params => { :oauth_token => token.token }
66     assert_response :success
67     assert_template :authorize
68
69     post "/oauth/authorize",
70          :params => { :oauth_token => token.token,
71                       :allow_read_prefs => true, :allow_write_prefs => true }
72     if client.callback_url
73       assert_response :redirect
74       assert_redirected_to "#{client.callback_url}?oauth_token=#{token.token}"
75     else
76       assert_response :success
77       assert_template :authorize_success
78     end
79     token.reload
80     assert_not_nil token.created_at
81     assert_not_nil token.authorized_at
82     assert_nil token.invalidated_at
83     assert_allowed token, [:allow_read_prefs]
84
85     signed_get "/oauth/access_token", :consumer => client, :token => token
86     assert_response :success
87     token.reload
88     assert_not_nil token.created_at
89     assert_not_nil token.authorized_at
90     assert_not_nil token.invalidated_at
91     token = parse_token(response)
92     assert_instance_of AccessToken, token
93     assert_not_nil token.created_at
94     assert_not_nil token.authorized_at
95     assert_nil token.invalidated_at
96     assert_allowed token, [:allow_read_prefs]
97
98     signed_get "/api/0.6/user/preferences", :consumer => client, :token => token
99     assert_response :success
100
101     signed_get "/api/0.6/gpx/2", :consumer => client, :token => token
102     assert_response :forbidden
103
104     post "/oauth/revoke", :params => { :token => token.token }
105     assert_redirected_to oauth_clients_url(token.user.display_name)
106     token = OauthToken.find_by(:token => token.token)
107     assert_not_nil token.invalidated_at
108
109     signed_get "/api/0.6/user/preferences", :consumer => client, :token => token
110     assert_response :unauthorized
111   end
112
113   def oauth10_refused(client)
114     token = get_request_token(client)
115
116     get "/oauth/authorize", :params => { :oauth_token => token.token }
117     assert_response :success
118     assert_template :authorize
119
120     post "/oauth/authorize", :params => { :oauth_token => token.token }
121     assert_response :success
122     assert_template :authorize_failure
123     assert_select "p", "You have denied application #{client.name} access to your account."
124     token.reload
125     assert_nil token.authorized_at
126     assert_not_nil token.invalidated_at
127
128     get "/oauth/authorize", :params => { :oauth_token => token.token }
129     assert_response :success
130     assert_template :authorize_failure
131     assert_select "p", "The authorization token is not valid."
132     token.reload
133     assert_nil token.authorized_at
134     assert_not_nil token.invalidated_at
135
136     post "/oauth/authorize", :params => { :oauth_token => token.token }
137     assert_response :success
138     assert_template :authorize_failure
139     assert_select "p", "The authorization token is not valid."
140     token.reload
141     assert_nil token.authorized_at
142     assert_not_nil token.invalidated_at
143   end
144
145   def oauth10_with_callback(client, callback_url)
146     token = get_request_token(client)
147
148     get "/oauth/authorize", :params => { :oauth_token => token.token }
149     assert_response :success
150     assert_template :authorize
151
152     post "/oauth/authorize",
153          :params => { :oauth_token => token.token, :oauth_callback => callback_url,
154                       :allow_write_api => true, :allow_read_gpx => true }
155     assert_response :redirect
156     assert_redirected_to "#{callback_url}?oauth_token=#{token.token}"
157     token.reload
158     assert_not_nil token.created_at
159     assert_not_nil token.authorized_at
160     assert_nil token.invalidated_at
161     assert_allowed token, [:allow_write_api, :allow_read_gpx]
162
163     signed_get "/oauth/access_token", :consumer => client, :token => token
164     assert_response :success
165     token.reload
166     assert_not_nil token.created_at
167     assert_not_nil token.authorized_at
168     assert_not_nil token.invalidated_at
169     token = parse_token(response)
170     assert_instance_of AccessToken, token
171     assert_not_nil token.created_at
172     assert_not_nil token.authorized_at
173     assert_nil token.invalidated_at
174     assert_allowed token, [:allow_write_api, :allow_read_gpx]
175
176     trace = create(:trace, :user => client.user)
177     signed_get "/api/0.6/gpx/#{trace.id}", :consumer => client, :token => token
178     assert_response :success
179
180     signed_get "/api/0.6/user/details", :consumer => client, :token => token
181     assert_response :forbidden
182
183     post "/oauth/revoke", :params => { :token => token.token }
184     assert_redirected_to oauth_clients_url(token.user.display_name)
185     token = OauthToken.find_by(:token => token.token)
186     assert_not_nil token.invalidated_at
187
188     signed_get "/api/0.6/gpx/2", :consumer => client, :token => token
189     assert_response :unauthorized
190   end
191
192   def oauth10a_without_callback(client)
193     token = get_request_token(client, :oauth_callback => "oob")
194
195     get "/oauth/authorize", :params => { :oauth_token => token.token }
196     assert_response :success
197     assert_template :authorize
198
199     post "/oauth/authorize",
200          :params => { :oauth_token => token.token,
201                       :allow_read_prefs => true, :allow_write_prefs => true }
202     if client.callback_url
203       assert_response :redirect
204       verifier = parse_verifier(response)
205       assert_redirected_to "http://some.web.app.example.org/callback?oauth_token=#{token.token}&oauth_verifier=#{verifier}"
206     else
207       assert_response :success
208       assert_template :authorize_success
209       m = response.body.match("<p>The verification code is ([A-Za-z0-9]+).</p>")
210       assert_not_nil m
211       verifier = m[1]
212     end
213     token.reload
214     assert_not_nil token.created_at
215     assert_not_nil token.authorized_at
216     assert_nil token.invalidated_at
217     assert_allowed token, [:allow_read_prefs]
218
219     signed_get "/oauth/access_token", :consumer => client, :token => token
220     assert_response :unauthorized
221
222     signed_get "/oauth/access_token",
223                :consumer => client, :token => token, :oauth_verifier => verifier
224     assert_response :success
225     token.reload
226     assert_not_nil token.created_at
227     assert_not_nil token.authorized_at
228     assert_not_nil token.invalidated_at
229     token = parse_token(response)
230     assert_instance_of AccessToken, token
231     assert_not_nil token.created_at
232     assert_not_nil token.authorized_at
233     assert_nil token.invalidated_at
234     assert_allowed token, [:allow_read_prefs]
235
236     signed_get "/api/0.6/user/preferences", :consumer => client, :token => token
237     assert_response :success
238
239     trace = create(:trace, :user => client.user)
240     signed_get "/api/0.6/gpx/#{trace.id}", :consumer => client, :token => token
241     assert_response :forbidden
242
243     post "/oauth/revoke", :params => { :token => token.token }
244     assert_redirected_to oauth_clients_url(token.user.display_name)
245     token = OauthToken.find_by(:token => token.token)
246     assert_not_nil token.invalidated_at
247
248     signed_get "/api/0.6/user/preferences", :consumer => client, :token => token
249     assert_response :unauthorized
250   end
251
252   def oauth10a_with_callback(client, callback_url)
253     token = get_request_token(client, :oauth_callback => callback_url)
254
255     get "/oauth/authorize", :params => { :oauth_token => token.token }
256     assert_response :success
257     assert_template :authorize
258
259     post "/oauth/authorize",
260          :params => { :oauth_token => token.token,
261                       :allow_write_api => true, :allow_read_gpx => true }
262     assert_response :redirect
263     verifier = parse_verifier(response)
264     assert_redirected_to "#{callback_url}?oauth_token=#{token.token}&oauth_verifier=#{verifier}"
265     token.reload
266     assert_not_nil token.created_at
267     assert_not_nil token.authorized_at
268     assert_nil token.invalidated_at
269     assert_allowed token, [:allow_write_api, :allow_read_gpx]
270
271     signed_get "/oauth/access_token", :consumer => client, :token => token
272     assert_response :unauthorized
273
274     signed_get "/oauth/access_token",
275                :consumer => client, :token => token, :oauth_verifier => verifier
276     assert_response :success
277     token.reload
278     assert_not_nil token.created_at
279     assert_not_nil token.authorized_at
280     assert_not_nil token.invalidated_at
281     token = parse_token(response)
282     assert_instance_of AccessToken, token
283     assert_not_nil token.created_at
284     assert_not_nil token.authorized_at
285     assert_nil token.invalidated_at
286     assert_allowed token, [:allow_write_api, :allow_read_gpx]
287
288     trace = create(:trace, :user => client.user)
289     signed_get "/api/0.6/gpx/#{trace.id}", :consumer => client, :token => token
290     assert_response :success
291
292     signed_get "/api/0.6/user/details", :consumer => client, :token => token
293     assert_response :forbidden
294
295     post "/oauth/revoke", :params => { :token => token.token }
296     assert_redirected_to oauth_clients_url(token.user.display_name)
297     token = OauthToken.find_by(:token => token.token)
298     assert_not_nil token.invalidated_at
299
300     signed_get "/api/0.6/gpx/2", :consumer => client, :token => token
301     assert_response :unauthorized
302   end
303
304   def oauth10a_refused(client)
305     token = get_request_token(client, :oauth_callback => "oob")
306
307     get "/oauth/authorize", :params => { :oauth_token => token.token }
308     assert_response :success
309     assert_template :authorize
310
311     post "/oauth/authorize", :params => { :oauth_token => token.token }
312     assert_response :success
313     assert_template :authorize_failure
314     assert_select "p", "You have denied application #{client.name} access to your account."
315     token.reload
316     assert_nil token.authorized_at
317     assert_not_nil token.invalidated_at
318
319     get "/oauth/authorize", :params => { :oauth_token => token.token }
320     assert_response :success
321     assert_template :authorize_failure
322     assert_select "p", "The authorization token is not valid."
323     token.reload
324     assert_nil token.authorized_at
325     assert_not_nil token.invalidated_at
326
327     post "/oauth/authorize", :params => { :oauth_token => token.token }
328     assert_response :success
329     assert_template :authorize_failure
330     assert_select "p", "The authorization token is not valid."
331     token.reload
332     assert_nil token.authorized_at
333     assert_not_nil token.invalidated_at
334   end
335
336   def get_request_token(client, options = {})
337     signed_get "/oauth/request_token", options.merge(:consumer => client)
338     assert_response :success
339     token = parse_token(response)
340     assert_instance_of RequestToken, token
341     assert_not_nil token.created_at
342     assert_nil token.authorized_at
343     assert_nil token.invalidated_at
344     assert_equal_allowing_nil options[:oauth_callback], token.callback_url
345     assert_allowed token, client.permissions
346
347     token
348   end
349
350   def signed_get(uri, options)
351     uri = URI.parse(uri)
352     uri.scheme ||= "http"
353     uri.host ||= "www.example.com"
354
355     helper = OAuth::Client::Helper.new(nil, options)
356
357     request = OAuth::RequestProxy.proxy(
358       "method" => "GET",
359       "uri" => uri,
360       "parameters" => helper.oauth_parameters
361     )
362
363     request.sign!(options)
364
365     get request.signed_uri
366   end
367
368   def parse_token(response)
369     params = CGI.parse(response.body)
370
371     token = OauthToken.find_by(:token => params["oauth_token"].first)
372     assert_equal token.secret, params["oauth_token_secret"].first
373
374     token
375   end
376
377   def parse_verifier(response)
378     params = CGI.parse(URI.parse(response.location).query)
379
380     assert_not_nil params["oauth_verifier"]
381     assert params["oauth_verifier"].first.present?
382
383     params["oauth_verifier"].first
384   end
385
386   def assert_allowed(token, allowed)
387     ClientApplication.all_permissions.each do |p|
388       assert_equal allowed.include?(p), token.attributes[p.to_s]
389     end
390   end
391 end