# How OpenSEO Determines Authentication Mode: Environment-Driven Configuration

> Discover how OpenSEO determines its authentication mode by reading the AUTH_MODE environment variable. Learn about supported modes and the default setting for secure access.

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

---

**OpenSEO reads the `AUTH_MODE` environment variable and validates it against a predefined list of supported modes, defaulting to `cloudflare_access` if the value is missing or invalid.**

The `every-app/open-seo` repository implements a configuration-driven authentication system that automatically wires the correct backend and frontend components based on a single environment variable. Understanding how OpenSEO determines authentication mode is essential for deploying self-hosted instances, integrating with Cloudflare Access, or running local development environments without credentials.

## How OpenSEO Authentication Mode Detection Works

The core logic resides in [`src/lib/auth-mode.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/auth-mode.ts), which exports utilities for parsing, validating, and querying the current authentication strategy.

### Step 1: Define Supported Authentication Modes

The framework maintains a strict allowlist of valid modes. The **`AUTH_MODES`** constant array explicitly defines three supported strings: `"cloudflare_access"`, `"local_noauth"`, and `"hosted"`. This constraint prevents runtime errors from typos or unsupported configurations.

### Step 2: Parse and Validate the Environment Variable

The **`getAuthMode(value)`** function processes the `AUTH_MODE` environment variable using a Zod enum schema (`authModeSchema`). This validation ensures type safety at runtime, rejecting malformed inputs before they propagate through the application stack.

### Step 3: Apply Safe Defaults and Warnings

If parsing fails due to a missing or invalid value, OpenSEO logs a one-time warning and returns `"cloudflare_access"` as a safe default. This fallback ensures the application remains secure even when configuration is incomplete.

## Authentication Mode Implementation in Core Files

Once determined, the OpenSEO authentication mode drives behavior across the entire stack, from middleware resolution to UI rendering.

### User Context Resolution (src/middleware/ensure-user/resolve.ts)

The middleware dispatcher in [`src/middleware/ensure-user/resolve.ts`](https://github.com/every-app/open-seo/blob/main/src/middleware/ensure-user/resolve.ts) calls `getAuthMode(env.AUTH_MODE)` to route each request to the appropriate context handler:

- **`resolveLocalNoAuthContext()`**: Returns a stub admin user for private development environments
- **`resolveHostedContext(headers)`**: Initializes the full Better-Auth UI flow
- **`resolveCloudflareAccessContext(headers)`**: Extracts identity from Cloudflare Access headers

### Auth Instance Creation (src/lib/auth.ts)

The Better-Auth library is only initialized when necessary. The [`src/lib/auth.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/auth.ts) module conditionally constructs the auth instance by checking **`isHostedAuthMode(env.AUTH_MODE)`**, preventing unnecessary database connections and middleware overhead in non-hosted modes.

### Route Guards and API Protection

API routes selectively enable endpoints based on the current mode. For example, `src/routes/api/auth/$.ts` and [`src/routes/api/gsc/oauth/callback.ts`](https://github.com/every-app/open-seo/blob/main/src/routes/api/gsc/oauth/callback.ts) verify `isHostedAuthMode(env.AUTH_MODE)` before registering their handlers, ensuring OAuth callbacks and session endpoints are only accessible when running in hosted mode.

### Client-Side Behavior Checks

The **`isHostedClientAuthMode()`** function checks `import.meta.env.AUTH_MODE` on the client side. This ensures the UI layer only renders login screens when the server is configured for hosted authentication, maintaining consistency between the build target and runtime behavior.

## Practical Code Examples

Reading and branching based on the authentication mode:

```typescript
// Example: reading the mode and branching
import { getAuthMode, isHostedAuthMode } from "@/lib/auth-mode";

const mode = getAuthMode(process.env.AUTH_MODE);
if (mode === "local_noauth") {
  // Run without any auth – useful for private dev setups
} else if (isHostedAuthMode(mode)) {
  // Initialise full Better‑Auth UI
} else {
  // Default Cloudflare Access flow
}

```

Client-side conditional rendering:

```typescript
// Example: client‑side check (Vite env)
import { isHostedClientAuthMode } from "@/lib/auth-mode";

if (isHostedClientAuthMode()) {
  // Render the sign‑in page
} else {
  // Skip UI – auth is handled upstream
}

```

Middleware user resolution:

```typescript
// Example: middleware that resolves the user context
import { resolveUserContextFromHeaders } from "@/middleware/ensure-user/resolve";

export async function handler(request: Request) {
  const ctx = await resolveUserContextFromHeaders(request.headers);
  // ctx now contains the authenticated user (or a stub for local_noauth)
}

```

## Summary

- OpenSEO determines authentication mode by reading the `AUTH_MODE` environment variable and validating it against the `AUTH_MODES` allowlist in [`src/lib/auth-mode.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/auth-mode.ts).
- The `getAuthMode()` function uses Zod for type-safe parsing, defaulting to `"cloudflare_access"` when the input is invalid or missing.
- Three modes are supported: `"hosted"` (full Better-Auth), `"cloudflare_access"` (header-based identity), and `"local_noauth"` (development stub).
- The resolved mode drives middleware routing in [`src/middleware/ensure-user/resolve.ts`](https://github.com/every-app/open-seo/blob/main/src/middleware/ensure-user/resolve.ts), conditional auth initialization in [`src/lib/auth.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/auth.ts), and client-side UI decisions via `isHostedClientAuthMode()`.

## Frequently Asked Questions

### What happens if I don't set the AUTH_MODE environment variable?

If `AUTH_MODE` is undefined or contains an invalid value, OpenSEO logs a warning and defaults to `"cloudflare_access"`. This safe fallback ensures the application remains secure while alerting you to the configuration issue.

### Can I use OpenSEO without any authentication?

Yes. Set `AUTH_MODE` to `"local_noauth"` to run the application without credentials. In this mode, [`src/middleware/ensure-user/resolve.ts`](https://github.com/every-app/open-seo/blob/main/src/middleware/ensure-user/resolve.ts) returns a stub admin context automatically, making it ideal for private development environments.

### How does OpenSEO handle authentication differently in hosted mode versus Cloudflare Access mode?

In hosted mode (`AUTH_MODE=hosted`), OpenSEO initializes the full Better-Auth instance from [`src/lib/auth.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/auth.ts) and exposes authentication endpoints like `src/routes/api/auth/$.ts`. In Cloudflare Access mode, the application skips local session management and instead resolves user identity from Cloudflare Access headers via `resolveCloudflareAccessContext()`.

### Why does the client need to check the authentication mode separately?

The client-side check via `isHostedClientAuthMode()` ensures the UI build matches the server configuration. Since `import.meta.env.AUTH_MODE` is evaluated at build time with Vite, this prevents client-side login components from rendering when the server is configured for external authentication like Cloudflare Access.