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

> Learn to set up dual-key authentication in CCX using PROXY_ACCESS_KEY and ADMIN_ACCESS_KEY for distinct proxy and admin access control. Secure your CCX environment effectively.

- Repository: [Benedict King/ccx](https://github.com/BenedictKing/ccx)
- Tags: how-to-guide
- Published: 2026-05-29

---

**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`](https://github.com/BenedictKing/ccx/blob/main/backend-go/internal/config/env.go) and [`backend-go/internal/middleware/auth.go`](https://github.com/BenedictKing/ccx/blob/main/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`](https://github.com/BenedictKing/ccx/blob/main/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`](https://github.com/BenedictKing/ccx/blob/main/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`](https://github.com/BenedictKing/ccx/blob/main/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:

```dotenv

# 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`](https://github.com/BenedictKing/ccx/blob/main/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`](https://github.com/BenedictKing/ccx/blob/main/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`](https://github.com/BenedictKing/ccx/blob/main/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:

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

```

### Accessing Proxy Endpoints

Use the proxy key for chat completions:

```bash
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:

```bash
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:

```go
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:

```go
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`](https://github.com/BenedictKing/ccx/blob/main/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`](https://github.com/BenedictKing/ccx/blob/main/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`](https://github.com/BenedictKing/ccx/blob/main/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`](https://github.com/BenedictKing/ccx/blob/main/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`](https://github.com/BenedictKing/ccx/blob/main/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`](https://github.com/BenedictKing/ccx/blob/main/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.