@@ -79,29 +79,16 @@ def test_should_throw_error_if_jwt_payload_missing_iss(self):
7979 == MCPAuthTokenVerificationExceptionCode .INVALID_TOKEN
8080 )
8181
82- def test_should_throw_error_if_jwt_payload_missing_client_id (self ):
83- # Test different invalid JWT payloads
84- jwt_missing_client_id = create_jwt (
85- {"iss" : "https://logto.io/" , "sub" : "user12345" }
86- )
87- jwt_invalid_client_id_type = create_jwt (
82+ def test_should_throw_error_if_client_id_is_not_string (self ):
83+ token = create_jwt (
8884 {"iss" : "https://logto.io/" , "client_id" : 12345 , "sub" : "user12345" }
8985 )
90- jwt_empty_client_id = create_jwt (
91- {"iss" : "https://logto.io/" , "client_id" : "" , "sub" : "user12345" }
92- )
9386
94- for token in [
95- jwt_missing_client_id ,
96- jwt_invalid_client_id_type ,
97- jwt_empty_client_id ,
98- ]:
99- with pytest .raises (MCPAuthTokenVerificationException ) as exc_info :
100- verify_jwt (token )
101- assert (
102- exc_info .value .code
103- == MCPAuthTokenVerificationExceptionCode .INVALID_TOKEN
104- )
87+ with pytest .raises (MCPAuthTokenVerificationException ) as exc_info :
88+ verify_jwt (token )
89+ assert (
90+ exc_info .value .code == MCPAuthTokenVerificationExceptionCode .INVALID_TOKEN
91+ )
10592
10693 def test_should_throw_error_if_jwt_payload_missing_sub (self ):
10794 # Test different invalid JWT payloads
@@ -226,3 +213,53 @@ def test_should_return_verified_jwt_payload_without_scopes(self):
226213 assert result .subject == claims ["sub" ]
227214 assert result .audience == claims ["aud" ]
228215 assert result .scopes == []
216+
217+ def test_should_return_verified_jwt_payload_without_client_id (self ):
218+ # Create JWT without client_id
219+ claims = {
220+ "iss" : "https://logto.io/" ,
221+ "sub" : "user12345" ,
222+ "aud" : "audience12345" ,
223+ }
224+ jwt_token = create_jwt (claims )
225+
226+ # Verify
227+ result = verify_jwt (jwt_token )
228+
229+ # Assertions
230+ assert result .issuer == claims ["iss" ]
231+ assert result .client_id is None
232+ assert result .subject == claims ["sub" ]
233+ assert result .audience == claims ["aud" ]
234+ assert result .scopes == []
235+
236+ # Empty client_id should not raise an error
237+ claims ["client_id" ] = ""
238+ claims ["azp" ] = "client12345" # Should be ignored if client_id is a string
239+ jwt_token = create_jwt (claims )
240+ result = verify_jwt (jwt_token )
241+ assert result .issuer == claims ["iss" ]
242+ assert result .client_id == ""
243+ assert result .subject == claims ["sub" ]
244+ assert result .audience == claims ["aud" ]
245+ assert result .scopes == []
246+
247+ def test_should_fall_back_to_azp_if_client_id_is_missing (self ):
248+ # Create JWT with azp instead of client_id
249+ claims = {
250+ "iss" : "https://logto.io/" ,
251+ "azp" : "client12345" ,
252+ "sub" : "user12345" ,
253+ "aud" : "audience12345" ,
254+ }
255+ jwt_token = create_jwt (claims )
256+
257+ # Verify
258+ result = verify_jwt (jwt_token )
259+
260+ # Assertions
261+ assert result .issuer == claims ["iss" ]
262+ assert result .client_id == claims ["azp" ]
263+ assert result .subject == claims ["sub" ]
264+ assert result .audience == claims ["aud" ]
265+ assert result .scopes == []
0 commit comments