# OpenSEO Security Measures: A Deep Dive into the Platform's Defense Architecture

> Discover OpenSEO security measures like better-auth, RBAC, and OAuth. Explore its layered defense architecture protecting user data and API credentials.

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

---

**OpenSEO implements a layered security architecture using better-auth for session management, role-based access control for organization permissions, request-level middleware validation, tightly-scoped OAuth integrations, and database-level tenant isolation to protect user data and external API credentials.**

OpenSEO (every-app/open-seo) is an open-source SEO platform that handles sensitive Google Search Console and Analytics data, requiring robust protection at every layer. Understanding the security measures OpenSEO implements reveals a defense-in-depth strategy that combines modern authentication libraries with custom middleware enforcement. This article examines the specific technical controls, source files, and implementation patterns that secure the platform from authentication through database isolation.

## Authentication and Session Management

OpenSEO builds its identity layer on top of the **better-auth** library, configured in [`src/lib/auth.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/auth.ts). This module handles user login flows, password hashing, and CAPTCHA verification to prevent automated attacks.

Session security relies on strict cookie policies. The platform sets authentication cookies with `HttpOnly`, `SameSite=Strict`, and optional `secure` flags via the TanStack cookies integration. This configuration prevents XSS attacks from stealing session tokens and ensures cookies are only transmitted over HTTPS in production environments.

## Authorization and Role-Based Access Control

Beyond verifying identity, OpenSEO enforces granular permissions through an access-control matrix defined in [`src/lib/org-permissions.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/org-permissions.ts). The system leverages **`better-auth/plugins/access`** and **`better-auth/plugins/organization/access`** to implement role-based access control (RBAC) at the organization level.

The permission model defines three distinct roles:

- **Owner** – Full administrative control over the organization
- **Admin** – Management capabilities with certain restrictions
- **Member** – Limited access to specific resources

These roles are enforced through the `requireOrgPermission` utility, which checks the user's role before allowing sensitive operations like project deletion or billing changes.

## Request-Level Enforcement with Middleware

Every server function passes through the **`ensure-user`** middleware to validate project and organization membership before business logic executes. Located in [`src/middleware/ensure-user/delegated.ts`](https://github.com/every-app/open-seo/blob/main/src/middleware/ensure-user/delegated.ts), this middleware injects a verified `context.auth` object containing the user's ID and organization membership.

Here is how the middleware protects server functions:

```typescript
import { ensureUser } from "@/middleware/ensure-user";
import { requireOrgPermission } from "@/server/auth/org-gate";

export const deleteProject = ensureUser(async (context) => {
  // `context.auth` holds the verified user info
  await requireOrgPermission(context.auth.userId, "owner");

  // Business logic follows…
});

```

This pattern ensures that even if a request reaches the server with valid credentials, the system verifies the user belongs to the correct organization before processing the request.

## OAuth Integration and External API Security

OpenSEO connects to Google Search Console (GSC) and Google Analytics 4 (GA4) using OAuth 2.0 with strictly scoped permissions. External tokens are stored in the **`better-auth` `account` table**, provider-scoped to prevent cross-service leakage.

The platform requests minimal scopes:

- **Google Search Console**: `webmasters.readonly` (defined in [`src/shared/gsc.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/gsc.ts))
- **Google Analytics**: `analytics.readonly` (defined in [`src/shared/ga4.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/ga4.ts))

The OAuth flow implementation ensures tokens are never exposed to the client-side:

```typescript
import { hasSelfHostedGoogleOAuthConfig } from "@/server/features/google/oauth-config";
import { getAuth } from "@/lib/auth";

export async function getGscAuthUrl() {
  const { accessToken } = await getAuth(); // pulls stored token from `better-auth` account table
  return `https://accounts.google.com/o/oauth2/auth?scope=${encodeURIComponent(
    "https://www.googleapis.com/auth/webmasters.readonly"
  )}&access_token=${accessToken}`;
}

```

## Machine-to-Machine Authentication

For programmatic access via the Model Context Protocol (MCP), OpenSEO supports API-key based authentication in addition to session cookies. The [`src/server/mcp/api-key-auth.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/api-key-auth.ts) module implements `withMcpProjectAuth`, a higher-order function that validates project-scoped API keys.

This approach limits Machine-to-Machine calls to specific projects while maintaining the same organizational permission checks:

```typescript
import { withMcpProjectAuth } from "@/server/mcp/project-auth";

export const auditWorkflow = withMcpProjectAuth(async (context, projectId) => {
  // `context.auth` now contains `{ userId, organizationId, scopes }`
  // Proceed with audit logic...
});

```

## Runtime Safeguards and Rate Limiting

OpenSEO includes multiple runtime protections to prevent abuse and ensure system stability. Before executing costly operations—such as third-party data lookups—the platform checks the organization's feature balance via internal utilities referenced in [`src/server/mcp/tools/whoami.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/whoami.ts).

The transport layer in [`src/server/mcp/transport.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/transport.ts) supports multiple authentication modes:

- **Cloudflare Access** – Enterprise SSO integration for managed deployments
- **local_noauth** – Explicit no-authentication mode for self-hosted installations with controlled network access
- **API-key authentication** – For service-to-service communication

Additionally, the platform performs pre-flight health checks through the `/api/health` endpoint and telemetry scripts in [`src/shared/selfhost-checks.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/selfhost-checks.ts), verifying that required environment variables and secrets are present before the application starts accepting requests.

## Database Isolation and Schema Security

Data isolation occurs at the database level through [`src/db/better-auth-schema.ts`](https://github.com/every-app/open-seo/blob/main/src/db/better-auth-schema.ts). OpenSEO stores all user-related tables—**users**, **organizations**, and **accounts**—in separate schemas for both SQLite and PostgreSQL deployments.

This schema separation prevents accidental cross-tenant data leakage by ensuring that queries must explicitly target the correct schema namespace. The better-auth library generates these schemas dynamically, maintaining consistent isolation across different database backends.

## Summary

OpenSEO's security measures create a comprehensive defense-in-depth model spanning authentication, authorization, and data storage:

- **Authentication layer** uses better-auth with secure, HttpOnly cookies and CAPTCHA protection
- **Authorization matrix** enforces role-based access control (owner/admin/member) at the organization level
- **Middleware enforcement** validates organization membership via `ensureUser` before executing server functions
- **OAuth scoping** limits external API access to read-only permissions for Google services
- **MCP security** provides API-key authentication with project-level scope restrictions
- **Database isolation** uses separate schemas to prevent cross-tenant data leakage
- **Runtime checks** include feature balance validation and health endpoint verification

## Frequently Asked Questions

### How does OpenSEO handle user authentication and session security?

OpenSEO uses the better-auth library to manage user login, password hashing, and CAPTCHA verification. Sessions are maintained via cookies configured with `HttpOnly`, `SameSite=Strict`, and `secure` flags to prevent XSS attacks and ensure transmission only over HTTPS. The implementation resides in [`src/lib/auth.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/auth.ts) and integrates with TanStack cookies for cross-platform compatibility.

### What permissions model does OpenSEO use for organization access?

The platform implements role-based access control through better-auth's organization plugins, defining three roles: **owner**, **admin**, and **member**. Permission checks occur via the `requireOrgPermission` utility in [`src/lib/org-permissions.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/org-permissions.ts), which validates the user's role before allowing sensitive operations such as project deletion or billing modifications.

### How does OpenSEO secure external API credentials for Google services?

OAuth tokens for Google Search Console and Analytics are stored in the better-auth `account` table with provider-scoped isolation. The platform requests minimal read-only scopes (`webmasters.readonly` and `analytics.readonly`) and retrieves tokens server-side in [`src/shared/gsc.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/gsc.ts) and [`src/shared/ga4.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/ga4.ts) to ensure credentials never reach the client browser.

### Can OpenSEO be securely self-hosted without cloud authentication?

Yes, OpenSEO supports a `local_noauth` mode explicitly designed for self-hosted installations within controlled network environments. The transport layer in [`src/server/mcp/transport.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/transport.ts) handles this mode alongside Cloudflare Access for enterprise SSO. Additionally, [`src/shared/selfhost-checks.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/selfhost-checks.ts) provides pre-flight health checks to verify that all required secrets and environment variables are properly configured before startup.