1
1
import json
2
2
import urlparse
3
3
import datetime
4
+
4
5
from django .http import QueryDict
5
6
from django .conf import settings
6
7
from django .core .urlresolvers import reverse
7
8
from django .utils .html import escape
8
9
from django .test import TestCase
9
10
from django .contrib .auth .models import User
11
+ import mock
12
+
10
13
from .. import constants , scope
11
14
from ..compat import skipIfCustomUser
15
+ from provider .constants import CONFIDENTIAL , READ
12
16
from ..templatetags .scope import scopes
13
17
from ..utils import now as date_now
14
18
from .forms import ClientForm
15
19
from .models import Client , Grant , AccessToken , RefreshToken
16
- from .backends import BasicClientBackend , RequestParamsClientBackend
17
- from .backends import AccessTokenBackend
20
+ from .backends import AccessTokenBackend , BasicClientBackend , RequestParamsClientBackend
18
21
19
22
20
23
@skipIfCustomUser
@@ -109,7 +112,8 @@ def test_authorization_requires_response_type(self):
109
112
110
113
def test_authorization_requires_supported_response_type (self ):
111
114
self .login ()
112
- response = self .client .get (self .auth_url () + '?client_id=%s&response_type=unsupported' % self .get_client ().client_id )
115
+ response = self .client .get (
116
+ self .auth_url () + '?client_id=%s&response_type=unsupported' % self .get_client ().client_id )
113
117
response = self .client .get (self .auth_url2 ())
114
118
115
119
self .assertEqual (400 , response .status_code )
@@ -144,7 +148,8 @@ def test_authorization_requires_a_valid_redirect_uri(self):
144
148
def test_authorization_requires_a_valid_scope (self ):
145
149
self .login ()
146
150
147
- response = self .client .get (self .auth_url () + '?client_id=%s&response_type=code&scope=invalid+invalid2' % self .get_client ().client_id )
151
+ response = self .client .get (
152
+ self .auth_url () + '?client_id=%s&response_type=code&scope=invalid+invalid2' % self .get_client ().client_id )
148
153
response = self .client .get (self .auth_url2 ())
149
154
150
155
self .assertEqual (400 , response .status_code )
@@ -211,7 +216,8 @@ def test_access_token_get_expire_delta_value(self):
211
216
now = date_now ()
212
217
default_expiration_timedelta = constants .EXPIRE_DELTA
213
218
current_expiration_timedelta = datetime .timedelta (seconds = token .get_expire_delta (reference = now ))
214
- self .assertTrue (abs (current_expiration_timedelta - default_expiration_timedelta ) <= datetime .timedelta (seconds = 1 ))
219
+ self .assertLessEqual (abs (current_expiration_timedelta - default_expiration_timedelta ),
220
+ datetime .timedelta (seconds = 1 ))
215
221
216
222
def test_fetching_access_token_with_invalid_client (self ):
217
223
self .login ()
@@ -259,8 +265,7 @@ def _login_authorize_get_token(self):
259
265
token = json .loads (response .content )
260
266
261
267
for prop in required_props :
262
- self .assertIn (prop , token , "Access token response missing "
263
- "required property: %s" % prop )
268
+ self .assertIn (prop , token , "Access token response missing required property: %s" % prop )
264
269
265
270
return token
266
271
@@ -283,8 +288,7 @@ def test_fetching_access_token_with_invalid_grant_type(self):
283
288
})
284
289
285
290
self .assertEqual (400 , response .status_code )
286
- self .assertEqual ('unsupported_grant_type' , json .loads (response .content )['error' ],
287
- response .content )
291
+ self .assertEqual ('unsupported_grant_type' , json .loads (response .content )['error' ], response .content )
288
292
289
293
def test_fetching_single_access_token (self ):
290
294
constants .SINGLE_ACCESS_TOKEN = True
@@ -361,12 +365,11 @@ def test_refreshing_an_access_token(self):
361
365
})
362
366
363
367
self .assertEqual (400 , response .status_code )
364
- self .assertEqual ('invalid_grant' , json .loads (response .content )['error' ],
365
- response .content )
368
+ self .assertEqual ('invalid_grant' , json .loads (response .content )['error' ], response .content )
366
369
367
370
def test_password_grant_public (self ):
368
371
c = self .get_client ()
369
- c .client_type = 1 # public
372
+ c .client_type = 1 # public
370
373
c .save ()
371
374
372
375
response = self .client .post (self .access_token_url (), {
@@ -385,7 +388,7 @@ def test_password_grant_public(self):
385
388
386
389
def test_password_grant_confidential (self ):
387
390
c = self .get_client ()
388
- c .client_type = 0 # confidential
391
+ c .client_type = 0 # confidential
389
392
c .save ()
390
393
391
394
response = self .client .post (self .access_token_url (), {
@@ -401,7 +404,7 @@ def test_password_grant_confidential(self):
401
404
402
405
def test_password_grant_confidential_no_secret (self ):
403
406
c = self .get_client ()
404
- c .client_type = 0 # confidential
407
+ c .client_type = 0 # confidential
405
408
c .save ()
406
409
407
410
response = self .client .post (self .access_token_url (), {
@@ -415,7 +418,7 @@ def test_password_grant_confidential_no_secret(self):
415
418
416
419
def test_password_grant_invalid_password_public (self ):
417
420
c = self .get_client ()
418
- c .client_type = 1 # public
421
+ c .client_type = 1 # public
419
422
c .save ()
420
423
421
424
response = self .client .post (self .access_token_url (), {
@@ -430,7 +433,7 @@ def test_password_grant_invalid_password_public(self):
430
433
431
434
def test_password_grant_invalid_password_confidential (self ):
432
435
c = self .get_client ()
433
- c .client_type = 0 # confidential
436
+ c .client_type = 0 # confidential
434
437
c .save ()
435
438
436
439
response = self .client .post (self .access_token_url (), {
@@ -475,8 +478,7 @@ def test_access_token_backend(self):
475
478
client = self .get_client ()
476
479
backend = AccessTokenBackend ()
477
480
token = AccessToken .objects .create (user = user , client = client )
478
- authenticated = backend .authenticate (access_token = token .token ,
479
- client = client )
481
+ authenticated = backend .authenticate (access_token = token .token , client = client )
480
482
481
483
self .assertIsNotNone (authenticated )
482
484
@@ -508,7 +510,7 @@ def test_access_token_enforces_SSL(self):
508
510
class ClientFormTest (TestCase ):
509
511
def test_client_form (self ):
510
512
form = ClientForm ({'name' : 'TestName' , 'url' : 'http://127.0.0.1:8000' ,
511
- 'redirect_uri' : 'http://localhost:8000/' })
513
+ 'redirect_uri' : 'http://localhost:8000/' })
512
514
513
515
self .assertFalse (form .is_valid ())
514
516
@@ -597,10 +599,8 @@ def test_clear_expired(self):
597
599
# make sure the grant is gone
598
600
self .assertFalse (Grant .objects .filter (code = code ).exists ())
599
601
# and verify that the AccessToken and RefreshToken exist
600
- self .assertTrue (AccessToken .objects .filter (token = access_token )
601
- .exists ())
602
- self .assertTrue (RefreshToken .objects .filter (token = refresh_token )
603
- .exists ())
602
+ self .assertTrue (AccessToken .objects .filter (token = access_token ).exists ())
603
+ self .assertTrue (RefreshToken .objects .filter (token = refresh_token ).exists ())
604
604
605
605
# refresh the token
606
606
response = self .client .post (self .access_token_url (), {
@@ -617,7 +617,58 @@ def test_clear_expired(self):
617
617
self .assertNotEquals (refresh_token , token ['refresh_token' ])
618
618
619
619
# make sure the orig AccessToken and RefreshToken are gone
620
- self .assertFalse (AccessToken .objects .filter (token = access_token )
621
- .exists ())
622
- self .assertFalse (RefreshToken .objects .filter (token = refresh_token )
623
- .exists ())
620
+ self .assertFalse (AccessToken .objects .filter (token = access_token ).exists ())
621
+ self .assertFalse (RefreshToken .objects .filter (token = refresh_token ).exists ())
622
+
623
+
624
+ class AccessTokenDetailViewTests (TestCase ):
625
+ JSON_CONTENT_TYPE = 'application/json'
626
+
627
+ def setUp (self ):
628
+ super (AccessTokenDetailViewTests , self )
629
+ self .
user = User .
objects .
create_user (
'TEST-USER' ,
'[email protected] ' )
630
+ self .oauth_client = Client .objects .create (client_type = CONFIDENTIAL )
631
+
632
+ def assert_invalid_token_response (self , token ):
633
+ """ Verifies that the view returns an invalid token response for the specified token. """
634
+ url = reverse ('oauth2:access_token_detail' , kwargs = {'token' : token })
635
+ response = self .client .get (url )
636
+ self .assertEqual (response .status_code , 400 )
637
+
638
+ self .assertEqual (response ['Content-Type' ], self .JSON_CONTENT_TYPE )
639
+ self .assertEqual (response .content , json .dumps ({'error' : 'invalid_token' }))
640
+
641
+ def test_invalid_token (self ):
642
+ """
643
+ If the requested token is invalid for any reason (expired, doesn't exist, etc.) the view should return HTTP 400.
644
+ """
645
+ # Non-existent token
646
+ self .assert_invalid_token_response ('abc' )
647
+
648
+ # Expired token
649
+ access_token = AccessToken .objects .create (user = self .user , client = self .oauth_client ,
650
+ expires = datetime .datetime .min )
651
+ self .assert_invalid_token_response (access_token .token )
652
+
653
+ def test_valid_token (self ):
654
+ """ If the token is valid, details about the token should be returned. """
655
+
656
+ expires = datetime .datetime (2016 , 1 , 1 , 0 , 0 , 0 )
657
+ access_token = AccessToken .objects .create (user = self .user , client = self .oauth_client , scope = READ , expires = expires )
658
+
659
+ url = reverse ('oauth2:access_token_detail' , kwargs = {'token' : access_token .token })
660
+
661
+ # Mock datetime.datetime.now() so that we can validate the expiration date
662
+ now = datetime .datetime (2015 , 1 , 1 , 0 , 0 , 0 )
663
+ with mock .patch ('provider.oauth2.models.now' , return_value = now ):
664
+ response = self .client .get (url )
665
+
666
+ self .assertEqual (response .status_code , 200 )
667
+ self .assertEqual (response ['Content-Type' ], self .JSON_CONTENT_TYPE )
668
+
669
+ expected = {
670
+ 'username' : self .user .username ,
671
+ 'scope' : 'read' ,
672
+ 'expires_in' : int ((expires - now ).total_seconds ())
673
+ }
674
+ self .assertEqual (response .content , json .dumps (expected ))
0 commit comments