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

> Configure Better-Auth in OpenWork with secrets, trusted origins, and CORS. Learn to set up environment variables for secure authentication and origin whitelisting.

- Repository: [Different AI/openwork](https://github.com/different-ai/openwork)
- Tags: how-to-guide
- Published: 2026-08-04

---

**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`](https://github.com/different-ai/openwork/blob/main/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`](https://github.com/different-ai/openwork/blob/main/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:

```typescript
// 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:

```typescript
// 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`](https://github.com/different-ai/openwork/blob/main/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:

```Dockerfile
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`](https://github.com/different-ai/openwork/blob/main/server.ts) for live environments.

## Implementation in the Den API

Inside the Den API service ([`ee/apps/den-api/src/auth.ts`](https://github.com/different-ai/openwork/blob/main/ee/apps/den-api/src/auth.ts)), the application consumes these environment variables to initialize Better-Auth and configure CORS middleware:

```typescript
// 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`](https://github.com/different-ai/openwork/blob/main/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`](https://github.com/different-ai/openwork/blob/main/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`](https://github.com/different-ai/openwork/blob/main/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.