How ClosedClaw Gateway Authenticates Incoming Connections and Enforces Token-Based Security

ClosedClaw's gateway authenticates every incoming WebSocket or HTTP connection through a centralized routine in src/gateway/auth.ts that resolves configuration, performs timing-safe credential verification, and rejects unauthorized requests with explicit error messages.

The ClosedClaw gateway implements a robust, multi-layered authentication system designed to secure WebSocket and HTTP connections against unauthorized access. By combining configuration-driven policies with cryptographic best practices, the gateway ensures that only clients with valid tokens or passwords can establish connections. This article examines the complete authentication flow as implemented in the asafelobotomy/closedclaw repository, from configuration resolution to connection rejection.

Authentication Flow Overview

The gateway processes every incoming connection through three distinct stages defined in src/gateway/auth.ts. First, the system resolves the active authentication configuration from files or environment variables. Second, it verifies client-supplied credentials using timing-safe comparison functions. Third, it either accepts the connection or rejects it with a structured error message and WebSocket close code 1008.

Stage 1: Resolving Gateway Authentication Configuration

Configuration Sources and Precedence

The resolveGatewayAuth function (lines 200-221 of src/gateway/auth.ts) establishes the authentication policy by reading the gateway.auth configuration section. The system supports two primary modes: token (default) and password. When the configuration file does not specify credentials, the gateway automatically falls back to environment variables to maintain operational flexibility.

Environment Variable Overrides

For runtime flexibility without configuration file modifications, the gateway checks for ClosedClaw_GATEWAY_TOKEN and ClosedClaw_GATEWAY_PASSWORD environment variables. These variables override any static configuration values, enabling secure token rotation in containerized environments. The resolution logic also evaluates the allowTailscale boolean, which determines whether Tailscale identity headers can serve as an authentication bypass for trusted network requests.

Stage 2: Verifying Client Credentials

Token-Based Authentication

When operating in token mode, the authorizeGatewayConnect function (lines 263-273 of src/gateway/auth.ts) requires clients to transmit a token field in the connection request. The gateway compares the submitted value against the resolved configuration using the safeEqual utility, which implements constant-time comparison to prevent timing side-channel attacks.

Password-Based Authentication

For deployments using password mode, the verification occurs at lines 284-286 of src/gateway/auth.ts. Clients must provide a password field, which undergoes the same safeEqual comparison as tokens. Password mode is typically used in development environments or when integrating with existing credential management systems.

Timing-Safe Comparison

The safeEqual function wraps Node.js crypto.timingSafeEqual to ensure that credential comparisons take constant time regardless of how many characters match. This prevents attackers from inferring valid credentials by measuring response times during brute-force attempts.

Tailscale Identity Verification

When allowTailscale is enabled and the request originates from outside the local machine, the gateway inspects validated Tailscale headers to identify the connecting user. If Tailscale identity verification succeeds, the gateway bypasses token and password requirements, treating the connection as pre-authenticated by the Tailscale network layer.

Stage 3: Connection Acceptance and Rejection

The attachGatewayWsMessageHandler function (lines 670-724 of src/gateway/server/ws-connection/message-handler.ts) orchestrates the final connection decision. When authorizeGatewayConnect returns { ok: false, reason: … }, the handler invokes formatGatewayAuthFailureMessage to generate a descriptive error message indicating whether the token or password was missing or invalid.

The gateway then closes the WebSocket connection with status code 1008 (Policy Violation), signaling to clients that authentication failed. This explicit rejection prevents connection hanging and provides clear feedback for debugging client configurations.

Configuring Token-Based Security Policies

Generating Secure Tokens

When initial configuration lacks a token, the onboarding wizard executes randomToken (lines 69-71 of src/commands/onboard-helpers.ts) to generate a cryptographically secure 48-byte hexadecimal string using Node.js crypto.randomBytes. This token is persisted to gateway.auth.token in the configuration file and can be overridden at runtime via the ClosedClaw_GATEWAY_TOKEN environment variable.

Allowing Insecure HTTP Authentication

The Control UI supports token-only authentication over plain HTTP when the allowInsecureAuth flag is enabled in src/config/types.gateway.ts (lines 69-71). This configuration relaxes the HTTPS requirement for browser-based UI access while maintaining the same token verification logic. Production deployments should disable this flag to prevent token interception.

Client Connection Examples

To establish an authenticated connection, clients use the callGateway helper from src/gateway/call.ts:

import { callGateway } from "./gateway/call.js";

await callGateway({
  url: "ws://localhost:18789",
  token: "your‑secure‑generated‑token",
  method: "health",
  clientName: "my‑script",
  mode: "probe",
});

The helper automatically forwards the token to authorizeGatewayConnect for validation.

For environment-based authentication without modifying configuration files:

export ClosedClaw_GATEWAY_TOKEN=env‑override‑token
closedclaw start

Summary

  • Centralized authentication occurs in src/gateway/auth.ts through the resolveGatewayAuth and authorizeGatewayConnect functions.
  • Dual credential modes support both token-based and password-based authentication, with tokens generated cryptographically via randomToken in src/commands/onboard-helpers.ts.
  • Timing-safe comparisons using safeEqual prevent side-channel attacks during credential verification.
  • Flexible configuration allows runtime overrides via ClosedClaw_GATEWAY_TOKEN and ClosedClaw_GATEWAY_PASSWORD environment variables.
  • Tailscale integration provides optional identity-based authentication bypass when allowTailscale is enabled.
  • Explicit rejection of unauthorized connections uses WebSocket status code 1008 with descriptive error messages formatted by formatGatewayAuthFailureMessage.

Frequently Asked Questions

What authentication modes does ClosedClaw support?

ClosedClaw supports two primary authentication modes defined in src/config/types.gateway.ts: token (default) and password. Token mode requires clients to provide a hexadecimal string generated by the randomToken function, while password mode accepts a configurable password string. Both modes support runtime overrides through environment variables ClosedClaw_GATEWAY_TOKEN and ClosedClaw_GATEWAY_PASSWORD.

How does ClosedClaw prevent timing attacks during authentication?

The gateway uses the safeEqual utility function in src/gateway/auth.ts to perform constant-time comparison of credentials. This function wraps Node.js crypto.timingSafeEqual, ensuring that the comparison operation takes the same amount of time regardless of how many characters match between the submitted and stored credentials. This prevents attackers from inferring valid tokens or passwords by measuring response latency.

Can I use Tailscale instead of tokens?

Yes, when the allowTailscale configuration option is enabled, ClosedClaw accepts validated Tailscale identity headers as an authentication bypass. If the request originates from a trusted Tailscale proxy and contains valid identity headers, the gateway treats the connection as pre-authenticated without requiring a token or password. This integration is handled within the authorizeGatewayConnect function alongside standard credential verification.

How do I rotate or update gateway tokens?

You can rotate tokens without modifying configuration files by using the ClosedClaw_GATEWAY_TOKEN environment variable, which takes precedence over the gateway.auth.token configuration value. For permanent rotation, update the token in your configuration file or run the onboarding wizard again to generate a new cryptographically secure token via the randomToken function. All connected clients must use the new token to establish subsequent connections.

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 →