@@ -265,6 +265,21 @@ describe('OAuth Authorization', () => {
265265 expect ( url . toString ( ) ) . toBe ( 'https://resource.example.com/.well-known/oauth-protected-resource/path/name' ) ;
266266 } ) ;
267267
268+ it ( 'normalizes duplicate trailing slashes in path before metadata discovery' , async ( ) => {
269+ mockFetch . mockResolvedValueOnce ( {
270+ ok : true ,
271+ status : 200 ,
272+ json : async ( ) => validMetadata
273+ } ) ;
274+
275+ const metadata = await discoverOAuthProtectedResourceMetadata ( 'https://resource.example.com/path/name//' ) ;
276+ expect ( metadata ) . toEqual ( validMetadata ) ;
277+ const calls = mockFetch . mock . calls ;
278+ expect ( calls . length ) . toBe ( 1 ) ;
279+ const [ url ] = calls [ 0 ] ! ;
280+ expect ( url . toString ( ) ) . toBe ( 'https://resource.example.com/.well-known/oauth-protected-resource/path/name' ) ;
281+ } ) ;
282+
268283 it ( 'preserves query parameters in path-aware discovery' , async ( ) => {
269284 mockFetch . mockResolvedValueOnce ( {
270285 ok : true ,
@@ -853,6 +868,17 @@ describe('OAuth Authorization', () => {
853868 ] ) ;
854869 } ) ;
855870
871+ it ( 'normalizes trailing slashes in server URLs before discovery' , ( ) => {
872+ const urls = buildDiscoveryUrls ( 'https://auth.example.com/tenant1//' ) ;
873+
874+ expect ( urls ) . toHaveLength ( 3 ) ;
875+ expect ( urls . map ( u => u . url . toString ( ) ) ) . toEqual ( [
876+ 'https://auth.example.com/.well-known/oauth-authorization-server/tenant1' ,
877+ 'https://auth.example.com/.well-known/openid-configuration/tenant1' ,
878+ 'https://auth.example.com/tenant1/.well-known/openid-configuration'
879+ ] ) ;
880+ } ) ;
881+
856882 it ( 'handles URL object input' , ( ) => {
857883 const urls = buildDiscoveryUrls ( new URL ( 'https://auth.example.com/tenant1' ) ) ;
858884
0 commit comments