OutlabsAuth
Integrations

OutlabsAuth UI

Optional sidecar admin console — point it at any FastAPI host running OutlabsAuth and manage the full surface.

OutlabsAuth UI is an optional sidecar admin console — a static single-page app built with Nuxt 4 and Nuxt UI 4, deployed separately from your API. It is not part of the Python package, and it does not ship a second auth stack. One build serves any FastAPI host that has OutlabsAuth mounted, using the same routers your product already exposes; each deployment names its API in a runtime app-config.json.

We maintain it ourselves and use it day-to-day: it is the fastest way to see and operate what is going on in an OutlabsAuth-backed system — users, roles, entities, keys, sessions, audit, and more — without building that console from scratch.

OutlabsAuth UI was rebuilt on Nuxt in October 2026. The earlier React/Vite console is retired (it remains in the repository history), so VITE_* environment variables and the 5173 dev port no longer apply.
The UI only shows what the backend advertises. Mount the right router factories first.

Why it exists

Sidecar, not a product UI

Point it at any instance that mounts OutlabsAuth — local examples, staging, or production. Your customers still get your screens; this console is for operators and implementers.

Full gamut of features

When the matching routers are mounted, you get the same surface the library exposes: invites, roles, permissions, ABAC, entities, memberships, API keys, sessions, audit search, account self-service, passwordless entry flows, and OAuth link/unlink where enabled.

Visualise the system

Browse the org tree, inspect memberships, search audit events, check active sessions, and watch activity signals on users and entities — useful while integrating and debugging, not only for “admin CRUD.”

Reference for your own UI

The repo is a working example of how to consume /auth/config, permission gates, and the management APIs. Steal patterns; you do not have to ship this SPA to end users.

What you can do in the console

A workspace appears only when the backend mounts its router (listed in mounted_surfaces from GET {authApiPrefix}/auth/config), the matching feature is on, and the signed-in admin holds the permission it needs, so a delegated admin sees what they may do and nothing else.

WorkspaceWhereWhat it is for
DashboardSidebarCapability snapshot and shortcuts into visible workspaces
UsersSidebar · DirectoryInvite / create, status, password reset, roles, memberships, sessions, personal keys, orphaned users, history, permission checks
EntitiesSidebar · DirectoryEnterprise org tree — create, move, members, local roles, activity
RolesSidebar · Access controlRole definitions, their permissions, ABAC conditions when enabled
PermissionsSidebar · Access controlPermission catalog
Service accountsSidebar · IntegrationsSystem integration principals and their API keys
AuditSidebar · MonitoringCross-user event search with before/after/metadata inspection
SettingsSidebar (admins)Server capabilities from /auth/config plus mutable entity types
AccountUser menuProfile and phone verification, password and own sessions, connected accounts, own access
My API keysUser menuThe signed-in user's personal API keys

The sign-in side offers every method the backend advertises and the deployment allows: password, magic link, e-mail and phone codes (WhatsApp, SMS), OAuth providers, self-signup, recovery, and accepting an invitation. A method shows only when both the backend (/auth/config) and the deployment's authUi settings allow it.

Self-signup is on by default (authUi.signup: true in the template). For an invite-only operator console, set "signup": false in authUi. That only hides the console's link and page: POST {authApiPrefix}/auth/register stays mounted with get_auth_router, so block registration in your host as well if it must be closed.

How it connects

sidecar
Your FastAPI app (any host)
└── OutlabsAuth routers under a stable prefix (/v1, /iam, …)
        ↑
        │  apiBaseUrl + authApiPrefix
        │
OutlabsAuth UI (static site, separate deploy)

Configure two values, plus a third when the backend registers frontend profiles:

FieldMeaning
apiBaseUrlOrigin of the FastAPI app (no trailing slash). Must be https in a deployment; plain http is accepted only for localhost
authApiPrefixParent of /auth, starting with / — e.g. /v1 when you mount /v1/auth, / when you mount /auth
frontendProfileKeyThe frontend profile the console signs in as (sent as app). Must name a profile the backend registers; omit it for a backend without profiles. An unknown key makes every sign-in fail with wrong_application

With authApiPrefix: "/v1", the UI calls /v1/auth/config, /v1/auth/login, /v1/users, /v1/roles, and so on. It adapts navigation for SimpleRBAC vs EnterpriseRBAC from that config snapshot (entity hierarchy, context-aware roles, activity tracking, …).

If you mount get_auth_router(..., prefix="/v1/auth"), set authApiPrefix to /v1, not/v1/auth.

The console targets the outlabs-auth.api/v1 API contract that /auth/config reports as api_contract_version (the Settings workspace shows it). Its release gate runs against the outlabs-auth example hosts at the version pinned in the UI repo's README.

Quick start

Clone and install

Requires Bun 1.3.3+ and Node.js 22.18+.

Terminal
git clone https://github.com/outlabsio/OutlabsAuthUI.git
cd OutlabsAuthUI
bun install
cp public/app-config.template.json public/app-config.json

Point at your API

public/app-config.json
{
  "apiBaseUrl": "http://localhost:8004",
  "authApiPrefix": "/v1",
  "frontendProfileKey": "console",
  "appName": "OutlabsAuth UI",
  "appSubtitle": "Shared auth admin console",
  "authBrand": "OutlabsAuth",
  "authLogoUrl": "/brand/outlabs-auth-logo.svg",
  "signInDescription": "Sign in against the configured auth backend to access this console.",
  "authUi": {
    "signup": true,
    "identifier": "email-or-phone",
    "defaultCountry": "AR",
    "channels": ["whatsapp", "sms"],
    "oauthProviders": [],
    "magicLink": true
  }
}
Example hostAPI portSuggested config
examples/simple_rbac8003apiBaseUrl: http://localhost:8003, authApiPrefix: /v1
examples/enterprise_rbac8004apiBaseUrl: http://localhost:8004, authApiPrefix: /v1

frontendProfileKey: "console" matches a profile the EnterpriseRBAC example registers. Remove it for a backend that registers no frontend profiles (the SimpleRBAC example registers none), or set it to the key your host registers for the console. authUi chooses which sign-in methods the console offers; set "signup": false for an invite-only console.

Run the UI

Terminal
bun run dev

The dev server runs on http://localhost:3000; both example hosts already allow that origin (and :3001) in their CORS settings. Sign in with a bootstrap or seeded admin from the host app.

Config precedence: a deployed build reads only an inline window.__OUTLABS_AUTH_UI_CONFIG__ (which wins) and the served /app-config.json; a missing or invalid config stops the console on a configuration error. The dev server also reads NUXT_PUBLIC_* variables, below the file, and falls back to http://localhost:8004 with /v1. Every key, including the authUi sign-in options, is documented in the UI repo's configuration section.

What to mount on the backend

Minimum for login: get_auth_router (and GET /auth/config comes with it).

For a useful admin console, mount the admin UI–friendly sets in Routers & Prefixes — users, roles, permissions, API keys, and (for Enterprise) entities / memberships / audit as needed.

If a workspace is missing in the UI, the usual cause is a missing router (not listed in mounted_surfaces), a feature flag off on the backend, or a signed-in account without the permission the workspace needs — not a broken SPA.

Simple vs Enterprise behaviour

The same SPA serves both presets. Invite and membership forms change with the backend:

  • SimpleRBAC — no entity scope on invites; selected role_ids become direct account role memberships.
  • EnterpriseRBAC — entity hierarchy and memberships appear when advertised; invites can attach roles through an entity membership when entity_id is supplied.

Building your own UI instead

You do not have to deploy OutlabsAuth UI. Many products keep customer-facing auth screens in-house and only use this console internally.

If you do build your own:

  1. Call GET {prefix}/auth/config and drive feature UI from that payload: features says what the preset supports, mounted_surfaces says which routers the host actually included.
  2. Reuse the same permission names the library enforces (user:read, …).
  3. Treat the OutlabsAuth UI repo as a worked example, not a required dependency: app/utils/capabilities.ts gates workspaces on surfaces, features and permissions, app/queries/ holds the API layer (Pinia Colada), and app/schemas/ the Zod form rules.

Deploy notes

  • One build, per-deployment config. bun run generate produces a static site in .output/public with a hash-based Content-Security-Policy. Each deployment keeps its own app-config.json outside the repository; the deploy preflight validates it, stages it, and pins the CSP connect-src to its API. A host that injects window.__OUTLABS_AUTH_UI_CONFIG__ inline must add that script's hash to script-src.
  • Hosting. Serve the console at the root of its own hostname (sub-paths are not supported). The repository deploys to Cloudflare Workers static assets (bun run deploy:cloudflare --config <app-config.json> --env <name>); another host must reproduce the generated _headers and the routing rules in wrangler.toml.
  • Release gate. There is no hosted CI. bun run release:check runs typecheck, lint, unit tests and the full Playwright suite on the static build against seeded EnterpriseRBAC and SimpleRBAC example hosts, and the Cloudflare deploy accepts only a commit with a recent passing record.
  • Backend settings. CORS must allow the console origin exactly, with credentials. With frontendProfileKey, the profile's public origin must be the console, so emailed reset, invitation, magic-link and code links open it. OAuth works only when the console and the API share a site (one registrable domain, e.g. console.example.com and auth.example.com), with the success, error and associate redirects at /auth/oauth/callback, /auth/login and /app/account.
  • No host secrets. OAuth, SMS and email credentials stay on the backend; the console only uses the public auth API.

The full per-deployment checklist is in the UI repo's PRODUCTION.md.

Known limitations

What is built, partial or missing for each backend capability, with the tests that prove it, is tracked in the UI repo's CAPABILITIES.md; the outlabs-auth changes it waits on are listed in PRODUCTION.md.