fix(oauth): handle missing expires_in in OAuth token response (supersedes #3992)#4447
Merged
fix(oauth): handle missing expires_in in OAuth token response (supersedes #3992)#4447
Conversation
Signed-off-by: Olivier Gintrand <olivier.gintrand@forterro.com>
Builds on the missing-expires_in fix (issue #3989) with review feedback: - Add parse_expires_in() helper (oauth_manager.py) that validates absent/numeric/string/zero values and raises OAuthError on negative, non-numeric, or non-scalar inputs - Refresh path now uses the same helper so initial-auth and refresh agree on what 'missing expires_in' means (was hardcoded 3600s) - cleanup_expired_tokens ages out NULL-expires_at rows via created_at - _is_token_expired docstring documents the NULL-expiry contract - Remove now-dead OAUTH_DEFAULT_TIMEOUT from config, env example, helm chart, docs, and test mocks - Lazy %-style logging; drop redundant int() cast - Add unit + integration tests for all new branches Refs: #3989 Signed-off-by: Jonathan Springer <jps@s390x.com>
5 tasks
…ional floats Addresses Oracle second-pass review findings on dd3c25f9: - _refresh_access_token: when the refresh response omits expires_in, preserve the prior TTL by computing (expires_at - updated_at) from the existing record instead of clearing expires_at to NULL. Clearing it caused proactive refresh to stop after the first such response, since _is_token_expired returns False for NULL. Falls back to NULL only when the token had no prior expiry (genuine no-expiry providers like GitHub OAuth Apps). New _preserve_prior_ttl() module-level helper handles timezone-naive timestamps and non-positive deltas. - cleanup_expired_tokens: NULL-expiry rows now age via updated_at, not created_at. store_tokens advances updated_at on re-authorization, so using created_at would delete tokens that were re-authorized recently but originally created more than max_age_days ago. - parse_expires_in: tighten validation against int() truncation. Previously expires_in=-0.5 would silently pass as 0 because int(-0.5) == 0 (Python truncates toward zero). Now: sign-check the original numeric before conversion, and reject non-integer floats (RFC 6749 §5.1 specifies integer seconds). Order matters - sign check fires first since 'negative' is the more fundamental violation. Tests: - test_refresh_without_expires_in_clears_expiry replaced by: test_refresh_without_expires_in_preserves_prior_ttl (asserts new TTL ~= prior TTL after refresh) and test_refresh_without_expires_in_no_prior_ttl_stays_none. - test_cleanup_expired_tokens_targets_null_expires_at now asserts the query uses updated_at AND does NOT use created_at. - test_parse_expires_in_negative_raises extended with -0.5 and -3600.7. - New test_parse_expires_in_non_integer_float_raises covers 3600.5, 0.5, 3600.7. Signed-off-by: Jonathan Springer <jps@s390x.com>
f379dfa to
a611f35
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔗 Related Issue
Closes #3989
Supersedes #3992 (couldn't push amendments to the contributor's fork)
📝 Summary
Picks up @ecthelion77's original fix in #3992 for the `TypeError` raised when an OAuth provider omits `expires_in` from its token response (RFC 6749 §5.1 marks it RECOMMENDED, not REQUIRED — e.g. GitHub OAuth Apps), then layers in review-driven hardening:
🏷️ Type of Change
🧪 Verification
✅ Checklist
📓 Notes
Original author credit: The first commit is signed by @ecthelion77 from #3992 — please give them the merge attribution. The branch is rebased onto current `main`; the second and third commits are the review-driven refinements described above.
Why a new PR? PR #3992 came from a fork I lack push access to (`maintainerCanModify` is set on the PR, but cross-repo push requires either SSH collaborator access on the fork or HTTPS-token auth that the upstream maintainer permission alone doesn't grant). Rather than ask @ecthelion77 to apply the changes manually, I'm opening this PR with the rebased + amended history. Once this is reviewed/merged, #3992 should be closed in favor of it.
Behavior changes worth highlighting in the changelog (none are silent breaking changes for callers, but operators should know):