Files
Charon/docs/security/archive/websocket-auth-security.md
akanealw eec8c28fb3
Some checks failed
Go Benchmark / Performance Regression Check (push) Has been cancelled
Cerberus Integration / Cerberus Security Stack Integration (push) Has been cancelled
Upload Coverage to Codecov / Backend Codecov Upload (push) Has been cancelled
Upload Coverage to Codecov / Frontend Codecov Upload (push) Has been cancelled
CodeQL - Analyze / CodeQL analysis (go) (push) Has been cancelled
CodeQL - Analyze / CodeQL analysis (javascript-typescript) (push) Has been cancelled
CrowdSec Integration / CrowdSec Bouncer Integration (push) Has been cancelled
Docker Build, Publish & Test / build-and-push (push) Has been cancelled
Quality Checks / Auth Route Protection Contract (push) Has been cancelled
Quality Checks / Codecov Trigger/Comment Parity Guard (push) Has been cancelled
Quality Checks / Backend (Go) (push) Has been cancelled
Quality Checks / Frontend (React) (push) Has been cancelled
Rate Limit integration / Rate Limiting Integration (push) Has been cancelled
Security Scan (PR) / Trivy Binary Scan (push) Has been cancelled
Supply Chain Verification (PR) / Verify Supply Chain (push) Has been cancelled
WAF integration / Coraza WAF Integration (push) Has been cancelled
Docker Build, Publish & Test / Security Scan PR Image (push) Has been cancelled
Repo Health Check / Repo health (push) Has been cancelled
History Rewrite Dry-Run / Dry-run preview for history rewrite (push) Has been cancelled
Prune Renovate Branches / prune (push) Has been cancelled
Renovate / renovate (push) Has been cancelled
Nightly Build & Package / sync-development-to-nightly (push) Has been cancelled
Nightly Build & Package / Trigger Nightly Validation Workflows (push) Has been cancelled
Nightly Build & Package / build-and-push-nightly (push) Has been cancelled
Nightly Build & Package / test-nightly-image (push) Has been cancelled
Nightly Build & Package / verify-nightly-supply-chain (push) Has been cancelled
changed perms
2026-04-22 18:19:14 +00:00

4.6 KiB
Executable File

title, description
title description
WebSocket Authentication Security Security documentation for WebSocket authentication in Charon. HttpOnly cookie implementation and token protection.

WebSocket Authentication Security

Overview

This document explains the security improvements made to WebSocket authentication in Charon to prevent JWT tokens from being exposed in access logs.

Security Issue

Before (Insecure)

Previously, WebSocket connections authenticated by passing the JWT token as a query parameter:

wss://example.com/api/v1/logs/live?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Security Risk:

  • Query parameters are logged in web server access logs (Caddy, nginx, Apache, etc.)
  • Tokens appear in proxy logs
  • Tokens may be stored in browser history
  • Tokens can be captured in monitoring and telemetry systems
  • An attacker with access to these logs can replay the token to impersonate a user

After (Secure)

WebSocket connections now authenticate using HttpOnly cookies:

wss://example.com/api/v1/logs/live?source=waf&level=error

The browser automatically sends the auth_token cookie with the WebSocket upgrade request.

Security Benefits:

  • HttpOnly cookies are not logged by web servers
  • HttpOnly cookies cannot be accessed by JavaScript (XSS protection)
  • Cookies are not visible in browser history
  • Cookies are not captured in URL-based monitoring
  • Token replay attacks are mitigated (tokens still have expiration)

Implementation Details

Frontend Changes

Location: frontend/src/api/logs.ts

Removed:

const token = localStorage.getItem('charon_auth_token');
if (token) {
  params.append('token', token);
}

The browser automatically sends the auth_token cookie when establishing WebSocket connections due to:

  1. The cookie is set by the backend during login with HttpOnly, Secure, and SameSite flags
  2. The axios client has withCredentials: true, enabling cookie transmission

Backend Changes

Location: backend/internal/api/middleware/auth.go

Authentication priority order:

  1. Authorization header (Bearer token) - for API clients
  2. auth_token cookie (HttpOnly) - preferred for browsers and WebSockets
  3. token query parameter - deprecated, kept for backward compatibility only

The query parameter fallback is marked as deprecated and will be removed in a future version.

Location: backend/internal/api/handlers/auth_handler.go

The auth_token cookie is set with security best practices:

  • HttpOnly: true - prevents JavaScript access (XSS protection)
  • Secure: true (in production with HTTPS) - prevents transmission over HTTP
  • SameSite: Strict (HTTPS) or Lax (HTTP/IP) - CSRF protection
  • Path: / - available for all routes
  • MaxAge: 24 hours - automatic expiration

Verification

Test Coverage

Location: backend/internal/api/middleware/auth_test.go

  • TestAuthMiddleware_Cookie - verifies cookie authentication works
  • TestAuthMiddleware_QueryParamFallback - verifies deprecated query param still works
  • TestAuthMiddleware_PrefersCookieOverQueryParam - verifies cookie is prioritized over query param
  • TestAuthMiddleware_PrefersAuthorizationHeader - verifies header takes highest priority

Log Verification

To verify tokens are not logged:

  1. Before the fix: Check Caddy access logs for token exposure:

    docker logs charon 2>&1 | grep "token=" | grep -o "token=[^&]*"
    

    Would show: token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

  2. After the fix: Check that WebSocket URLs are clean:

    docker logs charon 2>&1 | grep "/logs/live\|/cerberus/logs/ws"
    

    Shows: /api/v1/logs/live?source=waf&level=error (no token)

Migration Path

For Users

No action required. The change is transparent:

  • Login sets the HttpOnly cookie
  • WebSocket connections automatically use the cookie
  • Existing sessions continue to work

For API Clients

API clients using Authorization headers are unaffected.

Deprecation Timeline

  1. Current: Query parameter authentication is deprecated but still functional
  2. Future (v2.0): Query parameter authentication will be removed entirely
  3. Recommendation: Any custom scripts or tools should migrate to using Authorization headers or cookie-based authentication