fix: match complete www-authenticate auth params#3050
Conversation
|
I think this PR fixes the substring-param-name case from #3009, but there is one adjacent case it still misses: field-looking text inside a quoted auth-param value. Using this PR's proposed pattern: import re
header = 'Bearer error="invalid_token", error_description="missing scope=wrong", scope="from-header"'
field_pattern = re.escape("scope")
pattern = rf'(?:^|[\s,]){field_pattern}=(?:"([^"]+)"|([^\s,]+))'
match = re.search(pattern, header)
print(match.group(1) or match.group(2))
# wrong"
# expected: from-headerThis matters because MCP/OAuth challenges can carry I reproduced the current behavior on AI-assisted (Claude/Codex) for navigation and review; change authored and understood by me. |
There was a problem hiding this comment.
I differential-tested this against main and the two sibling PRs for #3009 (#3012, #3041) — full matrix in #3009 (comment).
This is the strongest of the three in my testing:
- Fixes both reported shadowing cases, and also two variants the issue did not mention: unquoted-value shadowing (
Bearer as_scope=x, scope=files→mainreturnsx) and comma separators without a following space (error_scope="a",scope="files"→mainreturnsa). - No behavior change in any other probe — including multi-challenge headers (
Basic …, Bearer …,DPoP …, Bearer …) and non-Bearer schemes, both of which regress in one of the sibling PRs. re.escape(field_name)is a nice hardening touch the current code lacks.tests/client/test_auth.py: 137 passed, 0 failed on this branch.
Two optional follow-ups, neither blocking:
- RFC 7235 auth-param names are case-insensitive, so
Bearer SCOPE="files"should match ascopelookup — addingre.IGNORECASEto the search would cover it (pre-existing gap, all implementations fail it today). - Escaped quotes inside quoted values (
scope="say \"hi, there") still truncate at the comma — also pre-existing; #3012 has parsing logic for this if it is ever wanted as a follow-up.
Fixes #3009
Updates
extract_field_from_www_authso it only matches completeWWW-Authenticateauth-param names. This prevents fields likescopefrom matching inside longer names such aserror_scopeorcustom_scope, and preventsresource_metadatafrom matching insidex_resource_metadata.Motivation and Context
The previous regex searched for the field name without a boundary, so a decoy parameter could shadow the real auth-param value or return a value when the requested parameter was not present.
This matters for OAuth discovery because
resource_metadatafromWWW-Authenticatecontrols the protected resource metadata URL selection.How Has This Been Tested?
Tested locally with:
Scenarios covered:
error_scopebefore realscopecustom_scopewithout realscopex_resource_metadatabefore realresource_metadatax_resource_metadatawithout realresource_metadataBreaking Changes
None.
Types of changes
Checklist
Additional context
The fix escapes the requested field name and requires it to appear at the start of the header or after an auth-param separator, so only complete auth-param names are matched.