How y-gui Implements OAuth Token Refresh with Scheduled Tasks in Cloudflare Workers

The y-gui application automatically refreshes OAuth tokens every hour using a Cloudflare Workers cron trigger that executes checkAndRefreshTokens for all user workspaces, storing updated credentials in a D1 database.

y-gui is an open-source integration management system built on Cloudflare Workers that maintains persistent Google OAuth connections. The application stores integration configurations—including sensitive refresh tokens—in a D1 database and employs an automated token refresh mechanism to ensure uninterrupted API access without manual intervention.

Core Token Refresh Mechanism

The token refresh logic resides in backend/src/utils/token-refresh.ts and operates through two coordinated functions that handle the OAuth token lifecycle.

refreshIntegrationToken: Exchanging Credentials with Google

The refreshIntegrationToken function manages the actual token exchange with Google's OAuth infrastructure. When invoked, it POSTs the stored refresh_token to the Google OAuth endpoint along with the application's GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET. Upon receiving a successful response containing a new access_token and expires_in value, the function persists these updated credentials back to the integration record via IntegrationD1Repository.

According to the source code at lines 15-75 of backend/src/utils/token-refresh.ts, this function encapsulates the entire exchange workflow, handling the HTTP request construction and database update operations atomically.

checkAndRefreshTokens: Proactive Expiry Inspection

Before triggering an exchange, the system must determine which tokens require refresh. The checkAndRefreshTokens function (lines 88-130 of backend/src/utils/token-refresh.ts) queries all integrations associated with a specific user prefix from the CHAT_DB D1 instance and inspects each token's expiry_date.

If the remaining lifetime falls below a configurable threshold—defaulting to approximately 5 hours—the function invokes refreshIntegrationToken for that specific integration. This proactive approach ensures tokens remain valid during periods of active use while minimizing unnecessary API calls to Google's authorization servers.

Scheduled Task Architecture

y-gui leverages Cloudflare Workers' cron trigger capabilities to automate the refresh workflow across all user workspaces without requiring external scheduling infrastructure.

Cron Configuration in wrangler.toml

The scheduled execution is configured in backend/wrangler.toml (lines 35-38), where a cron trigger is registered to fire every hour:

[triggers]
crons = ["0 * * * *"]

This configuration ensures the Workers runtime invokes the scheduled handler consistently, providing a reliable window for token maintenance regardless of application traffic patterns.

The Scheduled Handler Implementation

The entry point for automated execution is defined in backend/src/index.ts, which exports a scheduled handler alongside the standard fetch handler. When the cron trigger fires, the handler executes a two-phase refresh process across lines 13-35:

// Scheduled task – automatically invoked by Cloudflare Workers
export default {
  fetch: app.fetch,
  async scheduled(event, env, ctx) {
    console.log('⏰ Token refresh start');
    await checkAndRefreshTokens(env, '');               // default space
    const prefixes = await listUserPrefixes(env.CHAT_R2);
    for (const p of prefixes) await checkAndRefreshTokens(env, p);
    console.log('✅ Token refresh finished');
  },
};

First, it calls checkAndRefreshTokens for the default workspace (empty prefix). Then, it retrieves all user-specific prefixes and iterates through each, executing the refresh check for every user's integrations. This architecture ensures comprehensive coverage across multi-tenant deployments.

User Prefix Enumeration via R2 Storage

The listUserPrefixes utility function, implemented in backend/src/utils/storage.ts, queries the Cloudflare R2 bucket (CHAT_R2) to discover all active user workspaces. This dynamic discovery mechanism allows the scheduled task to adapt to new users automatically without requiring manual registry updates or static configuration lists.

Manual Invocation and Development Workflows

While the scheduled task handles production automation, developers can manually trigger the token refresh mechanism for testing or debugging purposes. The following example demonstrates invoking checkAndRefreshTokens with custom parameters:

// Manual trigger (e.g., during development)
import { checkAndRefreshTokens } from './utils/token-refresh';

await checkAndRefreshTokens(
  {
    CHAT_DB: myD1Database,
    GOOGLE_CLIENT_ID: 'my-client-id',
    GOOGLE_CLIENT_SECRET: 'my-client-secret',
  },
  'user123',          // user prefix
  15 * 60 * 1000      // refresh if expiring within 15 minutes
);

This flexibility allows precise control over refresh thresholds during development, enabling testing with shorter expiry windows than the production default.

Summary

  • y-gui stores OAuth credentials in a Cloudflare D1 database and uses a dual-function approach in backend/src/utils/token-refresh.ts to manage token lifecycle
  • The refreshIntegrationToken function exchanges refresh tokens for new access tokens via Google's OAuth endpoint, while checkAndRefreshTokens orchestrates proactive refreshes based on configurable expiry thresholds (default ~5 hours)
  • An hourly cron trigger configured in backend/wrangler.toml drives the automated workflow through a scheduled handler exported from backend/src/index.ts (lines 13-35)
  • The system dynamically discovers all user workspaces using listUserPrefixes from R2 storage, ensuring complete multi-tenant coverage during each execution cycle

Frequently Asked Questions

How does y-gui determine when to refresh an OAuth token?

The system compares the token's expiry_date against the current time using a configurable threshold. If a token expires within approximately 5 hours (or a custom millisecond value passed to checkAndRefreshTokens), the function flags it for refresh. This threshold prevents service interruptions while avoiding excessive token rotation that could trigger Google API rate limits.

What happens if the Google OAuth endpoint is unavailable during a scheduled refresh?

The refreshIntegrationToken function handles the HTTP exchange logic in backend/src/utils/token-refresh.ts. If the endpoint is unavailable or returns an error, the function fails to obtain new credentials and the existing database record remains unchanged. The next scheduled execution (within one hour) retries the operation, as the token remains flagged for refresh due to its proximity to expiry.

Can the token refresh mechanism handle multiple Google integrations per user?

Yes. The checkAndRefreshTokens function retrieves all integrations for a given user prefix and iterates through each record independently. Each integration maintains its own expiry_date and refresh credentials, allowing the system to manage multiple concurrent OAuth connections—such as Gmail, Calendar, and Drive—under a single user account.

Where are the user workspace prefixes stored and how are they discovered?

User prefixes are enumerated from the Cloudflare R2 bucket using the listUserPrefixes function defined in backend/src/utils/storage.ts. During the scheduled execution in backend/src/index.ts, the system queries R2 to dynamically discover all active prefixes, then invokes the refresh check for each workspace. This eliminates the need to maintain a static list of users in the application configuration.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →