@@ -15,7 +15,7 @@ public class AuthorizationHelpers
1515 private static readonly Lazy < HttpClient > _defaultHttpClient = new ( ( ) => new HttpClient ( ) ) ;
1616
1717 /// <summary>
18- /// The common well-known path prefix for resource metadata.
18+ /// The well-known path prefix for resource metadata.
1919 /// </summary>
2020 private static readonly string WellKnownPathPrefix = "/.well-known/" ;
2121
@@ -82,30 +82,27 @@ private static bool VerifyResourceMatch(ProtectedResourceMetadata protectedResou
8282 }
8383
8484 /// <summary>
85- /// Normalizes a URI for consistent comparison by removing ports and trailing slashes .
85+ /// Normalizes a URI for consistent comparison.
8686 /// </summary>
8787 /// <param name="uri">The URI to normalize.</param>
8888 /// <returns>A normalized string representation of the URI.</returns>
8989 private static string NormalizeUri ( Uri uri )
9090 {
91- // Create a builder that will normalize the URI
9291 var builder = new UriBuilder ( uri )
9392 {
94- Port = - 1 // Always remove port specification regardless of whether it's default or not
93+ Port = - 1 // Always remove port
9594 } ;
9695
97- // Ensure consistent path representation (remove trailing slash if it's just "/")
9896 if ( builder . Path == "/" )
9997 {
10098 builder . Path = string . Empty ;
10199 }
102- // Remove trailing slash for other paths
103100 else if ( builder . Path . Length > 1 && builder . Path . EndsWith ( "/" ) )
104101 {
105102 builder . Path = builder . Path . TrimEnd ( '/' ) ;
106103 }
107104
108- return builder . Uri . ToString ( ) . TrimEnd ( '/' ) ;
105+ return builder . Uri . ToString ( ) ;
109106 }
110107
111108 /// <summary>
@@ -116,38 +113,27 @@ private static string NormalizeUri(Uri uri)
116113 /// <exception cref="InvalidOperationException">Thrown when the URI does not contain a valid well-known path.</exception>
117114 private Uri ExtractBaseResourceUri ( Uri metadataUri )
118115 {
119- // Get the absolute URI path to check for well-known path
120- string absoluteUriString = metadataUri . AbsoluteUri ;
116+ // Check for well-known path
117+ int wellKnownIndex = metadataUri . AbsolutePath . IndexOf ( WellKnownPathPrefix , StringComparison . OrdinalIgnoreCase ) ;
121118
122- // Find the well-known path index directly with string operations
123- // This avoids the allocation from WellKnownPathPrefix.AsSpan()
124- int wellKnownIndex = absoluteUriString . IndexOf ( WellKnownPathPrefix , StringComparison . OrdinalIgnoreCase ) ;
125-
126- // Validate that the URL contains the well-known path
127- if ( wellKnownIndex <= 0 )
119+ // Validate the URL contains a valid well-known path
120+ if ( wellKnownIndex < 0 )
128121 {
129122 throw new InvalidOperationException (
130123 $ "Resource metadata URL '{ metadataUri } ' does not contain a valid well-known path format (/.well-known/)") ;
131124 }
132125
133- // Get just the path segment before .well-known directly on the URI
134- int wellKnownPathIndex = metadataUri . AbsolutePath . IndexOf ( WellKnownPathPrefix , StringComparison . OrdinalIgnoreCase ) ;
135-
136- // Create a new URI builder using the original scheme and authority
126+ // Create URI with just the base part
137127 var baseUriBuilder = new UriBuilder ( metadataUri )
138128 {
139- Path = wellKnownPathIndex > 0 ? metadataUri . AbsolutePath . Substring ( 0 , wellKnownPathIndex ) : "/" ,
129+ Path = wellKnownIndex > 0 ? metadataUri . AbsolutePath . Substring ( 0 , wellKnownIndex ) : "/" ,
140130 Fragment = string . Empty ,
141- Query = string . Empty
131+ Query = string . Empty ,
132+ Port = - 1 // Remove port
142133 } ;
143134
144- // Ensure the path ends with exactly one slash for consistency
145- string path = baseUriBuilder . Path ;
146- if ( string . IsNullOrEmpty ( path ) )
147- {
148- baseUriBuilder . Path = "/" ;
149- }
150- else if ( ! path . EndsWith ( "/" ) )
135+ // Ensure path ends with a slash
136+ if ( ! baseUriBuilder . Path . EndsWith ( "/" ) )
151137 {
152138 baseUriBuilder . Path += "/" ;
153139 }
@@ -230,35 +216,34 @@ public async Task<ProtectedResourceMetadata> ExtractProtectedResourceMetadata(
230216 /// <returns>The value of the parameter, or null if not found.</returns>
231217 private static string ? ParseWwwAuthenticateParameters ( string parameters , string parameterName )
232218 {
233- if ( ! parameters . Contains ( parameterName , StringComparison . OrdinalIgnoreCase ) )
219+ if ( parameters . IndexOf ( parameterName , StringComparison . OrdinalIgnoreCase ) == - 1 )
234220 {
235221 return null ;
236222 }
237223
238- var parts = parameters . Split ( ',' ) ;
239- foreach ( var part in parts )
224+ foreach ( var part in parameters . Split ( ',' ) )
240225 {
241- int equalsIndex = part . IndexOf ( '=' ) ;
242- if ( equalsIndex <= 0 || equalsIndex == part . Length - 1 )
243- {
244- continue ;
245- }
226+ string trimmedPart = part . Trim ( ) ;
227+ int equalsIndex = trimmedPart . IndexOf ( '=' ) ;
246228
247- string key = part . Substring ( 0 , equalsIndex ) . Trim ( ) ;
248-
249- if ( string . IsNullOrEmpty ( key ) || ! string . Equals ( key , parameterName , StringComparison . OrdinalIgnoreCase ) )
229+ if ( equalsIndex <= 0 )
250230 {
251231 continue ;
252232 }
253-
254- string value = part . Substring ( equalsIndex + 1 ) . Trim ( ) ;
255-
256- if ( value . Length >= 2 && value [ 0 ] == '"' && value [ ^ 1 ] == '"' )
233+
234+ string key = trimmedPart . Substring ( 0 , equalsIndex ) . Trim ( ) ;
235+
236+ if ( string . Equals ( key , parameterName , StringComparison . OrdinalIgnoreCase ) )
257237 {
258- value = value . Substring ( 1 , value . Length - 2 ) ;
238+ string value = trimmedPart . Substring ( equalsIndex + 1 ) . Trim ( ) ;
239+
240+ if ( value . StartsWith ( "\" " ) && value . EndsWith ( "\" " ) )
241+ {
242+ value = value . Substring ( 1 , value . Length - 2 ) ;
243+ }
244+
245+ return value ;
259246 }
260-
261- return value ;
262247 }
263248
264249 return null ;
0 commit comments