Skip to content

fix(oauth): use dict list value for multi-resource RFC 8707 token requests#5078

Open
pjaroliya wants to merge 1 commit into
IBM:mainfrom
pjaroliya:fix/oauth-resource-list-async-client-error
Open

fix(oauth): use dict list value for multi-resource RFC 8707 token requests#5078
pjaroliya wants to merge 1 commit into
IBM:mainfrom
pjaroliya:fix/oauth-resource-list-async-client-error

Conversation

@pjaroliya
Copy link
Copy Markdown

When oauth_config["resource"] is a list (e.g. learned from a JWT aud claim with multiple audiences), the token exchange and refresh code converted token_data from a dict into a list[tuple[str, str]] to carry multiple resource= parameters.

httpx only invokes encode_urlencoded_data() — which produces a ByteStream compatible with AsyncClient — when data= is a Mapping. A list of tuples is not a Mapping, so httpx falls through to encode_content(), which wraps the list in an IteratorByteStream (SyncByteStream only). AsyncClient then raises:

RuntimeError: Attempted to send an sync request with an AsyncClient instance.

This error surfaces as "Unexpected Error" on the OAuth callback page and affects every authorization attempt after the first one succeeds (because _persist_learned_audience() stores the JWT aud list into oauth_config).

Fix: keep token_data as a dict and store the resource list directly as its value. httpx's encode_urlencoded_data() already expands list values into repeated key=value pairs, producing the correct
resource=r1&resource=r2 encoding with a ByteStream that AsyncClient accepts.

Affects _exchange_code_for_tokens() and refresh_token() in OAuthManager.

Closes #XXXX

🔗 Related Issue

Closes #


📝 Summary

What does this PR do and why?


🏷️ Type of Change

  • Bug fix
  • Feature / Enhancement
  • Documentation
  • Refactor
  • Chore (deps, CI, tooling)
  • Other (describe below)

🧪 Verification

Check Command Status
Lint suite make lint
Unit tests make test
Coverage ≥ 80% make coverage

✅ Checklist

  • Code formatted (make black isort pre-commit)
  • Tests added/updated for changes
  • Documentation updated (if applicable)
  • No secrets or credentials committed

📓 Notes (optional)

Screenshots, design decisions, or additional context.

…uests

When oauth_config["resource"] is a list (e.g. learned from a JWT aud
claim with multiple audiences), the token exchange and refresh code
converted token_data from a dict into a list[tuple[str, str]] to carry
multiple resource= parameters.

httpx only invokes encode_urlencoded_data() — which produces a ByteStream
compatible with AsyncClient — when data= is a Mapping.  A list of tuples
is not a Mapping, so httpx falls through to encode_content(), which wraps
the list in an IteratorByteStream (SyncByteStream only).  AsyncClient then
raises:

  RuntimeError: Attempted to send an sync request with an AsyncClient instance.

This error surfaces as "Unexpected Error" on the OAuth callback page and
affects every authorization attempt after the first one succeeds (because
_persist_learned_audience() stores the JWT aud list into oauth_config).

Fix: keep token_data as a dict and store the resource list directly as its
value.  httpx's encode_urlencoded_data() already expands list values into
repeated key=value pairs, producing the correct
resource=r1&resource=r2 encoding with a ByteStream that AsyncClient accepts.

Affects _exchange_code_for_tokens() and refresh_token() in OAuthManager.

Closes #XXXX

Signed-off-by: pjaroliya <pjaroliya@webmd.net>
Signed-off-by: pjaroliya <pjaroliya@pulsepoint.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants