How the y-gui Integration Router Connects to Gmail and Google Calendar
The y-gui integration router handles OAuth-based connections to Gmail and Google Calendar through a three-stage workflow: service configuration, authorization URL generation, and callback processing with token persistence to a Cloudflare D1 database.
The integration router serves as the central gateway for third-party service authentication in the y-gui application. Located in backend/src/api/integration.ts, this router manages the complete lifecycle of Google service connections, from initial authorization requests to secure credential storage.
OAuth Configuration and Service Setup
The router defines service-specific configurations as constants for each supported integration. These configurations encapsulate the OAuth scope, redirect URIs, and service identifiers required for Google authentication.
In backend/src/api/integration.ts, you will find the configuration objects for Google services:
- GOOGLE_CALENDAR_CONFIG: Defines the Calendar API scope and callback handling
- GMAIL_CONFIG: Specifies Gmail API permissions and redirect behavior
Each configuration includes the display name, service identifier, OAuth scope array, environment variable references for redirect URIs, and default callback paths. These constants drive the dynamic behavior of the authentication endpoints.
Generating Authorization URLs
When a client initiates a connection, the router handles GET /api/integration/auth/:type requests to generate Google OAuth URLs dynamically.
The createOAuthUrl function constructs the authorization URL by combining the client ID, redirect URI, requested scopes, response type, and access type parameters. The /auth/:type handler selects the appropriate configuration based on the route parameter, then returns a JSON response containing the generated URL.
// Client-side request to initiate Gmail authorization
const resp = await fetch('/api/integration/auth/google-gmail');
const { authUrl } = await resp.json();
window.location.href = authUrl; // Redirects to Google's consent screen
This endpoint supports offline access and forces consent prompts to ensure refresh tokens are obtained for long-term API access.
Handling OAuth Callbacks and Token Storage
After user authorization, Google redirects to /api/integration/callback/:type with an authorization code. The router processes this through the handleOAuthCallback function, which exchanges the code for access and refresh tokens.
The callback handler performs these operations:
- Extracts the authorization code from the request body
- Exchanges the code for tokens via Google OAuth servers
- Constructs an
IntegrationConfigobject containing credentials and metadata - Persists the configuration to the database
// Server-side callback handler (simplified)
router.post('/callback/:type', async (c) => {
const { code } = await c.req.json();
const integration = await handleOAuthCallback(c, code, config);
return c.json({ success: true, integration });
});
The implementation stores access tokens, refresh tokens, and expiry timestamps required for subsequent API calls to Google services.
Database Persistence with IntegrationD1Repository
Integration records are persisted using the IntegrationD1Repository class defined in backend/src/repository/d1/integration-d1-repository.ts. This repository manages CRUD operations against the Cloudflare D1 database.
The repository uses env.CHAT_DB as the database connection and organizes records by user_prefix and integration name. Key methods include:
- getIntegrations(): Retrieves all integrations for a user
- createIntegration(): Inserts new OAuth credentials
- updateIntegration(): Refreshes existing token data
The IntegrationConfig interface in shared/types/index.ts defines the data model, specifying fields for service name, authentication type, connection status, and encrypted credential storage.
// Retrieving stored credentials for downstream use
import { IntegrationD1Repository } from '@/backend/repository/d1/integration-d1-repository';
async function getGmailToken(env: Env, userPrefix: string) {
const repo = new IntegrationD1Repository(env.CHAT_DB, userPrefix);
const integrations = await repo.getIntegrations();
const gmail = integrations.find(i => i.name === 'google-gmail');
return gmail?.credentials?.access_token;
}
Using Stored Integrations
Once persisted, integrations are available to other services within y-gui. The repository provides lookup methods that enable email fetching, calendar event retrieval, and other API operations without requiring re-authentication.
The stored IntegrationConfig objects contain the active access tokens and refresh logic, allowing background services to maintain persistent connections to Google APIs.
Summary
- The integration router in
backend/src/api/integration.tscentralizes OAuth authentication for third-party services - Configuration constants define service-specific OAuth parameters for Gmail and Calendar
- Two-phase authentication involves
/auth/:typefor URL generation and/callback/:typefor token exchange - IntegrationD1Repository handles secure persistence of credentials to Cloudflare D1
- The IntegrationConfig type standardizes credential storage across the application
Frequently Asked Questions
What happens when the authorization code is exchanged in the callback?
The handleOAuthCallback function receives the authorization code from Google's redirect and exchanges it for access and refresh tokens through Google's OAuth token endpoint. It then constructs an IntegrationConfig object containing these credentials and persists them to the D1 database via IntegrationD1Repository, either creating a new record or updating an existing one with fresh tokens.
Where are the OAuth tokens stored in y-gui?
OAuth tokens are stored in a Cloudflare D1 database through the IntegrationD1Repository class located in backend/src/repository/d1/integration-d1-repository.ts. Each integration record is keyed by user_prefix and service name, storing the access token, refresh token, expiry date, and connection status in JSON format as defined by the IntegrationConfig interface.
How does the router handle different Google services like Gmail versus Calendar?
The router uses service configuration objects (GOOGLE_CALENDAR_CONFIG and GMAIL_CONFIG) that define the specific OAuth scopes, redirect URIs, and service identifiers for each API. When a request hits /api/integration/auth/:type or /api/integration/callback/:type, the router maps the :type parameter to the appropriate configuration and applies the correct scopes during the OAuth flow.
Can the integration router support OAuth providers other than Google?
Yes, the architecture supports additional OAuth providers. The router uses a configuration-driven approach where new services can be added by defining new configuration objects with the required OAuth endpoints, scopes, and callback paths. The IntegrationConfig type in shared/types/index.ts is provider-agnostic, storing generic credential fields that accommodate various authentication schemes beyond Google OAuth.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →