Skip to content

Commit 68c4b76

Browse files
btiernayclaude
andcommitted
test: add comprehensive test coverage for token exchange
Add 25 high-value tests covering gaps in token exchange implementation: Auth & Security: - HTTP Basic auth header verification (client_id/secret not in form) - Missing client_id/client_secret separately - Case-insensitive reserved parameter validation (Scope, RESOURCE, Audience, etc.) Discovery Edge Cases: - Missing token_endpoint in OIDC metadata - Non-JSON discovery response - HTTP error during discovery Token Endpoint Error Shapes: - Non-200 with non-JSON body (defaults to token_exchange_error) - 200 with non-JSON body (invalid_json error) - Network error (not timeout) Response Field Handling: - Empty strings preserved (id_token="", refresh_token="") - Numeric string expires_in coerced to int (lenient policy) - Non-numeric string expires_in rejected - Zero and negative expires_in accepted Extras Handling: - Array with exactly MAX_ARRAY_VALUES_PER_KEY passes - Mixed type arrays coerced to strings [1, "2", 3.5] → ["1", "2", "3.5"] - Numeric string arrays preserved ["1", "2"] → ["1", "2"] - Int values coerced to strings (user_id: 12345 → "12345") Parameter Wiring: - audience/scope/requested_token_type present when provided - audience absent when omitted - All parameters appear exactly once in form Coverage: 115 tests, 86% coverage (up from 90 tests, 85%) Policy Decision: expires_in uses lenient coercion (numeric strings accepted) Documented in code with clear comment explaining behavior. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 2df8d4c commit 68c4b76

2 files changed

Lines changed: 470 additions & 0 deletions

File tree

src/auth0_api_python/api_client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,8 @@ async def get_token_by_exchange_profile(
660660
502
661661
)
662662

663+
# Lenient policy: coerce numeric strings like "3600" to int
664+
# Reject non-numeric values (e.g., "not-a-number", None, objects)
663665
expires_in_raw = token_response.get("expires_in", 3600)
664666
try:
665667
expires_in = int(expires_in_raw)

0 commit comments

Comments
 (0)