Skip to content
This repository was archived by the owner on Aug 29, 2026. It is now read-only.
This repository was archived by the owner on Aug 29, 2026. It is now read-only.

bug(oauth): expired-token validator blocks loading persisted tokens for refresh #1785

Description

@awesome-pro

Summary

OAuthTokenAuthentication has a Pydantic mode=\"after\" validator that raises ValueError(\"Token has already expired\") whenever expires_at is in the past:

# backend/airweave/schemas/source_connection.py
@model_validator(mode="after")
def validate_token(self):
    if self.expires_at and self.expires_at < datetime.now(timezone.utc):
        raise ValueError("Token has already expired")
    return self

Problem

OAuth access tokens expire (typically in 1 hour). The normal flow for long-lived connections is:

  1. Store the token (including expires_at) in the DB.
  2. On the next sync, load the token from DB.
  3. Detect that expires_at < now(), then call the refresh endpoint.
  4. Swap in the new access token.

Step 2 fails: constructing OAuthTokenAuthentication from the persisted data triggers the validator and raises a ValidationError before the code ever gets a chance to refresh. This means any source connection whose access token has expired cannot be loaded at all — syncs will fail with a Pydantic ValidationError rather than a meaningful "token expired, refresh needed" error.

Expected behaviour

The expiry check should guard connection creation / user-facing input, not the internal load-for-refresh path. Options:

  • Move the check out of the model validator and into the OAuth handshake layer so it only fires when a brand-new token is being accepted, not when an existing one is being deserialized.
  • Alternatively, make the validator configurable (e.g., a skip_expiry_check flag) or split into two schemas: OAuthTokenInput (strict, validates freshness) and OAuthTokenStored (no expiry check).

Steps to reproduce

from datetime import datetime, timezone, timedelta
from airweave.schemas.source_connection import OAuthTokenAuthentication

# Simulate loading a token that expired 10 minutes ago
OAuthTokenAuthentication(
    access_token="some-access-token",
    expires_at=datetime.now(timezone.utc) - timedelta(minutes=10),
)
# → raises pydantic.ValidationError: Token has already expired

Impact

Any OAuth-backed source connection whose access token has expired will fail to load for refresh, causing syncs to break instead of transparently refreshing.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions