2
2
import json
3
3
import urlparse
4
4
5
+ import ddt
5
6
from django .conf import settings
6
7
from django .contrib .auth .models import User
7
8
from django .core .urlresolvers import reverse
@@ -64,6 +65,7 @@ def _login_and_authorize(self, url_func=None):
64
65
self .assertTrue (self .redirect_url () in response ['Location' ])
65
66
66
67
68
+ @ddt .ddt
67
69
class AuthorizationTest (BaseOAuth2TestCase ):
68
70
fixtures = ['test_oauth2' ]
69
71
@@ -89,17 +91,40 @@ def test_authorization_requires_login(self):
89
91
90
92
self .assertTrue (self .auth_url2 () in response ['Location' ])
91
93
92
- def test_authorization_requires_client_id (self ):
94
+ @ddt .data (
95
+ ('read' , 'read' ),
96
+ ('write' , 'write' ),
97
+ ('read+write' , 'read write read+write' ),
98
+ )
99
+ @ddt .unpack
100
+ def test_implicit_flow (self , requested_scope , expected_scope ):
101
+ """
102
+ End-to-end test of the implicit flow (happy path).
103
+ """
93
104
self .login ()
94
- response = self .client .get (self .auth_url ())
105
+ self .client .get (self .auth_url (), data = self .get_auth_params (response_type = 'token' , scope = requested_scope ))
106
+ response = self .client .post (self .auth_url2 (), {'authorize' : True })
107
+ fragment = urlparse .urlparse (response ['Location' ]).fragment
108
+ auth_response_data = {k : v [0 ] for k , v in urlparse .parse_qs (fragment ).items ()}
109
+ self .assertEqual (auth_response_data ['scope' ], expected_scope )
110
+ self .assertEqual (auth_response_data ['access_token' ], AccessToken .objects .all ()[0 ].token )
111
+ self .assertEqual (auth_response_data ['token_type' ], 'Bearer' )
112
+ self .assertEqual (int (auth_response_data ['expires_in' ]), constants .EXPIRE_DELTA .days * 60 * 60 * 24 - 1 )
113
+ self .assertNotIn ('refresh_token' , response )
114
+
115
+ @ddt .data ('code' , 'token' )
116
+ def test_authorization_requires_client_id (self , response_type ):
117
+ self .login ()
118
+ self .client .get (self .auth_url (), data = {'response_type' : response_type })
95
119
response = self .client .get (self .auth_url2 ())
96
120
97
121
self .assertEqual (400 , response .status_code )
98
122
self .assertTrue ("An unauthorized client tried to access your resources." in response .content )
99
123
100
- def test_authorization_rejects_invalid_client_id (self ):
124
+ @ddt .data ('code' , 'token' )
125
+ def test_authorization_rejects_invalid_client_id (self , response_type ):
101
126
self .login ()
102
- response = self .client .get (self .auth_url (), data = {"client_id" : 123 })
127
+ response = self .client .get (self .auth_url (), data = {"client_id" : 123 , 'response_type' : response_type })
103
128
response = self .client .get (self .auth_url2 ())
104
129
105
130
self .assertEqual (400 , response .status_code )
@@ -113,22 +138,19 @@ def test_authorization_requires_response_type(self):
113
138
self .assertEqual (400 , response .status_code )
114
139
self .assertTrue (escape (u"No 'response_type' supplied." ) in response .content )
115
140
116
- def test_authorization_requires_supported_response_type (self ):
141
+ @ddt .data ('code' , 'token' , 'unsupported' )
142
+ def test_authorization_requires_supported_response_type (self , response_type ):
117
143
self .login ()
118
144
response = self .client .get (
119
- self .auth_url (), self .get_auth_params (response_type = "unsupported" ))
145
+ self .auth_url (), self .get_auth_params (response_type = response_type ))
120
146
response = self .client .get (self .auth_url2 ())
121
147
122
- self .assertEqual (400 , response .status_code )
123
- self .assertTrue (escape (u"'unsupported' is not a supported response type." ) in response .content )
148
+ if response_type == 'unsupported' :
149
+ self .assertEqual (400 , response .status_code )
150
+ self .assertTrue (escape (u"'unsupported' is not a supported response type." ) in response .content )
124
151
125
- response = self .client .get (self .auth_url (), data = self .get_auth_params ())
126
- response = self .client .get (self .auth_url2 ())
127
- self .assertEqual (200 , response .status_code , response .content )
128
-
129
- response = self .client .get (self .auth_url (), data = self .get_auth_params (response_type = "token" ))
130
- response = self .client .get (self .auth_url2 ())
131
- self .assertEqual (200 , response .status_code )
152
+ else :
153
+ self .assertEqual (200 , response .status_code )
132
154
133
155
def test_token_authorization_redirects_to_correct_uri (self ):
134
156
self .login ()
@@ -212,48 +234,83 @@ def test_token_authorization_cancellation(self):
212
234
213
235
self .assertEqual (AccessToken .objects .count (), 0 )
214
236
215
- def test_authorization_requires_a_valid_redirect_uri (self ):
237
+ @ddt .data ('code' , 'token' )
238
+ def test_authorization_requires_a_valid_redirect_uri (self , response_type ):
216
239
self .login ()
217
240
218
- response = self .client .get (self .auth_url (),
219
- data = self .get_auth_params (redirect_uri = self .get_client ().redirect_uri + '-invalid' ))
241
+ self .client .get (
242
+ self .auth_url (),
243
+ data = self .get_auth_params (
244
+ response_type = response_type , redirect_uri = self .get_client ().redirect_uri + '-invalid'
245
+ )
246
+ )
220
247
response = self .client .get (self .auth_url2 ())
221
248
222
249
self .assertEqual (400 , response .status_code )
223
250
self .assertTrue (escape (u"The requested redirect didn't match the client settings." ) in response .content )
224
251
225
- response = self .client .get (self .auth_url (),
226
- data = self . get_auth_params ( redirect_uri = self .get_client ().redirect_uri ))
252
+ self .client .get (self .auth_url (), data = self . get_auth_params (
253
+ response_type = response_type , redirect_uri = self .get_client ().redirect_uri ))
227
254
response = self .client .get (self .auth_url2 ())
228
255
229
256
self .assertEqual (200 , response .status_code )
230
257
231
- def test_authorization_requires_a_valid_scope (self ):
258
+ @ddt .data ('code' , 'token' )
259
+ def test_authorization_requires_a_valid_scope (self , response_type ):
232
260
self .login ()
233
261
234
- response = self .client .get (self .auth_url (), data = self .get_auth_params (scope = "invalid" ))
262
+ self .client .get (self .auth_url (), data = self .get_auth_params (response_type = response_type , scope = "invalid" ))
235
263
response = self .client .get (self .auth_url2 ())
236
264
237
265
self .assertEqual (400 , response .status_code )
238
266
self .assertTrue (escape (u"'invalid' is not a valid scope." ) in response .content ,
239
267
'Expected `{0}` in {1}' .format (escape (u"'invalid' is not a valid scope." ), response .content ))
240
268
241
- response = self .client .get (self .auth_url (), data = self .get_auth_params (scope = constants .SCOPES [0 ][1 ]))
269
+ self .client .get (
270
+ self .auth_url (),
271
+ data = self .get_auth_params (response_type = response_type , scope = constants .SCOPES [0 ][1 ])
272
+ )
242
273
response = self .client .get (self .auth_url2 ())
243
274
self .assertEqual (200 , response .status_code )
244
275
245
- def test_authorization_is_not_granted (self ):
276
+ @ddt .data ('code' , 'token' )
277
+ def test_authorization_sets_default_scope (self , response_type ):
278
+
279
+ self .login ()
280
+ self .client .get (self .auth_url (), data = self .get_auth_params (response_type = response_type ))
281
+ response = self .client .post (self .auth_url2 (), {'authorize' : True })
282
+
283
+ if response_type == 'code' :
284
+ # authorization code flow
285
+ response = self .client .get (self .redirect_url ())
286
+ query = urlparse .urlparse (response ['Location' ]).query
287
+ code = urlparse .parse_qs (query )['code' ][0 ]
288
+ response = self .client .post (self .access_token_url (), {
289
+ 'grant_type' : 'authorization_code' ,
290
+ 'client_id' : self .get_client ().client_id ,
291
+ 'client_secret' : self .get_client ().client_secret ,
292
+ 'code' : code })
293
+ scope_str = json .loads (response .content ).get ('scope' )
294
+ else :
295
+ # implicit flow
296
+ fragment = urlparse .urlparse (response ['Location' ]).fragment
297
+ scope_str = urlparse .parse_qs (fragment )['scope' ][0 ]
298
+
299
+ self .assertEqual (scope_str , constants .SCOPES [0 ][1 ])
300
+
301
+ @ddt .data ('code' , 'token' )
302
+ def test_authorization_is_not_granted (self , response_type ):
246
303
self .login ()
247
304
248
- response = self .client .get (self .auth_url (), data = self .get_auth_params (response_type = "code" ))
249
- response = self .client .get (self .auth_url2 ())
305
+ self .client .get (self .auth_url (), data = self .get_auth_params (response_type = response_type ))
306
+ self .client .get (self .auth_url2 ())
250
307
251
308
response = self .client .post (self .auth_url2 (), {'authorize' : False , 'scope' : constants .SCOPES [0 ][1 ]})
252
309
self .assertEqual (302 , response .status_code , response .content )
253
310
self .assertTrue (self .get_client ().redirect_uri in response ['Location' ],
254
311
'{0} not in {1}' .format (self .redirect_url (), response ['Location' ]))
255
312
self .assertTrue ('error=access_denied' in response ['Location' ])
256
- self .assertFalse ('code' in response ['Location' ])
313
+ self .assertFalse (response_type in response ['Location' ])
257
314
258
315
def test_authorization_is_granted (self ):
259
316
self .login ()
@@ -278,6 +335,17 @@ def test_preserving_the_state_variable(self):
278
335
self .assertTrue ('code' in response ['Location' ])
279
336
self .assertTrue ('state=abc' in response ['Location' ])
280
337
338
+ def test_preserving_the_state_variable_implicit (self ):
339
+ self .login ()
340
+
341
+ self .client .get (self .auth_url (), data = self .get_auth_params (response_type = 'token' , state = 'abc' ))
342
+ self .client .get (self .auth_url2 ())
343
+ response = self .client .post (self .auth_url2 (), {'authorize' : True , 'scope' : constants .SCOPES [0 ][1 ]})
344
+ self .assertEqual (302 , response .status_code )
345
+ self .assertFalse ('error' in response ['Location' ])
346
+ self .assertTrue ('access_token=' in response ['Location' ])
347
+ self .assertTrue ('state=abc' in response ['Location' ])
348
+
281
349
def test_redirect_requires_valid_data (self ):
282
350
self .login ()
283
351
response = self .client .get (self .redirect_url ())
0 commit comments