@@ -565,6 +565,14 @@ def test_invalid_configuration_encoding_is_rejected(field):
565565 "https://inventory.example.com/stock item" ,
566566 "https://inventory.example.com/%invalid" ,
567567 "https://[invalid" ,
568+ "1inventory:stock" ,
569+ "urn%3Ainventory" ,
570+ "urn:inventory%" ,
571+ "urn:inventory%2" ,
572+ "urn:inventory%2G" ,
573+ "urn:inventory%G2" ,
574+ "urn:inventory%%20" ,
575+ "urn:inventorý" ,
568576 ],
569577)
570578def test_resource_must_be_an_absolute_uri_without_a_fragment (resource ):
@@ -578,6 +586,9 @@ def test_resource_must_be_an_absolute_uri_without_a_fragment(resource):
578586 {"resource" : "urn:example:inventory" },
579587 {"resource" : "https://inventory.example.com/stock?region=eu&category=%23parts" },
580588 {"resource" : "http://inventory.example.com" },
589+ {"resource" : "URN:example:inventory" },
590+ {"resource" : "inventory+v1.2-test:stock%2fitems%20eu?category=%23" },
591+ {"resource" : "https://[::1]/caf%C3%A9?encoded=%00%ff" },
581592 {"audience" : "inventory" },
582593 ],
583594)
@@ -594,6 +605,22 @@ def test_valid_resource_identifiers_and_provider_audiences_are_preserved(http, s
594605 assert other not in fields
595606
596607
608+ @pytest .mark .parametrize ("suffix" , ["%" , "%4" , "%4G" , "#" ])
609+ def test_long_resources_with_invalid_suffixes_are_rejected_before_loading_credentials (http , suffix ):
610+ secrets = []
611+
612+ def load_secret ():
613+ secrets .append ("test-secret" )
614+ return secrets [- 1 ]
615+
616+ resource = "urn:inventory:" + "a%41" * 25_000 + suffix
617+ with pytest .raises (ValueError , match = "absolute URI without a fragment" ):
618+ client (resource = resource , client_secret = load_secret )
619+
620+ assert secrets == []
621+ assert http .requests == []
622+
623+
597624def test_secret_lookup_does_not_expire_a_new_short_lived_token (http , clock ):
598625 def load_secret ():
599626 clock .advance (2 )
0 commit comments