Skip to content

Commit b0f0222

Browse files
committed
DRY up the www-authenticate header extraction
1 parent fbde0f5 commit b0f0222

File tree

1 file changed

+15
-21
lines changed

1 file changed

+15
-21
lines changed

src/mcp/client/auth.py

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)