# How to Configure Remote Mode with Scoped Access Tokens in OmniRoute

> Learn to configure OmniRoute remote mode using scoped access tokens. Generate tokens via CLI, set environment variables, and connect to your server for secure remote access.

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

---

**To configure remote mode with scoped access tokens in OmniRoute, generate a token with the CLI using `omniroute token create --scope <read|write|admin>`, set it as the `OMNIRoute_TOKEN` environment variable, and point the CLI to your remote server with `--server https://your-server.com`.**

OmniRoute supports a remote mode that shifts management operations from your local machine to a dedicated server instance. When you configure remote mode with scoped access tokens in OmniRoute, you authenticate using bearer tokens that carry specific permissions rather than inference API keys. This guide walks through the complete setup using the actual implementation from the `diegosouzapw/OmniRoute` repository.

## Understanding the Token Scope Model

OmniRoute implements a three-tier **scope hierarchy** that determines which management actions a token can perform. The system is defined in [`src/lib/accessTokens/scopes.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/accessTokens/scopes.ts) and uses a simple ranking system where higher scopes inherit lower permissions.

### The Three-Level Hierarchy

The `ACCESS_SCOPES` constant defines the available levels:

```typescript
// src/lib/accessTokens/scopes.ts
export const ACCESS_SCOPES = ["read", "write", "admin"] as const;
export type AccessScope = (typeof ACCESS_SCOPES)[number];

```

- **read** – Allows listing and inspecting resources (e.g., viewing providers or combos)
- **write** – Includes read permissions plus the ability to create or modify configuration
- **admin** – Includes write permissions plus sensitive actions like creating or revoking tokens, adding providers, or installing services

The hierarchy follows `admin ⊃ write ⊃ read`, meaning an admin token can perform any action a write or read token can.

### How Scope Validation Works

The server uses the `scopeSatisfies(have, need)` helper function to check if a token's scope meets the endpoint's requirements. This function verifies that the token's rank is greater than or equal to the required rank. Remote mode tokens must always be sent in the `Authorization` header; tokens passed via URL are explicitly ignored in [`src/lib/api/requireManagementAuth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/api/requireManagementAuth.ts).

## Creating Scoped Access Tokens

Use the CLI to generate tokens with specific permission levels. These tokens always start with the prefix `oma_` and are managed through the `access_tokens` database table.

### CLI Token Creation Commands

Generate tokens for different operational needs:

```bash

# Read-only token for dashboard inspection

omniroute token create --scope read --name "readonly-dashboard"

# Write token for configuration management

omniroute token create --scope write --name "config-writer"

# Admin token for full management access

omniroute token create --scope admin --name "admin-access"

```

Each command performs three operations internally:

1. Generates a random UUID and prefixes it with `oma_`
2. Stores the token in the `access_tokens` table (defined in `db/migrations/…_access_tokens.sql`) with the specified scope and metadata
3. Displays the full token value exactly once

**Important:** The secret is shown only during creation. Store it immediately in a secret manager or environment variable—never commit tokens to source control.

## Enabling Remote Mode in the CLI

Remote mode activates automatically when the CLI targets a non-local server URL. You only need to provide the scoped token and server address.

### Environment Variable Configuration

Set the `OMNIRoute_TOKEN` variable to inject the authentication header automatically:

```bash
OMNIRoute_TOKEN=oma_3f4a7c8d9e10ab11cd22ef33ab44cd55 \
  omniroute --server https://omniroute.example.com combo list

```

The CLI reads this variable and adds `Authorization: Bearer <token>` to every HTTP request.

### Explicit Flag Method

Alternatively, pass the token directly via command line:

```bash
omniroute --server https://omniroute.example.com \
          --token oma_3f4a7c8d9e10ab11cd22ef33ab44cd55 \
          combo edit myCombo --add-model gpt-4o

```

Both methods require the token to have sufficient scope for the requested operation.

## Server-Side Token Validation

When a request hits a management route (e.g., `/api/cli/*`, `/api/providers/*`, `/api/combo/*`), the server executes a strict validation pipeline defined across several authorization modules.

### The Validation Flow

The sequence in [`src/server/authz/accessTokenAuth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/server/authz/accessTokenAuth.ts) and [`src/server/authz/policies/management.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/server/authz/policies/management.ts) follows these steps:

1. **`evaluateAccessTokenAuth(request)`** extracts the bearer token and verifies the `oma_` prefix
2. **`verifyAccessToken`** performs a database lookup in the `access_tokens` table
3. **`inferRequiredScope`** determines the necessary permission level based on the HTTP method and pathname
4. **`scopeSatisfies(token.scope, requiredScope)`** validates that the token meets the requirement
5. **`requireManagementAuth`** (in [`src/lib/api/requireManagementAuth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/api/requireManagementAuth.ts)) returns a verdict of `ok`, `invalid`, `insufficient`, `error`, or `absent`, which translates to HTTP status codes `200`, `401`, `403`, `503`, or similar

If the token lacks sufficient scope, the server returns **403 Forbidden** with a message indicating the required scope.

## Practical Implementation Examples

### Querying Resources with Read Scope

Use a read-only token to inspect configuration without modification rights:

```bash
OMNIRoute_TOKEN=oma_5a6b7c8d9e0f1a2b3c4d5e6f7g8h9i0j \
omniroute --server https://omniroute.example.com provider list

```

Or using raw HTTP:

```javascript
const token = process.env.OMNIRoute_TOKEN;
const resp = await fetch('https://omniroute.example.com/api/combo/list', {
  method: 'GET',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json',
  },
});

const data = await resp.json();
console.log('Available combos:', data);

```

### Modifying Configuration with Write Scope

Update combos or providers using a write-scoped token:

```bash
omniroute --server https://omniroute.example.com \
          --token oma_9f8e7d6c5b4a3a2b1c0d9e8f7g6h5i4j \
          combo edit myCombo --add-model gpt-4o

```

A `read`-only token would receive **403 Forbidden** with the message: `Access token scope 'read' is insufficient; 'write' required.`

### Administrative Operations

Creating new tokens requires `admin` scope:

```bash
omniroute --server https://omniroute.example.com \
          --token oma_admin_token \
          token create --scope write --name "ci-writer"

```

This operation manipulates credential material in the `access_tokens` table, which is protected to admin-only access as enforced by the policy in [`src/server/authz/policies/management.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/server/authz/policies/management.ts).

## Summary

- **Scoped tokens** use the prefix `oma_` and come in three levels: `read`, `write`, and `admin`, defined in [`src/lib/accessTokens/scopes.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/accessTokens/scopes.ts)
- **Token creation** happens via `omniroute token create --scope <level>`, storing secrets in the database via migrations in `db/migrations/…_access_tokens.sql`
- **Remote mode** requires setting `OMNIRoute_TOKEN` or using `--token`, targeting a remote server with `--server`, and relies on header-based authentication handled by [`src/lib/api/requireManagementAuth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/api/requireManagementAuth.ts)
- **Validation** occurs in [`src/server/authz/accessTokenAuth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/server/authz/accessTokenAuth.ts) and [`src/server/authz/policies/management.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/server/authz/policies/management.ts), using `scopeSatisfies` to enforce the hierarchy
- **Security** mandates storing tokens in environment variables or secret managers, never in source control, and using the minimum necessary scope for each operation

## Frequently Asked Questions

### What is the difference between an OmniRoute scoped token and an inference API key?

Scoped access tokens (prefixed with `oma_`) are management credentials for remote CLI operations like configuring providers and editing combos, while inference API keys are used for actual model inference requests. The scoped tokens operate against management routes (`/api/cli/*`, `/api/combo/*`) and carry permissions (`read`, `write`, `admin`), whereas inference keys authenticate prediction requests and do not have the hierarchical scope system defined in [`src/lib/accessTokens/scopes.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/accessTokens/scopes.ts).

### How do I rotate or revoke a compromised scoped token?

You must use an `admin`-scoped token to create or revoke credentials. Run `omniroute token revoke <token-id>` or delete the entry directly from the `access_tokens` table in the database. Since tokens are evaluated against the database on every request in [`src/server/authz/accessTokenAuth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/server/authz/accessTokenAuth.ts), removal takes effect immediately without requiring server restarts.

### Why does my request return 403 when I have a valid token?

A 403 error indicates your token exists but lacks sufficient scope for the operation. The server evaluates requirements using `scopeSatisfies` in [`src/lib/accessTokens/scopes.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/lib/accessTokens/scopes.ts), where `read` cannot perform `write` operations. Check the error message—it explicitly states the required scope (e.g., `'write' required`) and verify you are using the correct token level for the endpoint's method (POST/PUT typically require `write` or `admin`).

### Can I use scoped tokens in the URL query parameters instead of headers?

No. The `evaluateAccessTokenAuth` function in [`src/server/authz/accessTokenAuth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/src/server/authz/accessTokenAuth.ts) only checks the `Authorization: Bearer` header. The [`requireManagementAuth.ts`](https://github.com/diegosouzapw/OmniRoute/blob/main/requireManagementAuth.ts) file explicitly ignores tokens passed in URLs for security reasons. Always set the token via the `OMNIRoute_TOKEN` environment variable or the `--token` CLI flag, which properly injects it into the request header.