How to Implement Password Protection Using the ACCESS_KEYS Environment Variable in MiniSearch

MiniSearch enables instant password protection when you define the ACCESS_KEYS environment variable, activating Argon2-based validation that secures all API endpoints while the UI prompts users for authentication and persists valid sessions in localStorage.

The felladrin/minisearch repository ships with a built-in access control system that requires zero code changes to deploy. By setting a single environment variable, you activate server-side key validation using Argon2 hashing and client-side session management. This implementation protects search, inference, and custom endpoints behind a password-style access key system.

How the ACCESS_KEYS Protection System Works

MiniSearch uses a multi-layered approach to access control that spans both server and client codebases. When ACCESS_KEYS is populated, the system automatically activates validation hooks and UI prompts.

Server-Side Validation Architecture

The server intercepts all requests through the validateAccessKeyServerHook middleware defined in server/validateAccessKeyServerHook.ts. This hook listens for POST requests to /api/validate-access-key and compares submitted hashes against the environment variable using Argon2 verification.

The validation logic loops through each key in the comma-separated list:

const accessKeys = process.env.ACCESS_KEYS?.split(",") ?? [];

for (const key of accessKeys) {
  if (await argon2Verify({ password: key, hash: accessKeyHash })) {
    isValid = true;
    break;
  }
}

If any key matches the submitted Argon2 hash, the server returns { valid: true }, granting access to the requesting client.

Client-Side Authentication Flow

The client application checks for protection status through the VITE_ACCESS_KEYS_ENABLED flag exposed in vite.config.ts. When enabled, the App component in client/components/App/App.tsx forces a modal prompt before rendering the main interface.

User input flows through client/modules/accessKey.ts, which handles three critical operations:

  • Local Hashing: Plain-text keys are hashed locally using hashAccessKey() before transmission
  • Server Validation: The hash is sent to /api/validate-access-key for verification
  • Session Persistence: Valid hashes are stored in localStorage under accessKeyHash with timestamps to prevent re-prompting during the timeout period defined by VITE_ACCESS_KEY_TIMEOUT_HOURS

Configuring Password Protection

Activating access control requires only environment configuration and a service restart. No source code modifications are necessary.

1. Define Access Keys in the Environment

Create or edit the .env file at the project root using the format shown in .env.example. Set ACCESS_KEYS to a comma-separated list of plain-text passwords:


# .env

ACCESS_KEYS="alpha-2024,beta-2024,gamma-2024"

Each comma-separated value represents a valid access credential. The server stores these as plain text in memory but validates them against Argon2 hashes submitted by clients.

2. Enable the Vite Build Flag

The build system automatically detects the environment variable and exposes it to the client bundle. In vite.config.ts, the define block sets VITE_ACCESS_KEYS_ENABLED:

define: {
  VITE_ACCESS_KEYS_ENABLED: JSON.stringify(
    Boolean(process.env.ACCESS_KEYS)
  ),
},

This boolean flag determines whether the UI renders the access key prompt or bypasses authentication entirely.

3. Rebuild and Deploy

For Docker deployments, rebuild the image to capture the new environment variables:

docker compose up --build -d

The server hook activates automatically on startup when process.env.ACCESS_KEYS is detected.

4. Client Authentication Implementation

When integrating the access key flow into custom client code, import the validation module from client/modules/accessKey.ts:

import { validateAccessKey } from "./accessKey";

async function onKeySubmit(input: string) {
  const ok = await validateAccessKey(input);
  if (ok) {
    // Proceed to protected resources
    console.log("Access granted");
  } else {
    // Display authentication error
    console.error("Invalid access key");
  }
}

The validateAccessKey function handles local hashing, server verification, and automatic localStorage persistence upon success.

Key Source Files Reference

Understanding the codebase structure helps with customization and debugging:

Summary

  • Set the ACCESS_KEYS environment variable to a comma-separated list of authorized passwords to activate protection
  • The server automatically validates keys using Argon2 through server/validateAccessKeyServerHook.ts
  • The client UI switches to protected mode via VITE_ACCESS_KEYS_ENABLED defined in vite.config.ts
  • Valid sessions persist in localStorage with configurable timeouts via VITE_ACCESS_KEY_TIMEOUT_HOURS
  • All API endpoints, including search and inference, require valid access keys when protection is enabled

Frequently Asked Questions

What hashing algorithm does MiniSearch use for access key validation?

MiniSearch uses Argon2 for all access key operations. When a user enters a key, the client hashes it locally using hashAccessKey() from client/modules/accessKey.ts before transmission. The server then uses argon2Verify() in server/validateAccessKeyServerHook.ts to compare the submitted hash against the plain-text keys defined in ACCESS_KEYS without transmitting passwords over the network.

Can I use ACCESS_KEYS with Docker Compose?

Yes. Pass the environment variable through your docker-compose.yml file or an .env file in the project root. The container must be rebuilt or restarted to pick up changes to ACCESS_KEYS. You can reference the variable in your compose file using ${ACCESS_KEYS:-} to provide a default empty value if the variable is unset.

How long do access key sessions last?

Session duration is controlled by the VITE_ACCESS_KEY_TIMEOUT_HOURS environment variable. After successful validation, the client stores the hash and timestamp in localStorage. The verifyStoredAccessKey() function in client/modules/accessKey.ts checks this timeout on page load and prompts for re-authentication when the period expires.

Does enabling ACCESS_KEYS affect API endpoints only, or the UI as well?

Both. When ACCESS_KEYS is defined, vite.config.ts sets VITE_ACCESS_KEYS_ENABLED to true, causing client/components/App/App.tsx to render the access key modal before the main interface. Simultaneously, the server hook validates keys for all requests. The system protects both the user interface and underlying API resources.

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 →