NNO Docs
Guides

Authentication

Set up authentication for your NNO platform using Better Auth with per-platform auth Workers.

Set Up Authentication

Every NNO platform gets a dedicated auth Worker backed by its own D1 database. Users, sessions, and tenant memberships are fully isolated between platforms — no shared tables, no cross-platform tokens.

How it works

NNO uses Better Auth as the authentication framework. When you provision a platform, the Provisioning service automatically:

  1. Creates an auth Worker (auth.svc.default.<platformId>.nno.app)
  2. Provisions a D1 database (<platformId>-default-auth-db)
  3. Runs the Better Auth migrations to create user, session, organization, and permission tables

You do not configure this manually — it is part of the platform bootstrap flow.

Connect your console to the auth Worker

Set VITE_AUTH_URL in your console environment to your platform's auth Worker URL:

# apps/console/.env
VITE_AUTH_URL=https://auth.svc.default.<platformId>.nno.app
VITE_PLATFORM_ID=<platformId>

Replace <platformId> with your 10-character platform ID (for example, k3m9p2xw7q). The console shell reads this URL to perform session checks and token exchanges.

For local development, the Vite dev server proxies auth requests to avoid cross-origin cookie issues:

# apps/console/.env (local)
VITE_AUTH_API_URL=/api/auth   # proxied to http://localhost:8787

See Managing Environments for the full environment file structure.

Session management and cookies

After sign-in, Better Auth sets a session cookie scoped to .<platformId>.nno.app. All apps on your platform share this cookie domain, so a user authenticated at console.app.default.<platformId>.nno.app is also authenticated at any other app on *.<platformId>.nno.app.

Locally, the cookie is scoped to localhost and works across all localhost ports without extra configuration.

Role model

NNO uses a two-tier role system on top of Better Auth:

ScopeRolesDescription
Platformplatform-admin, userSet on the user record via the Admin plugin
Tenantowner, admin, memberSet on the org membership via the Organization plugin

A user can hold different roles in different tenants. Platform admins can manage all tenants, view billing, and activate features. Tenant owners can invite and remove members within their tenant.

Check the active session in your feature components via the SDK:

import { useNnoSession } from "@neutrino-io/sdk";

function MyComponent() {
  const { user } = useNnoSession();
  const isAdmin = user.role === "platform-admin";
}

Social auth (optional)

Better Auth supports OAuth providers (Google, GitHub, etc.) via the Social Login plugin. To enable a provider, add its credentials to your auth Worker's secrets:

wrangler secret put GOOGLE_CLIENT_ID
wrangler secret put GOOGLE_CLIENT_SECRET

Then configure the provider in your auth Worker's createAuthApp() call. See the Better Auth social providers docs for the full list of supported providers.

Two-factor authentication

The Better Auth Two-Factor plugin is included in the auth Worker template. Users can enroll TOTP authenticators from their profile settings page. The NNO console shell renders the 2FA enrollment flow automatically via @neutrino-io/ui-auth — no additional setup required.

Verify the setup

After provisioning, confirm the auth Worker is responding:

curl https://auth.svc.default.<platformId>.nno.app/api/auth/session
# {"session": null}  — expected when unauthenticated

If you receive a connection error, check that the platform bootstrap job completed successfully in the NNO Portal under Platform > Provisioning.

Next steps

On this page