Files
auth-proxy/docs/security.md
db123-test ffd5f0fc35 docs(security): clarify IPv6 support for whitelist endpoints
Update docs/security.md to reflect that the
/api/whitelist endpoints now accept both
IPv4 and IPv6 addresses, removing the
previous statement that IPv6 was unsupported.
2026-05-05 19:25:28 +03:30

3.3 KiB

Auth-proxy Security Model

Authentication flow

  1. Client request arrives at NGINX.
  2. NGINX sends an internal auth_request subrequest to auth-proxy.
  3. Auth-proxy checks:
    • Is the IP in the permanent whitelist? → Allow.
    • Is the IP in the temporary whitelist and not expired? → Allow.
    • Otherwise → 401 Unauthorized.
  4. NGINX passes the request to the upstream service if auth-proxy returned 200.
  5. NGINX returns 401 to the client if auth-proxy returned 401/403.

IP handling

Permanent whitelist

  • Stored in SQLite permanent_whitelist table.
  • Only single IPs and CIDR ranges (as strings) are supported.
  • Added/removed via the /api/whitelist/perm API.

Temporary whitelist

  • Stored in SQLite temp_whitelist table.
  • Entries expire after their TTL.
  • The cleanup goroutine runs every 60 seconds (configurable) to remove expired entries.

API key

The API key is the only secret for the /api/* endpoints. It's sent as a bearer token in the Authorization header.

  • Required. The service will not start without it.
  • Keep it secret. Don't log it. Don't put it in the URL.
  • Use a strong random string.
  • Rotate it regularly.

Audit log

All whitelist operations are logged to the audit_log table in SQLite. Each entry records:

  • action — what happened (add_temp, delete_temp, add_perm, delete_perm, expire_temp)
  • ip — the affected IP or CIDR range
  • ttl_seconds — for temp entries
  • reason — the reason provided
  • api_client_ip — the IP that made the API call (from NGINX X-Real-IP)

Retrieve logs via the /api/logs endpoint.

The audit log is automatically rotated to maintain a maximum of 200,000 entries.

IP validation

The /api/whitelist/temp and /api/whitelist/perm endpoints validate inputs:

  • /api/whitelist/temp requires a valid IP address.
  • /api/whitelist/perm requires a valid IP address or CIDR range.
  • Invalid inputs return 400 Bad Request.

Graceful shutdown

The service listens for SIGTERM and SIGINT. On signal:

  1. Stop accepting new connections.
  2. Close idle connections.
  3. Wait for in-flight requests to complete (up to 30 seconds).
  4. Exit.

This ensures Docker deployments can shut down cleanly.

What we don't do

  • We don't support JWT/OAuth. If you need these, add them later.
  • We don't support session state. The auth decision is made per-request.
  • We don't support rate limiting. Use NGINX's limit_req for that.
  • We don't support IP-based rate limiting. Use NGINX's limit_conn for that.
  • We support IPv6. The /api/whitelist endpoints accept both IPv4 and IPv6 addresses.
  • We don't support TLS. The auth endpoint should always be served over TLS.
  • We don't support logging to a file. Logs go to stdout (Docker).
  • We don't support metrics. If you need metrics, add them later.
  • We don't support health checks with Prometheus. The /status endpoint returns a JSON response with uptime, DB status, and whitelist counts.
  • We don't support configuration via a config file. Use environment variables.
  • We don't support multiple domains. The auth-proxy service doesn't care about domains.
  • We don't support HTTP/2. The auth-proxy service uses HTTP/1.1 only.
  • We don't support WebSocket. The auth-proxy service doesn't need WebSocket.
  • We don't support gRPC. The auth-proxy service is a simple REST API.