# How the OAuth Provider in OpenSEO Manages and Purges Expired Tokens

> Learn how the OpenSEO OAuth provider efficiently purges expired tokens using TTL settings and scheduled data cleanup in Cloudflare KV storage.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: internals
- Published: 2026-09-04

---

**The OpenSEO OAuth provider eliminates expired tokens through configurable TTL settings paired with a scheduled `purgeExpiredData` method that sweeps orphaned records from Cloudflare KV storage.**

The OpenSEO MCP (Multi-Channel-Provider) OAuth implementation handles authentication for the every-app/open-seo repository, leveraging Cloudflare Workers KV for state persistence. Understanding how this **OAuth provider in OpenSEO** cleans up stale credentials is critical for maintaining secure, performant integrations.

## Token Lifecycle Configuration

OpenSEO defines three distinct time-to-live (TTL) values when instantiating the `OAuthProvider` in [`src/server/mcp/oauth-provider.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/oauth-provider.ts) (lines 49-55). These settings govern the validity window for different credential types:

| Setting | Duration | Purpose |
|---------|----------|---------|
| `accessTokenTTL` | 24 hours (86,400 seconds) | Short-lived access tokens used for individual API calls |
| `refreshTokenTTL` | 30 days (2,592,000 seconds) | Long-term refresh tokens that maintain MCP sessions between accesses |
| `clientRegistrationTTL` | 1 year (31,536,000 seconds) | Validity period for dynamic client registration records |

These values are passed to the underlying `@cloudflare/workers-oauth-provider` library during initialization:

```typescript
const provider = new OAuthProvider({
  accessTokenTTL: 60 * 60 * 24,
  refreshTokenTTL: 60 * 60 * 24 * 30,
  clientRegistrationTTL: 60 * 60 * 24 * 365,
  // additional configuration
});

```

## Automated Cleanup with purgeExpiredData

While Cloudflare KV automatically expires entries based on their TTL, it does not cascade deletions. This leaves orphaned grants and metadata when parent registrations expire. To address this, the provider exposes a `purgeExpiredData` method defined in [`src/server/mcp/oauth-provider.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/oauth-provider.ts) (lines 64-71).

The method iterates over the KV namespace (`OAUTH_KV`), validates whether each grant or token remains referenced, and removes stale records:

```typescript
purgeExpiredData(env: OpenSeoOAuthEnv) {
  return getProvider().purgeExpiredData(env, { batchSize: 200 });
}

```

The upstream `OAuthProvider` implementation handles the actual deletion logic, using a **batch size of 200** to process the entire keyspace efficiently.

## Scheduling the Cleanup Cron

OpenSEO triggers token purging through a Cloudflare Worker scheduled event. The cron handler instantiates the provider and invokes the cleanup method:

```typescript
export default {
  async fetch(request, env, ctx) {
    const provider = createOpenSeoOAuthProvider((req) => fetch(req));
    return provider.fetch(request, env, ctx);
  },

  async scheduled(event, env, ctx) {
    const provider = createOpenSeoOAuthProvider(() => new Response());
    await provider.purgeExpiredData(env);
  },
};

```

Configure this to run every 6 hours (or your preferred interval) in your [`wrangler.toml`](https://github.com/every-app/open-seo/blob/main/wrangler.toml) or Cloudflare dashboard to ensure expired **OpenSEO OAuth tokens** do not accumulate.

## Manual Token Revocation

For immediate invalidation (such as during user logout), OpenSEO supports manual revocation through the `revokeOAuthToken` utility in [`src/lib/oauth-resource.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/oauth-resource.ts). This bypasses the TTL mechanism and deletes the token directly from KV:

```typescript
import { revokeOAuthToken } from "@/lib/oauth-resource";

async function logout(request: Request, env: Env) {
  const token = request.headers.get("Authorization")?.replace(/^Bearer /, "");
  if (token) {
    await revokeOAuthToken(env.OAUTH_KV, token);
  }
  return new Response("Logged out", { status: 200 });
}

```

## Key Implementation Files

The token management system spans four primary files:

- **[`src/server/mcp/oauth-provider.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/oauth-provider.ts)** – Core implementation including TTL definitions and the `purgeExpiredData` method
- **[`src/lib/oauth-resource.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/oauth-resource.ts)** – Contains `revokeOAuthToken` and the `MCP_OAUTH_SCOPES` authorization definitions  
- **[`src/server/mcp/oauth-registration.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/oauth-registration.ts)** – Handles dynamic client registration subject to `clientRegistrationTTL`
- **[`src/server/mcp/api-key-auth.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/api-key-auth.ts)** – Demonstrates alternative authentication using the same KV store

## Summary

- The **OAuth provider in OpenSEO** sets three distinct TTL values (24 hours for access tokens, 30 days for refresh tokens, 1 year for client registrations) in [`src/server/mcp/oauth-provider.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/oauth-provider.ts)
- Cloudflare KV stores all tokens, but KV TTL alone cannot clean up orphaned grant data
- The `purgeExpiredData` method (batch size 200) sweeps stale records and runs on a scheduled cron job
- Manual revocation via `revokeOAuthToken` allows immediate token invalidation during logout flows
- This architecture prevents dead data accumulation while maintaining strict session controls

## Frequently Asked Questions

### How long do access tokens remain valid in OpenSEO?

Access tokens expire after **24 hours** (`accessTokenTTL: 86400` seconds). This short lifespan minimizes security exposure for active API calls, while refresh tokens maintain session continuity for 30 days.

### What happens to expired tokens if the cron job fails to run?

Expired tokens remain in Cloudflare KV until the `purgeExpiredData` method successfully executes. While the raw KV entries auto-expire based on TTL, orphaned metadata (unlinked grants) persists indefinitely without the cleanup sweep, potentially causing storage bloat.

### Can administrators manually revoke tokens before their natural expiration?

Yes. Import `revokeOAuthToken` from [`src/lib/oauth-resource.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/oauth-resource.ts) to delete tokens immediately from the `OAUTH_KV` namespace. This is the recommended approach for logout functionality or security incidents requiring instant session termination.

### Why does the purge method use a batch size of 200?

The **batch size of 200** ensures the cleanup process can scan the entire KV keyspace in a single pass without hitting Cloudflare Worker execution limits. This parameter is hardcoded in the `purgeExpiredData` call within [`src/server/mcp/oauth-provider.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/oauth-provider.ts).