Skip to content

Python MGMT SDK: SDK making malformed request for OAuth access tokens in v 3.0.0#507

Merged
BinoyOza-okta merged 4 commits intomasterfrom
OKTA-1105052
Mar 6, 2026
Merged

Python MGMT SDK: SDK making malformed request for OAuth access tokens in v 3.0.0#507
BinoyOza-okta merged 4 commits intomasterfrom
OKTA-1105052

Conversation

@BinoyOza-okta
Copy link
Contributor

@BinoyOza-okta BinoyOza-okta commented Mar 4, 2026

fix: resolve OAuth 2.0 duplicate parameter error in token requests

Fixed a critical issue where OAuth 2.0 token requests were failing due to duplicate client_assertion parameters being sent both in the URL query string and the request body, causing "400 Bad Request" errors.

Changes:

  • Fixed duplicate parameter issue in oauth.py by sending all OAuth parameters in the request body only (per RFC 6749 spec)
  • Removed parameters from URL query string in token endpoint requests
  • Fixed form data encoding in http_client.py for application/x-www-form-urlencoded content type by allowing aiohttp to handle encoding automatically
  • Removed unused imports (urlencode, quote) from oauth.py
  • Cleaned up debug print statements

Technical Details:

  • OAuth 2.0 token endpoint requests should send parameters in POST body, not URL query string (RFC 6749 Section 3.2)
  • When Content-Type is application/x-www-form-urlencoded, aiohttp handles encoding automatically when the header is not manually set
  • This fix ensures compatibility with Okta OAuth applications, including those with DPoP enabled (requires DPoP to be disabled in app settings)

Affected Files:

  • okta/oauth.py: Removed URL query parameter encoding, send all params in body
  • okta/http_client.py: Fixed form data handling for URL-encoded content

Testing:

  • Verified OAuth authentication works with private key JWT
  • Confirmed no duplicate parameter errors
  • Validated successful user API requests

Fixes authentication failures when using authorizationMode: "PrivateKey"
with client credentials grant type.

Resolves:

BinoyOza-okta added a commit that referenced this pull request Mar 5, 2026
Fixed OAuth 2.0 authentication failure caused by duplicate client_assertion
parameters being sent in both URL query string and request body. Also fixed
critical shared state mutation bug in HTTP client.

OAuth Fix:
- Send all OAuth parameters in request body only (per RFC 6749)
- Remove parameters from URL query string in token endpoint
- Update oauth.mustache template to prevent regression on code regeneration
- Remove unused imports (urlencode, quote) from oauth.py

HTTP Client Security Fix:
- Fix shared header mutation by using local copies instead of mutating
  self._default_headers (addresses critical security issue where headers
  were permanently modified across requests)
- Fix form data encoding for application/x-www-form-urlencoded
- Ensure header isolation between requests

Version Alignment:
- Update PYTHON_REQUIRES from ">=3.9" to ">=3.10" to align with CI matrix
- Update both setup.py and setup.mustache template

Comprehensive Unit Tests:
- Added 9 comprehensive unit tests (all passing)
- Test OAuth parameter placement (body vs URL)
- Test header isolation and no mutation
- Test form data encoding and file uploads
- Test branching logic for file vs non-file forms
- Validates all security fixes work correctly

This resolves "400 Bad Request - Duplicate parameter provided" errors
when using authorizationMode: "PrivateKey" with client credentials flow
and prevents header pollution between requests.

Addresses all critical review comments from PR #507 code review.

Files changed:
- okta/oauth.py
- okta/http_client.py
- openapi/templates/okta/oauth.mustache
- setup.py
- openapi/templates/setup.mustache

Files added:
- test_oauth_http_client.py (comprehensive test suite)
- test_header_mutation.py (standalone header test)
- UNIT_TESTS_SUMMARY.md (test documentation)

Testing:
- All 9 unit tests pass
- Verified OAuth authentication works correctly with private key JWT
- Verified headers are not mutated between requests
- All HTTP client operations maintain isolated header state
- Form data and file uploads validated
Fixed a critical issue where OAuth 2.0 token requests were failing due to duplicate client_assertion parameters being sent both in the URL query string and the request body, causing "400 Bad Request" errors.

Changes:
- Fixed duplicate parameter issue in oauth.py by sending all OAuth parameter  in the request body only (per RFC 6749 spec)
- Removed parameters from URL query string in token endpoint requests
- Fixed form data encoding in http_client.py for application/x-www-form-urlencoded
  content type by allowing aiohttp to handle encoding automatically
- Removed unused imports (urlencode, quote) from oauth.py
- Cleaned up debug print statements

Technical Details:
- OAuth 2.0 token endpoint requests should send parameters in POST body,
  not URL query string (RFC 6749 Section 3.2)
- When Content-Type is application/x-www-form-urlencoded, aiohttp handles
  encoding automatically when the header is not manually set
- This fix ensures compatibility with Okta OAuth applications, including
  those with DPoP enabled (requires DPoP to be disabled in app settings)

Affected Files:
- okta/oauth.py: Removed URL query parameter encoding, send all params in body
- okta/http_client.py: Fixed form data handling for URL-encoded content

Fixes authentication failures when using authorizationMode: "PrivateKey"
with client credentials grant type.
…#504 contains the permanent fix for this issue. Once it's merged will sync it.
Fixed OAuth 2.0 authentication failure caused by duplicate client_assertion
parameters being sent in both URL query string and request body. Also fixed
critical shared state mutation bug in HTTP client.

OAuth Fix:
- Send all OAuth parameters in request body only (per RFC 6749)
- Remove parameters from URL query string in token endpoint
- Update oauth.mustache template to prevent regression on code regeneration
- Remove unused imports (urlencode, quote) from oauth.py

HTTP Client Security Fix:
- Fix shared header mutation by using local copies instead of mutating
  self._default_headers (addresses critical security issue where headers
  were permanently modified across requests)
- Fix form data encoding for application/x-www-form-urlencoded
- Ensure header isolation between requests

Version Alignment:
- Update PYTHON_REQUIRES from ">=3.9" to ">=3.10" to align with CI matrix
- Update both setup.py and setup.mustache template

Comprehensive Unit Tests:
- Added 9 comprehensive unit tests (all passing)
- Test OAuth parameter placement (body vs URL)
- Test header isolation and no mutation
- Test form data encoding and file uploads
- Test branching logic for file vs non-file forms
- Validates all security fixes work correctly

This resolves "400 Bad Request - Duplicate parameter provided" errors
when using authorizationMode: "PrivateKey" with client credentials flow
and prevents header pollution between requests.

Addresses all critical review comments from PR #507 code review.

Files changed:
- okta/oauth.py
- okta/http_client.py
- openapi/templates/okta/oauth.mustache
- setup.py
- openapi/templates/setup.mustache

Files added:
- test_oauth_http_client.py (comprehensive test suite)
- test_header_mutation.py (standalone header test)
- UNIT_TESTS_SUMMARY.md (test documentation)

Testing:
- All 9 unit tests pass
- Verified OAuth authentication works correctly with private key JWT
- Verified headers are not mutated between requests
- All HTTP client operations maintain isolated header state
- Form data and file uploads validated
@BinoyOza-okta BinoyOza-okta merged commit 1d6a1c0 into master Mar 6, 2026
15 checks passed
@BinoyOza-okta BinoyOza-okta deleted the OKTA-1105052 branch March 6, 2026 04:59
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