@@ -205,12 +205,12 @@ def __init__(
205205 )
206206 self ._initialized = False
207207
208- def _extract_resource_metadata_from_www_auth (self , init_response : httpx .Response ) -> str | None :
208+ def _extract_field_from_www_auth (self , init_response : httpx .Response , field_name : str ) -> str | None :
209209 """
210- Extract protected resource metadata URL from WWW-Authenticate header as per RFC9728 .
210+ Extract field from WWW-Authenticate header.
211211
212212 Returns:
213- Resource metadata URL if found in WWW-Authenticate header, None otherwise
213+ Field value if found in WWW-Authenticate header, None otherwise
214214 """
215215 if not init_response or init_response .status_code != 401 :
216216 return None
@@ -219,8 +219,8 @@ def _extract_resource_metadata_from_www_auth(self, init_response: httpx.Response
219219 if not www_auth_header :
220220 return None
221221
222- # Pattern matches: resource_metadata="url " or resource_metadata=url (unquoted)
223- pattern = r'resource_metadata =(?:"([^"]+)"|([^\s,]+))'
222+ # Pattern matches: field_name="value " or field_name=value (unquoted)
223+ pattern = rf' { field_name } =(?:"([^"]+)"|([^\s,]+))'
224224 match = re .search (pattern , www_auth_header )
225225
226226 if match :
@@ -229,29 +229,23 @@ def _extract_resource_metadata_from_www_auth(self, init_response: httpx.Response
229229
230230 return None
231231
232+ def _extract_resource_metadata_from_www_auth (self , init_response : httpx .Response ) -> str | None :
233+ """
234+ Extract protected resource metadata URL from WWW-Authenticate header as per RFC9728.
235+
236+ Returns:
237+ Resource metadata URL if found in WWW-Authenticate header, None otherwise
238+ """
239+ return self ._extract_field_from_www_auth (init_response , "resource_metadata" )
240+
232241 def _extract_scope_from_www_auth (self , init_response : httpx .Response ) -> str | None :
233242 """
234243 Extract scope parameter from WWW-Authenticate header as per RFC6750.
235244
236245 Returns:
237246 Scope string if found in WWW-Authenticate header, None otherwise
238247 """
239- if not init_response or init_response .status_code != 401 :
240- return None
241-
242- www_auth_header = init_response .headers .get ("WWW-Authenticate" )
243- if not www_auth_header :
244- return None
245-
246- # Pattern matches: scope="value" or scope=value (unquoted)
247- pattern = r'scope=(?:"([^"]+)"|([^\s,]+))'
248- match = re .search (pattern , www_auth_header )
249-
250- if match :
251- # Return quoted value if present, otherwise unquoted value
252- return match .group (1 ) or match .group (2 )
253-
254- return None
248+ return self ._extract_field_from_www_auth (init_response , "scope" )
255249
256250 async def _discover_protected_resource (self , init_response : httpx .Response ) -> httpx .Request :
257251 # RFC9728: Try to extract resource_metadata URL from WWW-Authenticate header of the initial response
0 commit comments