OpenSEO Security Measures: A Deep Dive into the Platform's Defense Architecture
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. 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. 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, this middleware injects a verified context.auth object containing the user's ID and organization membership.
Here is how the middleware protects server functions:
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 insrc/shared/gsc.ts) - Google Analytics:
analytics.readonly(defined insrc/shared/ga4.ts)
The OAuth flow implementation ensures tokens are never exposed to the client-side:
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 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:
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.
The transport layer in 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, 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. 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
ensureUserbefore 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 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, 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 and 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 handles this mode alongside Cloudflare Access for enterprise SSO. Additionally, src/shared/selfhost-checks.ts provides pre-flight health checks to verify that all required secrets and environment variables are properly configured before startup.
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 →