Install Policies

Focus

Install-Time & Auth-Mode Policies

Install policies enforce security requirements during initial deployment. They determine whether a gateway token is required at install time and prevent ambiguous auth configurations where both token and password are set without an explicit mode declaration.

Install Policy auth-install-policy.ts
Mode Policy auth-mode-policy.ts
Config Utils auth-config-utils.ts
Error Constant EXPLICIT_GATEWAY_AUTH_MODE_REQUIRED_ERROR

Table of Contents

Overview

Two distinct but related policy systems ensure auth is properly configured:

  1. Install Policy (auth-install-policy.ts) — decides whether a gateway token must be generated during openclaw install
  2. Auth Mode Policy (auth-mode-policy.ts) — detects and rejects ambiguous configurations where both token and password exist without an explicit mode
🛑 Breaking change: If both auth.token and auth.password are configured without setting auth.mode explicitly, assertExplicitGatewayAuthModeWhenBothConfigured() will throw EXPLICIT_GATEWAY_AUTH_MODE_REQUIRED_ERROR. This prevents silent fallback to an unintended auth method.

Install Policy Decision Flow

flowchart TB
    START["openclaw install"]
    CHECK["shouldRequireGatewayTokenForInstall(cfg, env)"]
    EXPLICIT["hasExplicitGatewayInstallAuthMode(mode)?"]
    PASS_CFG["hasConfiguredGatewayPasswordForInstall(cfg)?"]
    PASS_ENV["hasDurableGatewayPasswordEnvForInstall(cfg, env)?"]
    TOKEN_REQ["Token REQUIRED
Generate during install"] TOKEN_SKIP["Token NOT required
Password auth sufficient"] START --> CHECK CHECK --> EXPLICIT EXPLICIT -->|"mode explicitly set"| TOKEN_SKIP EXPLICIT -->|"no explicit mode"| PASS_CFG PASS_CFG -->|"password in config"| TOKEN_SKIP PASS_CFG -->|"no password"| PASS_ENV PASS_ENV -->|"password in env"| TOKEN_SKIP PASS_ENV -->|"no password"| TOKEN_REQ

How It Works

Install Policy Check

shouldRequireGatewayTokenForInstall() is called during the installation process. It checks three sources in order: explicit install auth mode, config file password, and environment variable password.

import { shouldRequireGatewayTokenForInstall } from './auth-install-policy';

const needsToken = shouldRequireGatewayTokenForInstall(
  openClawConfig,
  process.env,
);

if (needsToken) {
  const token = generateSecureToken();
  console.log(`Gateway token: ${token}`);
  // Store token in config
}

Auth Mode Ambiguity Detection

When both token and password are present in config, hasAmbiguousGatewayAuthModeConfig() returns true. The assertion function then throws a descriptive error.

import {
  hasAmbiguousGatewayAuthModeConfig,
  assertExplicitGatewayAuthModeWhenBothConfigured,
  EXPLICIT_GATEWAY_AUTH_MODE_REQUIRED_ERROR,
} from './auth-mode-policy';

if (hasAmbiguousGatewayAuthModeConfig(cfg)) {
  // Both token and password configured without explicit mode
  // This is dangerous: which one should be used?
}

// Throws EXPLICIT_GATEWAY_AUTH_MODE_REQUIRED_ERROR
// if ambiguous config detected
assertExplicitGatewayAuthModeWhenBothConfigured(cfg);

Config Utilities for Password Management

auth-config-utils.ts provides helpers for setting passwords and resolving secret references from external files.

import {
  withGatewayAuthPassword,
  resolveGatewayPasswordSecretRef,
} from './auth-config-utils';

// Immutably set a password in config
const updatedCfg = withGatewayAuthPassword(cfg, 'my-secure-password');

// Resolve password from external secret file
const resolvedCfg = await resolveGatewayPasswordSecretRef({
  cfg,
  env: process.env,
  hasPasswordCandidate: true,
  hasTokenCandidate: false,
});

Auth Mode Policy State

stateDiagram-v2
    [*] --> ConfigLoaded: Load OpenClawConfig
    ConfigLoaded --> CheckMode: resolveGatewayAuth()
    CheckMode --> TokenOnly: Only token configured
    CheckMode --> PasswordOnly: Only password configured
    CheckMode --> NoneMode: No credentials configured
    CheckMode --> BothConfigured: Both token AND password

    TokenOnly --> Resolved: mode = "token"
    PasswordOnly --> Resolved: mode = "password"
    NoneMode --> Resolved: mode = "none"

    BothConfigured --> ExplicitCheck: hasAmbiguousGatewayAuthModeConfig?
    ExplicitCheck --> Resolved: auth.mode explicitly set
    ExplicitCheck --> Error: No explicit mode
    Error --> [*]: EXPLICIT_GATEWAY_AUTH_MODE_REQUIRED_ERROR

    Resolved --> [*]: ResolvedGatewayAuth

Function Reference

FunctionFileReturnsDescription
shouldRequireGatewayTokenForInstall()auth-install-policy.tsbooleanWhether token is needed at install time
hasAmbiguousGatewayAuthModeConfig()auth-mode-policy.tsbooleanDetects token+password without explicit mode
assertExplicitGatewayAuthModeWhenBothConfigured()auth-mode-policy.tsvoidThrows if ambiguous config detected
withGatewayAuthPassword()auth-config-utils.tsOpenClawConfigImmutably adds password to config
resolveGatewayPasswordSecretRef()auth-config-utils.tsPromise<OpenClawConfig>Resolves password from external secret

Edge Cases

ScenarioBehavior
Only token in configInstall policy: token not required (already exists)
Only password in configInstall policy: token not required
Password in env onlyInstall policy: token not required if env is durable
No credentials anywhereInstall policy: token required (generate one)
Both token + password, no modeMode policy: throws error
Both token + password, mode setMode policy: proceeds with explicit mode
Secret ref file missingThrows GatewaySecretRefUnavailableError

Directory Map

Source files for this topic
src/gateway/
├── auth-install-policy.ts    ← shouldRequireGatewayTokenForInstall
├── auth-mode-policy.ts       ← hasAmbiguousGatewayAuthModeConfig, assertExplicit...
├── auth-config-utils.ts      ← withGatewayAuthPassword, resolveGatewayPasswordSecretRef
└── credentials.ts            ← GatewaySecretRefUnavailableError