How to Set Up Dual-Key Authentication in CCX: PROXY_ACCESS_KEY vs ADMIN_ACCESS_KEY

To configure dual-key authentication in CCX, define PROXY_ACCESS_KEY for proxy API endpoints and optionally set ADMIN_ACCESS_KEY for management interfaces, enabling separate security credentials for proxy traffic and administrative operations.

CCX supports a robust dual-key authentication model that isolates proxy API access from administrative control. This architecture allows you to secure your chat completion endpoints (/v1/*) with one credential while protecting the web dashboard and management APIs (/api/*, /admin/*) with another. The implementation resides in the Go backend, specifically within backend-go/internal/config/env.go and backend-go/internal/middleware/auth.go.

Understanding the Dual-Key Architecture

CCX distinguishes between two distinct access keys, each serving a specific security domain.

PROXY_ACCESS_KEY for Proxy APIs

The PROXY_ACCESS_KEY serves as the primary credential for all proxy endpoints, including /v1/* and /v1beta/*. According to the source code in backend-go/internal/config/env.go (lines 59-61), this value is read from the PROXY_ACCESS_KEY environment variable with a default placeholder of your‑proxy‑access‑key. However, the application enforces a critical safety check in backend-go/main.go (lines 552-555): if you attempt to start CCX in production using this default value, the service will fail immediately with a "forbidden default value" error.

ADMIN_ACCESS_KEY for Management

The ADMIN_ACCESS_KEY controls access to the web UI and administrative endpoints under /api/* and /admin/*. As implemented in backend-go/internal/config/env.go (lines 111-116), the GetAdminAccessKey() function returns the configured admin key when set, but gracefully falls back to the PROXY_ACCESS_KEY value if ADMIN_ACCESS_KEY is undefined. This fallback ensures backward compatibility while allowing operators to enable true dual-key authentication by explicitly setting both variables.

Configuration Steps

Setting up dual-key authentication requires specific environment variables and adherence to production security protocols.

Environment Variable Setup

Create or modify your .env file (typically in the project root or backend-go/.env) to include both credentials:


# Required: Proxy access key for /v1/* endpoints

PROXY_ACCESS_KEY=sk-proxy-1234567890abcdef

# Optional: Separate admin key for /api/* and /admin/* endpoints

ADMIN_ACCESS_KEY=sk-admin-0987654321fedcba

When both variables are defined, CCX automatically routes proxy requests through PROXY_ACCESS_KEY validation while requiring ADMIN_ACCESS_KEY for management operations.

Production Safety Requirements

CCX implements strict safeguards against default credentials. In backend-go/main.go (lines 552-555), the application checks whether PROXY_ACCESS_KEY still contains the default value your‑proxy‑access‑key in production mode. If detected, the service exits immediately. You must explicitly override this value with a cryptographically secure key before deploying to production environments.

Authentication Flow Implementation

The dual-key system operates through distinct middleware paths depending on the endpoint type.

Web UI and Management API Authentication

middleware.WebAuthMiddleware handles security for administrative routes. As defined in backend-go/internal/middleware/auth.go (lines 51-55), this middleware intercepts requests to paths starting with /api or /admin, extracts the x-api-key header or Authorization: Bearer <key> token, and validates it against envCfg.GetAdminAccessKey(). If the provided key matches the configured admin key, access is granted; otherwise, the request returns a 401 Unauthorized response.

Proxy API Authentication

Proxy endpoints (/v1/*, /v1beta/*) follow a different pattern. These routes typically pass through initial middleware checks before reaching upstream handlers. In backend-go/internal/utils/headers.go (lines 143-144), the SetAuthenticationHeader function injects the appropriate API key into upstream requests. While the proxy endpoints may appear to "directly放行" (pass through) initial checks, downstream validation ensures that only requests bearing valid PROXY_ACCESS_KEY credentials in their headers succeed.

Practical Code Examples

Environment Configuration

Store your dual keys securely:

PROXY_ACCESS_KEY=sk-proxy-live-abc123xyz789
ADMIN_ACCESS_KEY=sk-admin-secure-def456uvw321

Accessing Proxy Endpoints

Use the proxy key for chat completions:

curl -H "Authorization: Bearer sk-proxy-live-abc123xyz789" \
     http://localhost:8000/v1/chat/completions \
     -d '{"model":"gpt-4","messages":[{"role":"user","content":"Hello"}]}'

Accessing Management APIs

Use the admin key for configuration endpoints:

curl -H "x-api-key: sk-admin-secure-def456uvw321" \
     http://localhost:8000/api/channels/list

Programmatic Key Access

When extending CCX functionality, access keys through the configuration API:

cfg, _ := config.LoadEnvConfig()
proxyKey := cfg.ProxyAccessKey
adminKey := cfg.GetAdminAccessKey() // Returns ADMIN_ACCESS_KEY or falls back to PROXY_ACCESS_KEY

fmt.Println("Proxy key:", proxyKey[:10]+"...")
fmt.Println("Admin key:", adminKey[:10]+"...")

Implementing Custom Middleware

Reuse the built-in authentication logic in custom routes:

r := gin.Default()
envCfg, _ := config.LoadEnvConfig()
r.Use(middleware.WebAuthMiddleware(envCfg, nil))
// Routes defined here automatically respect dual-key authentication

Summary

  • Dual-key architecture: CCX supports separate PROXY_ACCESS_KEY for proxy APIs and ADMIN_ACCESS_KEY for management interfaces, implemented in backend-go/internal/config/env.go.
  • Fallback behavior: If ADMIN_ACCESS_KEY is unset, GetAdminAccessKey() returns the proxy key, maintaining backward compatibility.
  • Production enforcement: The application refuses to start in production if PROXY_ACCESS_KEY retains its default value your‑proxy‑access‑key.
  • Middleware separation: WebAuthMiddleware validates admin keys for /api/* and /admin/* routes, while proxy endpoints utilize key injection via SetAuthenticationHeader in backend-go/internal/utils/headers.go.

Frequently Asked Questions

What happens if I only set PROXY_ACCESS_KEY and not ADMIN_ACCESS_KEY?

CCX will operate in single-key mode. The GetAdminAccessKey() function in backend-go/internal/config/env.go detects the empty admin key and returns the proxy key value instead. Both proxy endpoints and management interfaces will use the same credential, which simplifies setup but reduces security isolation.

Why does CCX refuse to start with the default PROXY_ACCESS_KEY?

This is a deliberate safety mechanism defined in backend-go/main.go (lines 552-555) to prevent accidental deployment with insecure default credentials. The code explicitly checks if the key equals your‑proxy‑access‑key and exits with an error if found in production environments, forcing operators to generate cryptographically secure keys.

Which HTTP headers should I use for each key?

For proxy endpoints (/v1/*), use Authorization: Bearer <PROXY_ACCESS_KEY>. For management endpoints (/api/*, /admin/*), you can use either x-api-key: <ADMIN_ACCESS_KEY> or Authorization: Bearer <ADMIN_ACCESS_KEY>. The WebAuthMiddleware in backend-go/internal/middleware/auth.go (lines 51-55) accepts both header formats for administrative access.

Can I rotate these keys without restarting CCX?

Based on the current implementation in backend-go/internal/config/env.go, configuration values are loaded at startup via LoadEnvConfig(). To rotate keys, you must update your environment variables and restart the CCX service to reload the configuration. There is no hot-reload mechanism for authentication credentials in the current codebase.

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 →