fix(schemas): accept expires_in alongside expires_at in OAuthTokenAuthentication (#1024) - #1782
Open
awesome-pro wants to merge 1 commit into
Conversation
…hentication OAuth providers return expires_in (seconds) per RFC 6749 §5.1, but the OAuthTokenAuthentication schema required expires_at (datetime), forcing callers to compute the absolute expiry themselves. Now both are accepted: when expires_in is supplied without expires_at, a before-validator converts it to expires_at = now + timedelta(seconds=expires_in). When expires_at is explicitly provided it is never overwritten. Fixes airweave-ai#1024
Contributor
There was a problem hiding this comment.
1 issue found across 2 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="backend/airweave/schemas/source_connection.py">
<violation number="1" location="backend/airweave/schemas/source_connection.py:104">
P1: Using raw `expires_in` in a `before` model validator can throw unwrapped exceptions before Pydantic validates/coerces the field, so bad input may become a server error instead of a schema validation error.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| return values | ||
| if values.get("expires_in") is not None and values.get("expires_at") is None: | ||
| values["expires_at"] = datetime.now(timezone.utc) + timedelta( | ||
| seconds=values["expires_in"] |
Contributor
There was a problem hiding this comment.
P1: Using raw expires_in in a before model validator can throw unwrapped exceptions before Pydantic validates/coerces the field, so bad input may become a server error instead of a schema validation error.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At backend/airweave/schemas/source_connection.py, line 104:
<comment>Using raw `expires_in` in a `before` model validator can throw unwrapped exceptions before Pydantic validates/coerces the field, so bad input may become a server error instead of a schema validation error.</comment>
<file context>
@@ -80,6 +80,30 @@ class OAuthTokenAuthentication(BaseModel):
+ return values
+ if values.get("expires_in") is not None and values.get("expires_at") is None:
+ values["expires_at"] = datetime.now(timezone.utc) + timedelta(
+ seconds=values["expires_in"]
+ )
+ return values
</file context>
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.
Summary
expires_in: Optional[int]field toOAuthTokenAuthenticationso callers can pass the standard OAuth RFC 6749 §5.1 response field directlymode="before"model validator convertsexpires_in → expires_at = now + timedelta(seconds=expires_in)whenexpires_atis not providedexpires_atusage is fully backward-compatible — if both are supplied,expires_atwinsProblem
OAuth providers return
expires_in(seconds, per RFC 6749 §5.1), butOAuthTokenAuthenticationonly acceptedexpires_at(datetime). This forced every SDK/API caller to manually compute the absolute timestamp:Changes
backend/airweave/schemas/source_connection.pyexpires_infield +coerce_expires_in_to_expires_atvalidatorbackend/tests/unit/schemas/test_source_connection_schemas.pyTest plan
expires_inalone →expires_atcomputed correctly (within 2 s of expected)expires_at+expires_in→expires_atnot overwrittenNoneexpires_in(already expired) →ValidationErrorexpires_atalone → unchanged (backward compat)access_tokenwithexpires_in→ still rejectedFixes #1024
Summary by cubic
Add
expires_insupport toOAuthTokenAuthenticationand auto-convert it toexpires_atso callers can pass standard OAuth responses directly. Keepsexpires_atprecedence for backward compatibility and removes client-side timestamp math. Fixes #1024.expires_in(RFC 6749 §5.1) and converts toexpires_atvia amodel_validator(mode="before")whenexpires_atis missing.expires_atwins; negativeexpires_inis rejected.Written for commit 63a3ba8. Summary will update on new commits.