Authorization Guide
v3.8.1Last updated: 2026-05-13
Was this page helpful?
Loading OmniRoute...
Source of truth: , , ,
Last updated: 2026-05-13 β v3.8.0
deterministic and fail-closed β anything that cannot be classified ends up as and demands a session or management-grade token. This page explains the model for engineers maintaining routes or designing new endpoints.
diagrams/authz-pipeline.mmd
scope.
/ in and re-exported through . The validator also accepts the / env vars as persistent passthrough keys (issue #1350).
in . The pipeline auto-refreshes the JWT when it has fewer than 7 days left in its 30-day lifetime.
either mode: cookie OR when the API key has the (or ) scope. This is what enables the "configurable via API calls" workflow added in v3.8.
defines three classes; any route that cannot be classified deterministically falls back to .
, plus aliases , |
) | |
| scope |
) are stripped from incoming requests before classification β clients cannot pre-populate to impersonate a subject.
:
() β always returns .
() β extracts Bearer, validates via . Falls through to anonymous if . Allows dashboard-session GET on (used by the dashboard model catalog).
() β accepts dashboard session, internal model-sync requests (matched against ), or skips entirely if returns false. Returns 403 () when a Bearer token is present but invalid, 401 otherwise.
with . Downstream handlers can read it via in instead of re-running auth logic.
is the explicit allowlist:
PUBLIC_API_ROUTE_PREFIXES = [ "/api/auth/login", "/api/auth/logout", "/api/auth/status", "/api/init", "/api/v1/", // treated as CLIENT_API in classify, not as "no-auth public" "/api/cloud/", "/api/sync/bundle", "/api/oauth/", ]; PUBLIC_READONLY_API_ROUTE_PREFIXES = ["/api/monitoring/health", "/api/settings/require-login"]; PUBLIC_READONLY_METHODS = new Set(["GET", "HEAD", "OPTIONS"]);
only for safe methods. Note: excludes from the PUBLIC fall-through β those are always so the Bearer-key policy still applies.
are classified automatically. The middleware enforces the Bearer check; route handlers don't need to redo it but can read the subject if useful.
// src/app/api/v1/your-route/route.ts
import { NextRequest, NextResponse } from "next/server";
import { assertAuth } from "@/server/authz/assertAuth";
export async function POST(req: NextRequest) {
const subject = assertAuth(req, "CLIENT_API");
// subject.kind === "client_api_key" | "anonymous" | "dashboard_session"
// ... handler logic
}
from :
import { requireManagementAuth } from "@/lib/api/requireManagementAuth";
export async function POST(request: Request) {
const rejection = await requireManagementAuth(request);
if (rejection) return rejection;
// ... handler logic
}
returns on success or a JSON error :
/ scope returns true for or .
(or for GET-only). Update unit tests at and .
array (stored as JSON in , see ).
β grants the key access to management API endpoints when sent as Bearer.
. Full list ():
): , , , . Use and for enforcement inside MCP handlers.
in decides whether any auth is enforced for a request:
env var β bootstrap mode allows the onboarding wizard and loopback requests, but exposed network requests still need credentials. and endpoints now require management auth (commit ). Clients previously sending a normal API key without the scope receive . Migration: either issue the key the scope in the API Manager dashboard, or use a logged-in dashboard session.
, , , , .
- .
- .
inside handlers β it throws with code if the middleware was bypassed (helpful for catching configuration regressions in tests).