OpenSEO Authentication Modes: Configuring Cloudflare Access, Local, and Hosted Auth
OpenSEO supports three authentication modes—cloudflare_access for Cloudflare Zero-Trust, local_noauth for development, and hosted for the managed SaaS platform—configured exclusively via the AUTH_MODE environment variable.
OpenSEO, the open-source SEO platform from every-app/open-seo, implements a flexible authentication architecture that adapts to different deployment environments without code changes. The system determines which authentication strategy to apply at runtime through the Auth_MODE environment variable, enabling the same codebase to operate as a secure SaaS application, a Cloudflare-protected self-hosted instance, or a credential-free local development server.
The Three OpenSEO Authentication Modes
OpenSEO determines user identity and authorization scope through the AuthMode type defined in src/lib/auth-mode.ts. Each mode handles request validation differently based on your infrastructure requirements.
cloudflare_access (Self-Hosted with Zero-Trust)
Use cloudflare_access when deploying a self-hosted instance that relies on Cloudflare Access for identity management. In this mode, Cloudflare Access injects an Authorization header containing a signed JWT into each request. The OpenSEO server validates this token and extracts the user's identity and permission scopes. This approach delegates all authentication decisions to Cloudflare's edge network, making it ideal for internal tools or teams already using Cloudflare Zero-Trust.
local_noauth (Local Development)
Set AUTH_MODE to local_noauth for local development or testing scenarios where authentication must be bypassed. When active, OpenSEO treats all incoming requests as originating from an internal admin user, requiring no authentication headers. This mode eliminates the need to configure external identity providers during rapid prototyping, though it should never be used in production environments.
hosted (Managed SaaS Platform)
The hosted mode powers the official SaaS version of OpenSEO running on Every App's managed platform. Users authenticate through the hosted UI via an OAuth flow managed by the platform. The server reads the session cookie or JWT that the platform sets on each request, automatically authorizing users without additional configuration. This mode is the default for the managed service and handles multi-tenant user isolation.
Configuring the AUTH_MODE Environment Variable
Authentication mode selection happens at runtime through environment variable configuration. No code changes or rebuilds are required to switch between modes.
Set the variable in your deployment environment:
# Self-hosted with Cloudflare Access
AUTH_MODE=cloudflare_access
# Local development (no auth)
AUTH_MODE=local_noauth
# Hosted SaaS (managed platform)
AUTH_MODE=hosted
For cloudflare_access deployments, you must additionally configure a Cloudflare Access Application and define the required authentication policies in your Cloudflare dashboard. The local_noauth mode requires no external setup, while hosted mode requires deployment to the Every App platform infrastructure. Verify the active mode at runtime using the /api/oauth/consent endpoint or the whoami tool available in the MCP transport layer.
Implementing Auth Mode Checks in Code
The core library provides type-safe utilities to branch logic based on the active authentication strategy. All helpers reside in src/lib/auth-mode.ts.
Resolving the Current Mode
Use getAuthMode to parse and normalize the environment variable value. This function accepts either process.env.AUTH_MODE on the server or import.meta.env.AUTH_MODE in client bundles:
import { getAuthMode } from "@/lib/auth-mode";
export async function handler(request: Request) {
const authMode = getAuthMode(process.env.AUTH_MODE);
console.log("Running in auth mode:", authMode);
// Branch logic based on authMode value
}
Using Predicate Functions
Helper predicates simplify conditional logic without hardcoding string comparisons:
import { getAuthMode, isHostedAuthMode, isHostedClientAuthMode, isEmailVerificationBypassed } from "@/lib/auth-mode";
const mode = getAuthMode(import.meta.env.AUTH_MODE);
if (isHostedAuthMode(mode)) {
// Execute hosted SaaS specific logic
}
if (isEmailVerificationBypassed()) {
// Skip verification steps in local development
}
if (isHostedClientAuthMode()) {
// Client-side safeguard ensuring build-time AUTH_MODE matches runtime
}
Server-Side Route Protection
The middleware layer uses these checks to enforce authentication requirements. In src/middleware/ensure-user/resolve.ts, the system uses the auth mode to decide whether to enforce user authentication for a given request. Similarly, src/server.ts reads AUTH_MODE at startup to select the appropriate request-handling path for hosted versus self-hosted deployments.
Core Files Handling Authentication Logic
Understanding the source file organization helps when customizing authentication behavior:
-
src/lib/auth-mode.ts— Defines theAuthModeunion type, thegetAuthModeparsing logic, and all predicate helper functions includingisHostedAuthModeandisEmailVerificationBypassed. -
src/server.ts— ReadsAUTH_MODEat application startup and initializes the appropriate request routing pipeline for hosted or self-hosted operation. -
src/middleware/ensure-user/resolve.ts— Contains the authentication enforcement logic that references the current mode to determine if a request requires a valid user session. -
src/server/mcp/transport.ts— Implements mode-aware request handling for internal MCP (Model Context Protocol) APIs, using thewhoamiverification tool. -
docs/SELF_HOSTING_DOCKER.md— Deployment documentation providing practical guidance on settingAUTH_MODEin containerized environments.
Summary
- OpenSEO provides three authentication strategies:
cloudflare_accessfor Cloudflare Zero-Trust,local_noauthfor development, andhostedfor the SaaS platform. - Configuration occurs exclusively through the
AUTH_MODEenvironment variable, requiring no code modifications to switch modes. - The
getAuthModefunction insrc/lib/auth-mode.tsnormalizes environment variable values into type-safeAuthModetypes. - Predicate helpers like
isHostedAuthModeandisEmailVerificationBypassedenable clean conditional logic without string comparisons. - Production deployments using
cloudflare_accessrequire additional Cloudflare Access Application configuration, whilelocal_noauthis strictly for development use.
Frequently Asked Questions
What are the valid AUTH_MODE values in OpenSEO?
OpenSEO accepts three string values for AUTH_MODE: cloudflare_access for Cloudflare Zero-Trust integration, local_noauth for credential-free development, and hosted for the managed Every App platform. The getAuthMode function in src/lib/auth-mode.ts validates and normalizes these values at runtime, throwing an error if an unsupported mode is specified.
How does Cloudflare Access authentication work technically?
When AUTH_MODE is set to cloudflare_access, OpenSEO expects Cloudflare's edge network to validate users before requests reach the application. Cloudflare injects a signed JWT in the Authorization header, which OpenSEO validates to extract identity claims and scopes. This moves authentication to the network edge, ensuring unauthenticated requests never reach your origin server.
Is local_noauth safe for production environments?
No, local_noauth is explicitly designed for local development and testing only. When enabled, OpenSEO treats all requests as coming from an admin user without verifying credentials, creating significant security vulnerabilities if exposed to the internet. Production deployments should use either cloudflare_access or the hosted mode on the managed platform.
How can I detect the current authentication mode in client-side code?
Use getAuthMode(import.meta.env.AUTH_MODE) to safely retrieve the mode in browser contexts, or use the isHostedClientAuthMode() predicate for build-time checks. These utilities ensure your client-side logic respects the same authentication configuration as the server, preventing mismatches between the build environment and runtime deployment.
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 →