# How to Connect and Authenticate Google Search Console in OpenSEO

> Learn to connect and authenticate Google Search Console in OpenSEO. Our guide details the OAuth 2.0 flow, token refresh, and reconnection for seamless integration.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: how-to-guide
- Published: 2026-08-10

---

**OpenSEO authenticates Google Search Console through an OAuth 2.0 flow that stores grants in a `gsc_grants` table and automatically handles token refresh and reconnection.**

Connecting your Google Search Console account to OpenSEO enables the platform to pull search analytics, inspect URL indexing status, and monitor site performance directly within your dashboard. This integration relies on a secure, standards-compliant OAuth 2.0 implementation that the OpenSEO team built into their generic authentication layer.

## OAuth Provider Configuration

The GSC integration starts with provider registration in [`src/shared/gsc.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/gsc.ts). This file defines the unique provider identifier and the specific Google API scopes required for read-only access:

```ts
// src/shared/gsc.ts
export const GSC_OAUTH_PROVIDER_ID = "google-search-console";
export const GSC_OAUTH_SCOPES = [
  "https://www.googleapis.com/auth/webmasters.readonly",
];

```

These constants get referenced across the codebase whenever GSC-specific OAuth operations occur.

The global authentication configuration in [`src/lib/auth-config.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/auth-config.ts) registers this provider so the OAuth engine knows which scopes and redirect URLs to apply:

```ts
// Inside the OAuth providers array in src/lib/auth-config.ts
{
  providerId: GSC_OAUTH_PROVIDER_ID,  // line 41
}

```

This registration happens once at application startup and enables all subsequent GSC linking flows.

## Initiating the Connection Flow

When a user clicks **Connect Google Search Console**, the client-side code in [`src/client/features/integrations/startGoogleLink.ts`](https://github.com/every-app/open-seo/blob/main/src/client/features/integrations/startGoogleLink.ts) handles the handoff to Google's consent screen:

```ts
// Client-side initiation
import { startGoogleLink } from '@/client/features/integrations/startGoogleLink';

// Called from a button click
await startGoogleLink({ integration: 'gsc' });

```

The `startGoogleLink` function forwards `GSC_OAUTH_PROVIDER_ID` to the generic `startOAuthLink` helper, which redirects the user to Google's OAuth consent screen with the exact scopes defined in [`src/shared/gsc.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/gsc.ts).

## Callback Handling and Token Storage

After the user grants permission, Google redirects back to OpenSEO's OAuth callback endpoint. According to the source code in **every-app/open-seo**, this callback:

1. Creates a **grant** linked to the authenticated user
2. Stores the grant in the `gsc_grants` database table
3. Associates the grant with `providerId: "google-search-console"`

This grant persists the refresh token and expiration metadata needed for subsequent API calls without requiring repeated user consent.

## Service Layer: GscService

The [`src/server/features/gsc/services/GscService.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/gsc/services/GscService.ts) file orchestrates all GSC interactions. It reads the user's stored grant and creates a `GscClient` instance:

```ts
// GscService retrieves the grant using the provider ID
providerId: GSC_OAUTH_PROVIDER_ID  // line 41

```

`GscService` validates connections on every request and automatically detects expired or revoked tokens (lines 83 and 128). When a token fails validation, it surfaces a **reconnect UI** rather than throwing raw errors—this graceful degradation keeps the user experience smooth.

Key methods exposed by `GscService`:

- `searchAnalytics` – Query search performance data with dimensions and filters
- `inspectUrls` – Check URL indexing status and coverage issues
- `disconnect` – Remove the stored grant and revoke server-side tokens

## Low-Level API Client

The [`src/server/lib/gscClient.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/gscClient.ts) file builds the authenticated HTTP client that talks directly to Google's Search Console API. When constructing a client, it passes the provider ID to ensure the correct grant gets loaded:

```ts
// src/server/lib/gscClient.ts, line 96
const client = createGscClient({ 
  userId, 
  gscAccountId, 
  providerId: GSC_OAUTH_PROVIDER_ID 
});

```

This client handles request signing, quota management, and standardized error responses that `GscService` can interpret.

## Server-Function API

The public interface for the UI lives in [`src/serverFunctions/gsc.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/gsc.ts). This file exposes functions that:

- Return connection state (`googleOAuthConfigured`)
- Allow property selection from available GSC sites
- Trigger disconnect or reconnect flows

Key implementation details include provider selection at **line 73** and disconnect event handling at **line 124**.

## Querying Search Console Data

Once authenticated, your server functions can query analytics data through `GscService`:

```ts
import { GscService } from '@/server/features/gsc/services/GscService';
import { SearchAnalyticsRequest } from '@/server/lib/gscClient';

export async function getSearchPerformance(
  projectId: string, 
  request: SearchAnalyticsRequest
) {
  // GscService pulls the stored grant, refreshes tokens if needed
  const rows = await GscService.searchAnalytics({ projectId, request });
  return rows; // array of GscSearchAnalyticsRow
}

```

To disconnect a property:

```ts
import { GscService } from '@/server/features/gsc/services/GscService';

await GscService.disconnect({ userId: currentUser.id, projectId });

```

## Error Handling

GSC-specific errors like `GscNotConnectedError` and token revocation scenarios are defined in [`src/server/lib/gscErrors.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/gscErrors.ts). The MCP tooling in [`src/server/mcp/tools/search-console-tools.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/search-console-tools.ts) translates these into friendly UI messages, with the specific reason code `gsc_oauth_not_configured` returned at **line 86** when authentication is missing or invalid.

This layered error handling ensures users see actionable messages like "Reconnect Google Search Console" rather than cryptic OAuth failures.

## Complete File Reference

| File | Purpose |
|------|---------|
| [`src/shared/gsc.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/gsc.ts) | Provider ID and OAuth scope constants |
| [`src/lib/auth-config.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/auth-config.ts) | Global OAuth provider registration |
| [`src/client/features/integrations/startGoogleLink.ts`](https://github.com/every-app/open-seo/blob/main/src/client/features/integrations/startGoogleLink.ts) | Client-side link initiation |
| [`src/server/lib/gscClient.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/gscClient.ts) | Low-level authenticated HTTP client |
| [`src/server/features/gsc/services/GscService.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/gsc/services/GscService.ts) | Core service for connection management and API calls |
| [`src/serverFunctions/gsc.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/gsc.ts) | Public server-function API |
| [`src/server/lib/gscErrors.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/gscErrors.ts) | GSC-specific error definitions |
| [`src/server/mcp/tools/search-console-tools.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/search-console-tools.ts) | Error translation for UI |

## Summary

- **Provider registration** in [`src/shared/gsc.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/gsc.ts) defines the OAuth identity and read-only scopes for Google Search Console
- **Client-side initiation** via `startGoogleLink` redirects users through Google's consent flow
- **Grant storage** persists tokens in `gsc_grants` with automatic refresh handled by `GscService`
- **Service layer** in [`GscService.ts`](https://github.com/every-app/open-seo/blob/main/GscService.ts) validates connections, detects revocation, and exposes `searchAnalytics` and `inspectUrls` methods
- **Error handling** surfaces reconnect prompts rather than raw OAuth failures, maintaining UX quality

## Frequently Asked Questions

### What permissions does OpenSEO request from Google Search Console?

OpenSEO requests the `https://www.googleapis.com/auth/webmasters.readonly` scope, which provides read-only access to search analytics, URL inspection data, and site coverage information. The platform cannot modify your site configuration or submit URLs for indexing with this scope alone.

### How does OpenSEO handle expired or revoked tokens?

The `GscService` class validates tokens before every API call and automatically detects expiration or revocation at lines 83 and 128 of [`src/server/features/gsc/services/GscService.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/gsc/services/GscService.ts). When detection occurs, it returns a state that triggers a reconnect UI rather than failing the request—users simply click to re-authenticate without losing their configuration.

### Can I connect multiple Google Search Console properties to one OpenSEO project?

Yes. The `gsc_grants` table stores grants per user, and `GscService` supports selecting from multiple available properties through the server-function API in [`src/serverFunctions/gsc.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/gsc.ts). The UI can present all properties the authenticated Google account has access to, letting users choose which to associate with each project.

### Where is the OAuth client secret stored in OpenSEO?

The analysis shows provider configuration in [`src/shared/gsc.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/gsc.ts) and [`src/lib/auth-config.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/auth-config.ts), but client secrets for the OAuth application are handled at the infrastructure level within OpenSEO's deployment environment— they do not appear in the referenced source files. This follows security best practices of keeping secrets out of version control and using environment-specific secret management.