Browse documentation
View Markdown

Identity and tenant setup

Nines separates identity from authorization.

  • Signing in identifies a person; a tenant membership, team role or current verified SSO claim grants access to a workspace.
  • Application tenant IDs are separate from projects, services and Kubernetes namespaces.

API-key tenants

Start with a server-owned YAML file. Credentials are environment references, never literal keys in the file:

yaml
tenants:
  - id: commerce
    name: Commerce
    access:
      - tokenEnv: COMMERCE_OWNER_TOKEN
        role: owner
      - tokenEnv: COMMERCE_VIEWER_TOKEN
        role: viewer
    source:
      kind: manual
  - id: analytics
    name: Analytics
    access:
      - tokenEnv: ANALYTICS_OWNER_TOKEN
        role: owner
    source:
      kind: manual
  • Set each referenced environment variable to an independently generated random value of at least 24 characters and set TENANTS_FILE to the file path.
    • Nines uses independent tenant stores and source maps; PostgreSQL tenant schemas are selected by trusted startup configuration.
    • A token grants access only to the tenants that explicitly name it.
    • Sharing a credential across tenants intentionally expands that credential's access.
  • owner administers a tenant, editor edits resources, viewer reads, and agent works within the bounded proposal/tool surface.
    • Use service-account keys or narrow tenant keys for automation.
    • Projects and resource labels do not add another access-control boundary.
  • Native processes inherit the environment.
    • Containers need the file mounted read-only and every referenced secret explicitly passed into their environment.
    • YAML file changes require a server restart; they are not discovered from arbitrary request bodies.

Portal URLs and browser sessions

  • Sign in at /login, for example https://slo.example.com/login. The root / selects an authorized workspace after authentication. Pages have stable tenant-scoped paths:
ScreenExample path
Home/tenants/commerce/home
SLO list and details/tenants/commerce/slos, /tenants/commerce/slos/api-latency
Critical user journeys/tenants/commerce/critical-user-journeys/checkout
Reliability reviews/tenants/commerce/reviews/<record-id>
Intent conversations/tenants/commerce/intents/<record-id>
Session replay/tenants/commerce/replays/<record-id>
Telemetry connections/tenants/commerce/telemetry-connections
Access control/tenants/commerce/access-control
  • Browser Back/Forward and macOS swipe navigation restore the URL's page, resource and authorized tenant.
    • Navigation links support opening a new tab.
    • Reloading a known page serves the portal shell; unknown API and asset paths remain 404.
    • Previous hash links for reviews, intents and replays still resolve and are replaced with canonical paths when opened.
    • A nonexistent resource shows an unavailable-resource message.
    • A link to an unauthorized tenant shows an access error and a choice of authorized workspaces; it does not substitute another tenant's data.
  • Deploy the portal at the origin root.
    • Proxies must forward /login, /tenants/*, /assets/*, /auth/* and /api/* to Nines, preserving the path.
    • Do not configure a blanket index.html fallback for APIs or assets.
    • OIDC redirect URIs remain the exact /auth/oidc/<provider>/callback URLs; /login is the browser entry point.
  • Sign-in preserves only a validated workspace path in returnTo.
    • Same-tab OIDC sign-in also uses optional session storage for that non-secret path.
    • External URLs, query parameters, fragments and malformed identifiers cannot become return destinations.
    • Without browser storage, local/password login still returns through the query; an OIDC round trip falls back to an authorized home page.
    • Never place passwords, API keys or session tokens in a URL.
    • API keys entered in the portal stay in memory, are sent in authorization headers and are forgotten on reload or sign-out.
    • The credential dialog clears its input on close; login and credential forms are excluded from replay.
    • The only persistent browser preference is the theme.
  • Browser sessions use HttpOnly, SameSite cookies, with Secure and __Host- protection on HTTPS deployments.
    • Server responses disable caching for portal pages and authentication, and use Referrer-Policy: no-referrer.
    • Existing CSRF, provider trust and tenant role checks apply to every API request; UUIDs and tenant paths do not grant access.
  • New alert events, proposed change sets and rollback records use random UUIDv4 identifiers in Go.
    • Portal-created reviews, intent conversations and replay records use browser-generated UUIDv4 identifiers.
    • SLOs, journeys and tenants retain their declared readable names, and existing identifiers remain valid.
    • Authentication credentials use a separate 256-bit cryptographic token generator; UUIDs are identifiers, not secrets.

Platform administration

  • The platform admin console uses explicit platformAdmins provider/subject entries in the authentication configuration.
    • It is separate from tenant ownership and requires a real browser session; tenant API keys do not grant platform access.
    • The local Compose and Kubernetes examples explicitly grant the bootstrap local admin identity access to the console.

Local accounts

  • The persistent Compose deployment and Kubernetes reference enable a local provider. admin is seeded with NINES_BOOTSTRAP_PASSWORD on the first start; its hash and memberships persist in PostgreSQL.
    • Owners use Access control → Users for profiles, password resets, roles and tenant access. A reset revokes existing sessions.
    • Changing the environment variable does not overwrite an existing password.
  • For native execution, mount or copy the local account configuration, set AUTH_CONFIG_FILE to it, and supply NINES_PUBLIC_URL and NINES_BOOTSTRAP_PASSWORD through the process environment. Use HTTPS outside loopback. API-token credentials can coexist with account login.

Microsoft Entra ID / OIDC

  • The Entra example configures OIDC SSO. Register a workforce web application in your Entra tenant, then set:
  • A Web redirect URI such as https://slo.example.com/auth/oidc/microsoft/callback. The provider ID microsoft is part of the exact callback path.
  • The issuer https://login.microsoftonline.com/YOUR_DIRECTORY_ID/v2.0 and the application's client ID.
  • A protected client secret in NINES_ENTRA_CLIENT_SECRET.
  • publicURL to the actual external HTTPS origin and AUTH_CONFIG_FILE to the mounted auth YAML.
  • Configure exact app-role values or group Object IDs in roleMappings.
    • For example, map a signed roles value Reliability.Admin to owner for the commerce tenant, and assign that app role to the intended administrator in Entra.
    • The mapping's tenant must exist in the tenant configuration.
    • Group claims must be present in the verified token; group-overage markers do not establish membership and are not expanded through Microsoft Graph.
  • If using a bootstrap entry, use the exact application-specific OIDC sub, not an email, UPN or directory Object ID.
    • Obtain it through an approved identity-administration process and keep a recovery owner.
    • Bootstrap is one-time provisioning per tenant/identity database, not ongoing directory synchronization.
    • Do not leave placeholder bootstrap subjects in a shared deployment.
  • Keep provider IDs stable.
    • Signed claims, audience, state, nonce and PKCE are checked.
    • Browser sessions and their linked CLI credentials are pinned to the authenticating provider.
    • Removing a provider or changing its OIDC issuer/client ID invalidates those sessions on the next request after the configuration is loaded.
    • LDAP URL, search base, login filter and immutable subject-attribute changes also require sign-in again.
    • Secret rotation and display-name changes preserve sessions; current role mappings and tenant memberships are still checked on each request.
    • For providers with role mappings, browser and linked CLI sessions are capped by the earlier of verified-claim age (claimsMaxAgeMinutes), ID-token expiry and the configured session lifetime.
    • This also requires directly granted users to sign in again when that authentication evidence expires; it does not remove their independent membership. It is not continuous access evaluation.
    • After changing mappings, test a fresh sign-in and verify the role in each intended tenant.
    • Verify that an unrelated user cannot enter those tenants.

LDAP and SAML upstreams

  • The generic auth example includes an LDAP provider.
    • Use LDAPS or StartTLS, a trusted CA, a restricted directory bind account and a stable subject attribute.
    • Plain LDAP binds and certificate-verification bypasses are unsupported.
    • Map the verified subject to tenant membership using bootstrap or tenant administration.
    • LDAP sign-in alone does not grant a role.
  • Native SAML and SCIM are not implemented.
    • Use an administrator-managed identity broker that presents OIDC to Nines if the upstream organization uses SAML.
    • The same tenant authorization rules still apply.

CLI login

sh
nines config set-context commerce --server https://slo.example.com --tenant commerce
nines login --context commerce --method sso
nines get slos --context commerce --agent
  • The browser flow uses the server's configured providers and issues a short-lived, single-tenant Nines credential.
    • It does not hand the identity-provider token to the CLI.
    • Headless automation should inject NINES_API_KEY through its secret manager.
    • See the CLI guide for storage, precedence and logout.
  • Sessions created before provider pinning was introduced require one new sign-in after upgrade; their CLI credentials must be renewed with nines login. No identity or membership records are migrated.
  • Run make test-identity for disposable PostgreSQL, signed OIDC, real OpenLDAP TLS and native CLI acceptance.
    • See identity acceptance for its evidence boundary and an optional real-Entra procedure.
    • Verify recovery access, viewer restrictions, cross-tenant denial and credential revocation before onboarding a team.
    • Real Entra/LDAP configuration requires an environment-specific acceptance test; synthetic provider tests are not a substitute.