Skip to content

Authentication Configuration

Garret Premo edited this page Mar 31, 2026 · 1 revision

Authentication & Configuration

This page documents the config file format, environment variable naming, credential security model, and session caching behavior. For information on authentication strategies (BasicAuth, BearerToken, ApiKey, custom), see Authentication Strategies.


Config File Location

Mode Path
Global (default) ~/.<cliName>/config.json
Project mode .apijack/config.json (relative to the .apijack.json project root)

Project mode is activated automatically when apijack finds a .apijack.json file by walking up from the current working directory. See Project Mode for details.


Config File Structure

{
  "active": "staging",
  "environments": {
    "local": {
      "url": "http://localhost:8080",
      "user": "admin",
      "password": "secret"
    },
    "staging": {
      "url": "https://staging.example.com",
      "user": "deploy-bot",
      "password": "..."
    }
  }
}

The file is written with two-space indentation. The active field names whichever environment key is currently selected. Each environment object must contain url, user, and password; it may also contain arbitrary extra fields written by auth strategies or updateEnvironmentField.


Environment Fields

Field Type Required Description
url string yes Base URL of the API (e.g. http://localhost:8080)
user string yes Username or email for authentication
password string yes Password, token, or API key
(extra fields) unknown no Any additional fields stored by auth strategies or updateEnvironmentField

The EnvironmentConfig interface uses an index signature ([key: string]: unknown) so strategies can persist arbitrary session metadata alongside the standard three fields.


Environment Variable Naming

Environment variables take priority over the config file. When all three variables are set, apijack uses them directly and does not read config.json.

The prefix is derived from the CLI name by calling .toUpperCase() on it. Hyphens and other characters are preserved as-is after uppercasing.

Variable Value
<PREFIX>_URL Base URL of the API
<PREFIX>_USER Username or email
<PREFIX>_PASS Password

Examples

createCli name Env var prefix Example variables
mycli MYCLI MYCLI_URL, MYCLI_USER, MYCLI_PASS
my-api MY-API MY-API_URL, MY-API_USER, MY-API_PASS
petstore PETSTORE PETSTORE_URL, PETSTORE_USER, PETSTORE_PASS

Note: because hyphens are preserved verbatim, a CLI named my-api produces MY-API_URL. If your shell does not support hyphens in variable names, rename the CLI to use underscores or a single word.

Priority

Environment variables  →  config file active environment  →  null (unauthenticated)

If any of the three env vars is missing, apijack falls back to the config file entirely. There is no partial merge between env vars and config.


Credential Security Model

apijack classifies the target URL before storing credentials in plaintext. If the URL resolves to a "safe" (non-production) host, credentials are stored in config.json. If the URL is classified as production, storage is blocked unless explicitly overridden.

Safe Hosts

Classification Examples
localhost (exact hostname match) http://localhost:8080
127.0.0.1 (exact IP match) http://127.0.0.1:3000
::1 (IPv6 loopback, exact match) http://[::1]:8080
CIDR allowlist match (IPv4 only) see CIDR Allowlists below

Any URL whose hostname does not match one of the above is classified as production, and setup will refuse to store credentials.

Production URL Behavior

When setup or config add encounters a production URL, it prints an error with three options:

Production API detected (api.example.com).
Credentials cannot be stored in plaintext for non-development environments.

Options:
  1. Use environment variables: MYCLI_URL, MYCLI_USER, MYCLI_PASS
  2. Add this network to your allowed CIDRs if it's internal
  3. Pass --allow-insecure-storage to override (not recommended)

--allow-insecure-storage Flag

Passing --allow-insecure-storage to setup or login bypasses the URL classification check and stores credentials regardless of the target URL.

mycli setup --allow-insecure-storage
mycli login --allow-insecure-storage

This is intended for internal staging environments or development scenarios where the URL looks like a production domain but isn't. It is not recommended for actual production credentials.


CIDR Allowlists

The allowedCidrs option extends the safe-host list to include private IP ranges. Only IPv4 addresses are matched against CIDRs; hostname-based URLs (e.g. staging.internal) are not matched.

Configuring in createCli

import { createCli, BasicAuthStrategy } from "@apijack/core";

const cli = createCli({
  name: "mycli",
  description: "My API CLI",
  version: "1.0.0",
  specPath: "/v3/api-docs",
  auth: new BasicAuthStrategy(),
  allowedCidrs: ["10.0.0.0/8", "192.168.0.0/16"],
});

await cli.run();

Configuring in .apijack.json (project mode)

{
  "allowedCidrs": ["10.0.0.0/8", "192.168.1.0/24"]
}

CIDR Format

Standard IPv4 CIDR notation: <network>/<prefix-length>. Prefix length must be 0–32.

CIDR Covers
10.0.0.0/8 All 10.x.x.x addresses
192.168.0.0/16 All 192.168.x.x addresses
192.168.1.0/24 192.168.1.0 through 192.168.1.255
172.16.0.0/12 172.16.x.x through 172.31.x.x

When a URL's IP address matches any entry in the CIDR list, the URL is classified as safe and credentials are stored normally.


Session Caching

Session File Location

Mode Path
Global ~/.<cliName>/session.json
Project mode .apijack/session.json

The session file is written by SessionManager after every successful authentication or refresh.

AuthSession Format

{
  "headers": {
    "Authorization": "Bearer eyJ..."
  },
  "expiresAt": 1740000000000,
  "data": {
    "sessionToken": "abc123"
  }
}
Field Type Description
headers Record<string, string> HTTP headers injected into every API request
expiresAt number (optional) Unix millisecond timestamp; session is considered expired when Date.now() > expiresAt
data Record<string, unknown> (optional) Arbitrary extra state stored by the auth strategy (e.g. refresh tokens, session IDs)

Session Lifecycle

On each CLI run, SessionManager.resolve() executes the following logic:

  1. Load session.json from disk.
  2. If no cached session exists, call strategy.authenticate(config) and save the result.
  3. If a cached session exists and expiresAt is set and has passed:
    • If strategy.refresh is defined, call it and save the refreshed session.
    • If strategy.refresh is not defined, fall through to strategy.authenticate(config).
  4. If a cached session exists and is not expired (or has no expiresAt), call strategy.restore(cached, config).
    • If restore returns a session, save and use it.
    • If restore returns null, fall through to strategy.authenticate(config).

Invalidating the Session

The session can be invalidated (deleted) programmatically by calling SessionManager.invalidate(). This deletes session.json. The next CLI run will call authenticate from scratch.

Clone this wiki locally