How to Configure Better-Auth in OpenWork: Secrets, Trusted Origins, and CORS Setup

To configure Better-Auth in OpenWork, you must set four environment variables: BETTER_AUTH_SECRET for cryptographic signing, BETTER_AUTH_URL for post-login redirects, and DEN_BETTER_AUTH_TRUSTED_ORIGINS combined with CORS_ORIGINS to whitelist your API and web origins.

OpenWork integrates the Better-Auth ecosystem (@better-auth/*) to handle authentication, SSO, SCIM, and API keys across its Den architecture. Understanding how to properly configure these secrets and cross-origin settings is essential for both local development and production deployments. This guide walks through the exact environment variables, helper functions, and source files that manage Better-Auth configuration in the different-ai/openwork repository.

Required Environment Variables

Better-Auth requires four specific environment variables to function securely within OpenWork's Den services:

  • BETTER_AUTH_SECRET – A high-entropy string (minimum 32 bytes) used for signing tokens and encrypting sensitive data. The development environment falls back to a placeholder in dev/evals/packages/testkit/src/server.ts (line ≈26), but production must use a cryptographically secure secret from a vault.
  • BETTER_AUTH_URL – The base URL of the Den web frontend (e.g., http://localhost:3000) that Better-Auth redirects to after authentication. This is dynamically constructed from the allocated web port in the development scripts.
  • DEN_BETTER_AUTH_TRUSTED_ORIGINS – A comma-separated list of origins that the Better-Auth server explicitly trusts for authentication callbacks and session validation.
  • CORS_ORIGINS – A comma-separated list passed to the CORS middleware, allowing the browser to call the API from specified web origins.

Both DEN_BETTER_AUTH_TRUSTED_ORIGINS and CORS_ORIGINS typically share the same value, covering both the API and web service endpoints.

Local Development Configuration

During local development, OpenWork uses a test-kit server to automatically allocate ports and generate the required origin lists. The primary configuration logic lives in dev/evals/packages/testkit/src/server.ts.

Allocating Ports and Generating Origins

The system first allocates free ports for the API and web services, then constructs the trusted origins list using the trustedOrigins helper function:

// dev/evals/packages/testkit/src/server.ts (line ≈118)
export function trustedOrigins(apiPort: number, webPort: number): string[] {
  return [
    `http://localhost:${apiPort}`,
    `http://127.0.0.1:${apiPort}`,
    `http://localhost:${webPort}`,
    `http://127.0.0.1:${webPort}`,
  ];
}

This function ensures that both localhost and 127.0.0.1 variants are included for both services, preventing CORS issues during local testing.

Injecting Configuration into the Den Runtime

After generating the origins array, the development script joins them into a comma-separated string and injects all required variables into a commonEnv object:

// dev/evals/packages/testkit/src/server.ts (lines ≈46-51)
const [apiPort, webPort] = await allocateFreePorts(2);
const origins = trustedOrigins(apiPort, webPort).join(",");

const commonEnv = {
  BETTER_AUTH_SECRET: "local-dev-secret-not-for-production-use!!",
  BETTER_AUTH_URL: `http://localhost:${webPort}`,
  DEN_BETTER_AUTH_TRUSTED_ORIGINS: origins,
  CORS_ORIGINS: origins,
  // …other env vars
};

// Spawned processes inherit this environment
spawn("pnpm", ["dev:den:api"], { env: commonEnv, cwd: REPO_ROOT });
spawn("pnpm", ["dev:den:web"], { env: commonEnv, cwd: REPO_ROOT });

The dev-den.ts script demonstrates this pattern in practice, showing how the Den API and web services receive the configuration automatically through environment inheritance.

Production Configuration Best Practices

In production deployments, you must remove all fallback placeholders and inject secrets through a secure secret manager such as Infisical, HashiCorp Vault, or Kubernetes Secrets.

The Den services read these variables directly from process.env, so any standard injection method works:

ENV BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET}
ENV BETTER_AUTH_URL=${BETTER_AUTH_URL}
ENV DEN_BETTER_AUTH_TRUSTED_ORIGINS=${DEN_BETTER_AUTH_TRUSTED_ORIGINS}
ENV CORS_ORIGINS=${CORS_ORIGINS}

Ensure your BETTER_AUTH_SECRET is at least 32 bytes of cryptographically random data. Never commit production secrets to the repository or use the development fallback values in server.ts for live environments.

Implementation in the Den API

Inside the Den API service (ee/apps/den-api/src/auth.ts), the application consumes these environment variables to initialize Better-Auth and configure CORS middleware:

// ee/apps/den-api/src/auth.ts
const betterAuthSecret = process.env.BETTER_AUTH_SECRET ?? "";
if (!betterAuthSecret) throw new Error("BETTER_AUTH_SECRET is required");

// Trusted origins are used by the CORS middleware
app.use(cors({
  origin: process.env.CORS_ORIGINS?.split(",") ?? [],
}));

The API splits the comma-separated CORS_ORIGINS string back into an array for the middleware, while Better-Auth internally uses DEN_BETTER_AUTH_TRUSTED_ORIGINS to validate redirect URLs and callback origins.

Summary

  • Four variables are required: BETTER_AUTH_SECRET, BETTER_AUTH_URL, DEN_BETTER_AUTH_TRUSTED_ORIGINS, and CORS_ORIGINS.
  • Development automation: The trustedOrigins() helper in dev/evals/packages/testkit/src/server.ts automatically generates localhost variants for both API and web ports.
  • Environment inheritance: Both dev:den:api and dev:den:web processes receive configuration through a shared commonEnv object.
  • Production security: Replace development fallbacks with secrets from a vault; never use the hardcoded placeholder from line 26 of the test-kit server.
  • CORS coordination: CORS_ORIGINS and DEN_BETTER_AUTH_TRUSTED_ORIGINS should match to ensure browsers and the auth server agree on valid origins.

Frequently Asked Questions

What happens if I don't set DEN_BETTER_AUTH_TRUSTED_ORIGINS?

If DEN_BETTER_AUTH_TRUSTED_ORIGINS is missing, Better-Auth will reject authentication callbacks and redirect attempts as a security measure. According to the source code in ee/apps/den-api/src/auth.ts, the middleware relies on this variable to validate incoming requests against the whitelist.

How do I rotate the BETTER_AUTH_SECRET in production?

To rotate secrets, update the value in your secret manager and restart the Den API and web services. Since Better-Auth uses this secret for token signing, existing sessions will become invalid after rotation, forcing users to re-authenticate. Plan rotations during maintenance windows.

Can I use wildcards in CORS_ORIGINS for development?

The OpenWork source code splits CORS_ORIGINS by comma and passes it directly to the CORS middleware. While some CORS libraries support wildcards, the Better-Auth trusted origins check requires exact URL matches. Stick to explicit http://localhost:PORT and http://127.0.0.1:PORT entries as generated by the trustedOrigins() function.

Where is the Better-Auth secret validated at runtime?

The secret is validated in ee/apps/den-api/src/auth.ts, where the application throws an error if BETTER_AUTH_SECRET is empty. This ensures the server fails fast on startup rather than operating with an insecure configuration.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →