# How OmniRoute Remote Mode Works with Scoped Access Tokens

> Learn how OmniRoute remote mode works with scoped access tokens for secure, least-privilege remote control of your OmniRoute instances using SHA-256 credentials.

- Repository: [Diego Rodrigues de Sa e Souza/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- Tags: how-to-guide
- Published: 2026-07-13

---

**OmniRoute's remote mode lets you control a distant instance via the local CLI using hierarchical scoped access tokens (oma_…) that enforce least-privilege access through SHA-256 hashed credentials stored in SQLite.**

OmniRoute's remote mode bridges the gap between local convenience and server-side deployment, allowing you to run the `omniroute` CLI on your laptop while the actual instance operates on a VPS, home server, or Tailscale-connected device. This architecture relies on **scoped access tokens** to authenticate management requests, ensuring that compromised credentials limit potential damage through strict permission boundaries. The implementation spans from the bootstrap handshake in [`src/app/api/cli/connect/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/cli/connect/route.ts) to the scope validation logic in [`src/app/api/v1/_helpers/apiKeyScope.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/v1/_helpers/apiKeyScope.ts).

## What is OmniRoute Remote Mode?

Remote mode separates the CLI client from the server process. Instead of running OmniRoute locally, you target a remote instance via HTTP-based management APIs. The CLI stores the server URL and authentication context in `~/.omniroute/config.json`, automatically attaching `Authorization: Bearer oma_…` headers to every request.

This design isolates administrative actions—such as adding providers or revoking tokens—from inference operations. While management routes require scoped tokens, inference endpoints like `/v1/chat/completions` continue using model-specific API keys (`sk-…`), maintaining a clear security boundary between administration and usage.

## The Token Lifecycle and Bootstrap Process

### Initial Connection and Minting

The remote mode workflow begins with a bootstrap exchange. When you run `omniroute connect <host>`, the CLI sends your management password to `POST /api/cli/connect` on the remote server.

In [`src/app/api/cli/connect/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/cli/connect/route.ts), the server:

1. **Verifies** the management password against stored credentials
2. Applies **brute-force protection** via [`src/server/auth/loginGuard.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/server/auth/loginGuard.ts), returning `429 Too Many Requests` for repeated failures
3. **Mints** a new scoped token with format `oma_…`
4. Stores a **SHA-256 hash** of the token in the SQLite `access_tokens` table (located in [`src/lib/db/accessTokens.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/accessTokens.ts))
5. Returns the **plaintext token exactly once** to the client

The CLI then writes this token to `~/.omniroute/config.json` with `chmod 600` permissions, establishing the remote context.

### Subsequent Request Flow

Once bootstrapped, all CLI commands automatically target the remote server:

```bash
omniroute models list

# CLI adds: Authorization: Bearer oma_live_abcdef...

# Request routed to https://your-vps:20128/api/cli/models

```

The server validates the token hash against the database on every request, checking both authenticity and scope authorization.

## Scope Hierarchy and Enforcement

OmniRoute implements three hierarchical permission levels. Each token carries one scope, and the server enforces these boundaries in [`src/app/api/v1/_helpers/apiKeyScope.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/v1/_helpers/apiKeyScope.ts).

### Read Scope

Tokens with `read` scope permit inspection operations only:

- `omniroute models list`
- `omniroute logs`
- `omniroute usage`
- `GET /api/cli/whoami`

The system maps HTTP `GET` requests to the `read` scope automatically.

### Write Scope

`write` tokens inherit `read` capabilities plus configuration privileges:

- `omniroute setup-codex`
- `omniroute config set`
- Creating provider combinations
- Non-GET management operations

All mutating HTTP methods (`POST`, `PUT`, `PATCH`, `DELETE`) default to requiring `write` scope unless the endpoint appears on the admin allow-list.

### Admin Scope

`admin` tokens grant full control, including:

- Token CRUD operations (`GET /api/cli/tokens`, `POST /api/cli/tokens`, `DELETE /api/cli/tokens/:id`)
- Provider management (`/api/providers/*` mutations)
- OAuth connections (`/api/oauth`)
- Policy editing

Additionally, **loopback-only routes**—such as those spawning subprocesses—force `admin` scope plus loopback IP verification. Remote tokens can never access these endpoints regardless of their scope.

## Practical CLI Workflow

### Connecting to a Remote Instance

```bash

# Bootstrap with management password (receives admin token)

omniroute connect 192.168.0.15

# Verify active context

omniroute contexts current

```

### Creating Limited Tokens

Create narrowly scoped tokens for specific use cases, such as CI pipelines:

```bash

# Create read-only token for automation

omniroute tokens create --name ci-runner --scope read

# Returns: oma_read_xyz123 (save this immediately)

```

### Managing Multiple Contexts

Switch between local and remote instances:

```bash

# Add staging environment manually

omniroute contexts add staging --url https://staging.example.com:20128 \
  --access-token oma_live_abcdef --scope write \
  --description "Staging box"

# List configured contexts

omniroute contexts list

# Switch back to local

omniroute contexts use default

```

### Revocation

When retiring a token, remove it server-side (requires admin scope) and clean up locally:

```bash

# Revoke on server

omniroute tokens revoke <token-id>

# Remove local reference

omniroute contexts remove staging --yes

```

## Security Mechanisms

### One-Time Secret Display

The plaintext token appears only during creation. The server persists only the SHA-256 hash in [`src/lib/db/accessTokens.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/db/accessTokens.ts), ensuring that database breaches do not expose usable credentials.

### Brute-Force Protection

The connection endpoint shares the same protection as the dashboard login. [`src/server/auth/loginGuard.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/server/auth/loginGuard.ts) tracks per-IP failure counts, enforcing exponential backoff and returning `429` responses before permanent lockout.

### Transport and Storage

- **File permissions**: `~/.omniroute/config.json` sets `chmod 600` to prevent other users from reading tokens
- **HTTPS/Tailscale**: While plain HTTP works for LAN convenience, production deployments should encrypt transport
- **Audit trail**: Token usage logs against the remote instance provide visibility into administrative actions

### Scope Isolation

The hierarchical design ensures that a compromised `read` token cannot modify configurations, while a `write` token cannot mint new credentials or revoke existing ones. This minimizes blast radius according to the principle of least privilege.

## Summary

- **OmniRoute remote mode** enables CLI control of distant instances via HTTP APIs, storing credentials in `~/.omniroute/config.json`
- **Scoped access tokens** (`oma_…`) enforce three hierarchical levels: `read` (inspection), `write` (configuration), and `admin` (management)
- **Bootstrap flow** in [`src/app/api/cli/connect/route.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/cli/connect/route.ts) mints tokens with brute-force protection and stores only SHA-256 hashes in SQLite
- **Scope enforcement** occurs in [`src/app/api/v1/_helpers/apiKeyScope.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/app/api/v1/_helpers/apiKeyScope.ts), mapping HTTP methods to required permissions and maintaining an admin allow-list for sensitive routes
- **Security features** include one-time plaintext display, `chmod 600` context files, per-IP rate limiting, and loopback-only route restrictions

## Frequently Asked Questions

### How do I rotate a compromised scoped access token?

If you suspect token exposure, immediately revoke it using an admin token: `omniroute tokens revoke <id>`. The server invalidates the hash in the database, causing subsequent requests to return `403 Forbidden`. Then generate a new token with `omniroute tokens create --name <name> --scope <read|write|admin>` and update your local context or CI environment, as the plaintext is shown only once during creation.

### Can I use remote mode without HTTPS?

The protocol supports plain HTTP for convenience on trusted LANs or Tailscale networks, but this exposes tokens to network sniffing. For production deployments across the public internet, always terminate TLS at the OmniRoute server or proxy. The token itself grants administrative access to your instance, so transport encryption is critical for security.

### What happens if I lose my admin token?

If you lose the only admin token stored in your local context, you must physically access the remote server or use an existing admin session to mint a new one. The server never reveals token plaintext after creation, and the hash stored in SQLite cannot be reversed. As a recovery method, you can re-run `omniroute connect <host>` with the management password to generate a fresh admin token.

### Why are inference routes excluded from scope checks?

Management tokens (`oma_…`) and model API keys (`sk-…`) serve fundamentally different purposes. Scope enforcement applies only to administrative routes under `/api/cli/*` to protect configuration changes. Inference endpoints (`/v1/chat/completions`) use separate provider-specific authentication, allowing you to distribute usage keys without granting administrative access to the OmniRoute instance.