Auth Proxy
What it does
Section titled “What it does”The auth-proxy is a standalone HTTP gateway that lets external services reuse Aether’s identity model and Casbin ACL engine without speaking the gateway’s gRPC protocol. It connects to the same PostgreSQL database as the Aether gateway, reads the acl_rules table via the Casbin enforcer, and validates every inbound HTTP request before the request reaches its destination.
Two operating modes are supported. In proxy mode (the default) the binary acts as a reverse proxy: it authenticates the caller, evaluates workspace ACL, injects trusted X-Auth-* identity headers, strips the Authorization header, then forwards the request to a configured backend. In verify mode it exposes a single /auth/verify endpoint compatible with nginx auth_request and Envoy ext_authz — it returns 200 with identity headers on success or 401/403 on failure, and all routing decisions stay with the upstream proxy.
When to use it
Section titled “When to use it”- Fronting a service (such as MemoryLayer) that needs Aether-validated identity headers but cannot consume the gateway’s gRPC API directly.
- Integrating nginx
auth_requestor Envoyext_authzinto an existing infrastructure stack while reusing Aether’s ACL rules. - Adding browser-based OAuth login (Azure, Google, or any OIDC provider) to a service that would otherwise require API-key–only access.
- Providing token-HMAC parity with the gateway so API keys issued by Aether validate identically in the sidecar path.
Architecture
Section titled “Architecture”Browser / Service │ Authorization: Bearer <token> ▼┌─────────────────┐│ auth-proxy │ :8080│ (proxy mode) ││ │──── acl_rules ─────► PostgreSQL│ Casbin ACL │◄─── api_tokens ────► (shared with gateway)│ Composite auth ││ Identity hdrs │└────────┬────────┘ │ X-Auth-User, X-Auth-Tenant, … ▼ Backend service (e.g. MemoryLayer)The binary builds a CasbinEnforcer directly from the shared acl_rules table — no Aether gateway connection is required at runtime. Credentials are verified in order: API key (always active when a DB is present), OAuth/JWT bearer token (optional), and Azure Entra JWT (optional). A CompositeAuthenticator tries each method in turn and returns the first match. When AUTH_PROXY_LOGIN_PROVIDERS is set, a session-cookie authenticator is also appended to the chain.
After authentication, workspace ACL is evaluated using the same Casbin model as the gateway. Fail-closed semantics apply: a missing ACL rule denies access.
On-behalf-of (OBO) requests
Section titled “On-behalf-of (OBO) requests”Callers may supply X-Aether-Grant-ID, X-Aether-Subject-Type, and X-Aether-Subject-ID headers to assert an OBO authority grant. The proxy validates the grant against the ACL service before injecting authority headers downstream. Requests without a resolver configured receive 501 Not Implemented.
Quick start
Section titled “Quick start”# Minimum: proxy mode against a local backendexport AUTH_PROXY_DB_URL="postgres://aether:secret@localhost:5432/aether?sslmode=disable"export AUTH_PROXY_BACKEND_URL="http://localhost:61001"export AUTH_PROXY_TENANT_ID="default"
go run ./server/cmd/auth-proxyThe proxy listens on :8080. All requests are authenticated and forwarded to the backend with X-Auth-* identity headers injected.
# Verify mode (nginx auth_request / Envoy ext_authz)export AUTH_PROXY_MODE=verifyexport AUTH_PROXY_DB_URL="postgres://aether:secret@localhost:5432/aether?sslmode=disable"
go run ./server/cmd/auth-proxy# nginx: auth_request http://auth-proxy:8080/auth/verify;Configuration
Section titled “Configuration”All configuration is via environment variables. There is no YAML config file for this binary — LoadConfigFromEnv() reads AUTH_PROXY_* directly at startup.
| Environment variable | Default | Description |
|---|---|---|
AUTH_PROXY_DB_URL | required | PostgreSQL DSN (shared with Aether gateway). |
AUTH_PROXY_MODE | proxy | proxy — reverse-proxy with header injection. verify — auth-only for nginx/Envoy. |
AUTH_PROXY_LISTEN_ADDR | :8080 | HTTP (or HTTPS) listen address. |
AUTH_PROXY_BACKEND_URL | http://localhost:61001 | Upstream URL in proxy mode. |
AUTH_PROXY_TENANT_ID | default | Tenant identifier injected into X-Auth-Tenant and related headers. |
AUTH_PROXY_LOG_LEVEL | info | Structured log level: debug, info, warn, error. |
AUTH_PROXY_CORS_ORIGIN | (none) | Sets Access-Control-Allow-Origin; enables CORS middleware when non-empty. |
AUTH_PROXY_REDIS_ADDR | (none) | Optional Redis for token cache and session store fallback. |
AUTH_PROXY_TOKEN_HMAC_KEY | (none) | HMAC-SHA256 key for token hashing — must match the gateway’s key. |
AUTH_PROXY_SECRETS_FILE | (none) | Path to gateway-generated secrets JSON (alternative to explicit HMAC key). |
AUTH_PROXY_TLS_CERT_FILE | (none) | PEM certificate file for HTTPS. |
AUTH_PROXY_TLS_KEY_FILE | (none) | PEM private key file for HTTPS. |
OAuth / JWT bearer tokens
Section titled “OAuth / JWT bearer tokens”| Environment variable | Default | Description |
|---|---|---|
AUTH_PROXY_OAUTH_ISSUER | (none) | Issuer URL for bearer-token validation. Enables OAuth auth when set. |
AUTH_PROXY_OAUTH_JWKS_URL | (none) | JWKS endpoint URL. |
AUTH_PROXY_OAUTH_AUDIENCE | (none) | Expected aud claim. |
AUTH_PROXY_OAUTH_VERIFY_SIGNATURE | true | Set false only with AETHER_DEV_MODE=true. |
Azure Entra (Azure AD)
Section titled “Azure Entra (Azure AD)”| Environment variable | Default | Description |
|---|---|---|
AUTH_PROXY_ENTRA_TENANT_ID | (none) | Entra tenant ID. Enables Entra auth when set together with client ID. |
AUTH_PROXY_ENTRA_CLIENT_ID | (none) | Entra application (client) ID. |
AUTH_PROXY_ENTRA_ALLOWED_TENANTS | (none) | Comma-separated whitelist of acceptable Entra tid values. |
AUTH_PROXY_ENTRA_VERIFY_SIGNATURE | true | Set false only with AETHER_DEV_MODE=true. |
Identity rules
Section titled “Identity rules”| Environment variable | Default | Description |
|---|---|---|
AUTH_PROXY_ALLOWED_EMAIL_DOMAINS | (none) | Comma-separated email-domain allow-list applied during single-tenant login. |
Browser-based login (optional)
Section titled “Browser-based login (optional)”Login flow is disabled by default. Set AUTH_PROXY_LOGIN_PROVIDERS to enable it. When enabled, the following routes are mounted:
| Route | Description |
|---|---|
GET /auth/login/<name> | Initiates the OIDC redirect for provider <name>. |
GET /auth/callback/<name> | OAuth callback handler; issues a session cookie. |
GET /auth/logout | Clears the session cookie. |
GET /auth/me | Returns the current session identity as JSON. |
GET /auth/checkz | Lightweight session liveness check. |
| Environment variable | Default | Description |
|---|---|---|
AUTH_PROXY_LOGIN_PROVIDERS | (empty — login disabled) | Comma-separated provider names, e.g. azure,google. |
AUTH_PROXY_LOGIN_<NAME>_ISSUER | (none) | OIDC issuer URL for provider <NAME>. |
AUTH_PROXY_LOGIN_<NAME>_CLIENT_ID | (none) | OAuth client ID. |
AUTH_PROXY_LOGIN_<NAME>_CLIENT_SECRET | (none) | OAuth client secret. |
AUTH_PROXY_LOGIN_<NAME>_REDIRECT_URL | (none) | OAuth redirect URL (/auth/callback/<name>). |
AUTH_PROXY_LOGIN_<NAME>_SCOPES | (provider default) | Additional OAuth scopes (comma-separated). |
AUTH_PROXY_LOGIN_<NAME>_ALLOWED_TENANTS | (none) | Per-provider tenant allow-list. |
Session store (when login is enabled)
Section titled “Session store (when login is enabled)”| Environment variable | Default | Description |
|---|---|---|
AUTH_PROXY_SESSION_STORE | redis | redis (opaque token) or jwt (signed cookie). |
AUTH_PROXY_SESSION_COOKIE_NAME | aether_session | Cookie name. |
AUTH_PROXY_SESSION_COOKIE_DOMAIN | (none) | Cookie Domain attribute. |
AUTH_PROXY_SESSION_COOKIE_SECURE | true | Cookie Secure attribute. |
AUTH_PROXY_SESSION_COOKIE_SAMESITE | lax | Cookie SameSite: lax, strict, or none. |
AUTH_PROXY_SESSION_TTL | 24h | Session lifetime (Go duration string). |
AUTH_PROXY_SESSION_JWT_SIGNING_KEY | (none) | HS256 signing key (min 32 bytes); required when SESSION_STORE=jwt. |
AUTH_PROXY_SESSION_REDIS_ADDR | falls back to AUTH_PROXY_REDIS_ADDR | Redis address for session storage. |
AUTH_PROXY_SESSION_REDIS_PASSWORD | (none) | Redis password. |
AUTH_PROXY_SESSION_REDIS_DB | 0 | Redis logical DB index. |
AUTH_PROXY_SESSION_REDIS_PREFIX | auth-session: | Redis key prefix. |
Full list: see Environment Variables.
HTTP endpoints
Section titled “HTTP endpoints”| Endpoint | Auth required | Description |
|---|---|---|
GET /healthz | No | Liveness probe. Returns {"status":"ok"} with HTTP 200. |
ANY /auth/verify | Yes | Auth-verify endpoint for nginx/Envoy. Returns 200 + identity headers or 401/403. |
ANY / | Yes | Proxy mode only: authenticates and forwards to backend. |
Operational notes
Section titled “Operational notes”Pass both AUTH_PROXY_TLS_CERT_FILE and AUTH_PROXY_TLS_KEY_FILE to enable HTTPS. When either is absent, the server falls back to plaintext HTTP and logs a warning. In production, terminate TLS at the proxy or provide certificates directly.
Health and readiness
Section titled “Health and readiness”GET /healthz returns {"status":"ok"} once the server is accepting connections. There is no separate readiness endpoint — use a startup probe that checks /healthz after allowing time for the PostgreSQL connection to establish (typically a few seconds).
Deployment topology
Section titled “Deployment topology”- Sidecar (proxy mode): deploy alongside the backend service in the same pod or network namespace. The backend need not be reachable from outside the pod.
- Centralised verify (verify mode): deploy as a shared service; configure nginx
auth_requestor Envoyext_authzto call/auth/verify. Identity headers are returned to nginx/Envoy for forwarding. - The auth-proxy shares the Aether PostgreSQL database but maintains no tables of its own. It uses a conservative connection pool (10 max, 5 idle, 5-minute lifetime).
Troubleshooting
Section titled “Troubleshooting”Startup fails: AUTH_PROXY_DB_URL is required
The only required variable is the database DSN. Set AUTH_PROXY_DB_URL before starting.
Startup fails: failed to connect to PostgreSQL
The proxy pings the database within a 5-second timeout. Verify network connectivity, credentials, and that the acl_rules table exists (created by the gateway’s migrations).
API keys return 401 after migration
If the gateway is configured with a token HMAC key, the auth-proxy must use the same key. Set AUTH_PROXY_TOKEN_HMAC_KEY to the same value, or point AUTH_PROXY_SECRETS_FILE at the gateway’s generated secrets file.
JWT signature verification fails at startup
Setting AUTH_PROXY_OAUTH_VERIFY_SIGNATURE=false or AUTH_PROXY_ENTRA_VERIFY_SIGNATURE=false without AETHER_DEV_MODE=true causes a hard startup error by design. Only disable signature verification in development environments.
Login providers fail with redis ping error
When AUTH_PROXY_LOGIN_PROVIDERS is set and AUTH_PROXY_SESSION_STORE=redis (the default), a reachable Redis instance is required. Either set AUTH_PROXY_SESSION_REDIS_ADDR, or fall back to AUTH_PROXY_SESSION_STORE=jwt with a 32-byte signing key.
Requests return 403 with no matching ACL rule
The Casbin enforcer is fail-closed. Add an ACL rule in the gateway’s admin UI (or directly in the acl_rules table) granting the principal read access to the target workspace.