1111
1212from django .core .management import call_command
1313from django .http import JsonResponse
14+
1415try :
1516 from django .urls import reverse
1617except ImportError :
@@ -51,6 +52,8 @@ class TokenTestCase(TestCase):
5152 Token Request to the Token Endpoint to obtain a Token Response
5253 when using the Authorization Code Flow.
5354 """
55+ SCOPE = 'openid email'
56+ SCOPE_LIST = SCOPE .split (' ' )
5457
5558 def setUp (self ):
5659 call_command ('creatersakey' )
@@ -64,7 +67,7 @@ def _password_grant_post_data(self, scope=None):
6467 'username' : 'johndoe' ,
6568 'password' : '1234' ,
6669 'grant_type' : 'password' ,
67- 'scope' : 'openid email' ,
70+ 'scope' : TokenTestCase . SCOPE ,
6871 }
6972 if scope is not None :
7073 result ['scope' ] = ' ' .join (scope )
@@ -102,6 +105,16 @@ def _refresh_token_post_data(self, refresh_token, scope=None):
102105
103106 return post_data
104107
108+ def _client_credentials_post_data (self , scope = None ):
109+ post_data = {
110+ 'client_id' : self .client .client_id ,
111+ 'client_secret' : self .client .client_secret ,
112+ 'grant_type' : 'client_credentials' ,
113+ }
114+ if scope is not None :
115+ post_data ['scope' ] = ' ' .join (scope )
116+ return post_data
117+
105118 def _post_request (self , post_data , extras = {}):
106119 """
107120 Makes a request to the token endpoint by sending the
@@ -127,7 +140,7 @@ def _create_code(self, scope=None):
127140 code = create_code (
128141 user = self .user ,
129142 client = self .client ,
130- scope = (scope if scope else [ 'openid' , 'email' ] ),
143+ scope = (scope if scope else TokenTestCase . SCOPE_LIST ),
131144 nonce = FAKE_NONCE ,
132145 is_authentication = True )
133146 code .save ()
@@ -227,7 +240,11 @@ def test_password_grant_full_response(self):
227240 self .check_password_grant (scope = ['openid' , 'email' ])
228241
229242 def test_password_grant_scope (self ):
230- self .check_password_grant (scope = ['openid' , 'profile' ])
243+ scopes_list = ['openid' , 'profile' ]
244+
245+ self .client .scope = scopes_list
246+ self .client .save ()
247+ self .check_password_grant (scope = scopes_list )
231248
232249 @override_settings (OIDC_TOKEN_EXPIRE = 120 ,
233250 OIDC_GRANT_TYPE_PASSWORD_ENABLE = True )
@@ -361,7 +378,7 @@ def do_refresh_token_check(self, scope=None):
361378
362379 # Retrieve refresh token
363380 code = self ._create_code ()
364- self .assertEqual (code .scope , [ 'openid' , 'email' ] )
381+ self .assertEqual (code .scope , TokenTestCase . SCOPE_LIST )
365382 post_data = self ._auth_code_post_data (code = code .code )
366383 start_time = time .time ()
367384 with patch ('oidc_provider.lib.utils.token.time.time' ) as time_func :
@@ -661,7 +678,7 @@ def test_additional_idtoken_processing_hook_one_element_in_tuple(self):
661678
662679 @override_settings (
663680 OIDC_IDTOKEN_PROCESSING_HOOK = [
664- 'oidc_provider.tests.app.utils.fake_idtoken_processing_hook' ,
681+ 'oidc_provider.tests.app.utils.fake_idtoken_processing_hook' ,
665682 ]
666683 )
667684 def test_additional_idtoken_processing_hook_one_element_in_list (self ):
@@ -682,8 +699,8 @@ def test_additional_idtoken_processing_hook_one_element_in_list(self):
682699
683700 @override_settings (
684701 OIDC_IDTOKEN_PROCESSING_HOOK = [
685- 'oidc_provider.tests.app.utils.fake_idtoken_processing_hook' ,
686- 'oidc_provider.tests.app.utils.fake_idtoken_processing_hook2' ,
702+ 'oidc_provider.tests.app.utils.fake_idtoken_processing_hook' ,
703+ 'oidc_provider.tests.app.utils.fake_idtoken_processing_hook2' ,
687704 ]
688705 )
689706 def test_additional_idtoken_processing_hook_two_elements_in_list (self ):
@@ -754,7 +771,7 @@ def test_additional_idtoken_processing_hook_kwargs(self):
754771 kwargs_passed = id_token .get ('kwargs_passed_to_processing_hook' )
755772 assert kwargs_passed
756773 self .assertTrue (kwargs_passed .get ('token' ).startswith (
757- '<Token: Some Client -' ))
774+ '<Token: Some Client -' ))
758775 self .assertEqual (kwargs_passed .get ('request' ),
759776 "<WSGIRequest: POST '/openid/token'>" )
760777 self .assertEqual (set (kwargs_passed .keys ()), {'token' , 'request' })
@@ -797,11 +814,7 @@ def test_client_credentials_grant_type(self):
797814 self .client .scope = fake_scopes_list
798815 self .client .save ()
799816
800- post_data = {
801- 'client_id' : self .client .client_id ,
802- 'client_secret' : self .client .client_secret ,
803- 'grant_type' : 'client_credentials' ,
804- }
817+ post_data = self ._client_credentials_post_data ()
805818 response = self ._post_request (post_data )
806819 response_dict = json .loads (response .content .decode ('utf-8' ))
807820
@@ -857,12 +870,85 @@ def test_printing_token_used_by_client_credentials_grant_type(self):
857870 self .client .scope = ['something' ]
858871 self .client .save ()
859872
860- post_data = {
861- 'client_id' : self .client .client_id ,
862- 'client_secret' : self .client .client_secret ,
863- 'grant_type' : 'client_credentials' ,
864- }
865- response = self ._post_request (post_data )
873+ response = self ._post_request (self ._client_credentials_post_data ())
866874 response_dict = json .loads (response .content .decode ('utf-8' ))
867875 token = Token .objects .get (access_token = response_dict ['access_token' ])
868876 self .assertTrue (str (token ))
877+
878+ @override_settings (OIDC_GRANT_TYPE_PASSWORD_ENABLE = True )
879+ def test_requested_scope (self ):
880+ # GRANT_TYPE=PASSWORD
881+ response = self ._post_request (
882+ post_data = self ._password_grant_post_data (['openid' , 'invalid_scope' ]),
883+ extras = self ._password_grant_auth_header ()
884+ )
885+
886+ response_dict = json .loads (response .content .decode ('utf-8' ))
887+
888+ # It should fail when client requested an invalid scope.
889+ self .assertEqual (400 , response .status_code )
890+ self .assertEqual ('invalid_scope' , response_dict ['error' ])
891+
892+ # happy path: no scope
893+ response = self ._post_request (
894+ post_data = self ._password_grant_post_data ([]),
895+ extras = self ._password_grant_auth_header ()
896+ )
897+
898+ response_dict = json .loads (response .content .decode ('utf-8' ))
899+ self .assertEqual (200 , response .status_code )
900+ self .assertEqual (TokenTestCase .SCOPE , response_dict ['scope' ])
901+
902+ # happy path: single scope
903+ response = self ._post_request (
904+ post_data = self ._password_grant_post_data (['email' ]),
905+ extras = self ._password_grant_auth_header ()
906+ )
907+
908+ response_dict = json .loads (response .content .decode ('utf-8' ))
909+ self .assertEqual (200 , response .status_code )
910+ self .assertEqual ('email' , response_dict ['scope' ])
911+
912+ # happy path: multiple scopes
913+ response = self ._post_request (
914+ post_data = self ._password_grant_post_data (['email' , 'openid' ]),
915+ extras = self ._password_grant_auth_header ()
916+ )
917+
918+ # GRANT_TYPE=CLIENT_CREDENTIALS
919+ response_dict = json .loads (response .content .decode ('utf-8' ))
920+ self .assertEqual (200 , response .status_code )
921+ self .assertEqual ('email openid' , response_dict ['scope' ])
922+
923+ response = self ._post_request (
924+ post_data = self ._client_credentials_post_data (['openid' , 'invalid_scope' ])
925+ )
926+
927+ response_dict = json .loads (response .content .decode ('utf-8' ))
928+
929+ # It should fail when client requested an invalid scope.
930+ self .assertEqual (400 , response .status_code )
931+ self .assertEqual ('invalid_scope' , response_dict ['error' ])
932+
933+ # happy path: no scope
934+ response = self ._post_request (post_data = self ._client_credentials_post_data ())
935+
936+ response_dict = json .loads (response .content .decode ('utf-8' ))
937+ self .assertEqual (200 , response .status_code )
938+ self .assertEqual (TokenTestCase .SCOPE , response_dict ['scope' ])
939+
940+ # happy path: single scope
941+ response = self ._post_request (post_data = self ._client_credentials_post_data (['email' ]))
942+
943+ response_dict = json .loads (response .content .decode ('utf-8' ))
944+ self .assertEqual (200 , response .status_code )
945+ self .assertEqual ('email' , response_dict ['scope' ])
946+
947+ # happy path: multiple scopes
948+ response = self ._post_request (
949+ post_data = self ._client_credentials_post_data (['email' , 'openid' ])
950+ )
951+
952+ response_dict = json .loads (response .content .decode ('utf-8' ))
953+ self .assertEqual (200 , response .status_code )
954+ self .assertEqual ('email openid' , response_dict ['scope' ])
0 commit comments