Skip to content

The v1 docs follow nauthera-server's main branch and its 0.x releases on the way to 1.0, so fields and APIs can still change.

v1

Organization

Docs version v1 (main)Nauthera is pre-1.0, in a design-partner programUpdated

An Organization declares one organization: a tenant with its own issuer, signing keys, users, sessions and audit log. The operator creates it on the server through the gRPC AdminService, or adopts the organization that already holds its slug, and keeps the settings that may change in step with the resource.

PropertyValue
API group / versionnauthera.io/v1alpha1
KindOrganization
Plural / short nameorganizations / org
ScopeCluster
Definitiondeploy/crds/organization-crd.yaml in nauthera-server

The resource is cluster-scoped because creating a tenant is not a decision one namespace may make for the whole deployment: only someone allowed to create cluster-scoped resources can apply one.

Example

apiVersion: nauthera.io/v1alpha1
kind: Organization
metadata:
  name: acme
spec:
  slug: acme
  displayName: Acme Inc.
  namespaces: [acme, grafana]        # the namespaces that may configure acme
  emailDomains: [acme.example]       # routed to acme by a broker, once verified
  emailVerificationRequired: true
  deletionPolicy: Retain
  secondFactor:
    methods: [totp, passkey]
    required: true
    rules:
      - name: passkey-off-site
        outsideZones: [office]
        methods: [passkey]
  networkZones:
    - name: office
      addressRanges:
        - 203.0.113.0/24
        - 2001:db8:1::/48
  branding:
    productName: Acme
    logoUrl: https://acme.example/logo.svg
    theme:
      color:
        accent: "#7B61FF"

kubectl get organizations shows the slug, the issuer, the phase and the Ready condition's status and reason; -o wide adds the message.

Before you apply one

The server decides whether the operator may manage an organization. The operator's identity needs the organizations operation and the organization's slug (or *) in its server.grpc.tls.allowed_clients entry; in the Helm chart that is certManager.grpcTLS.allowedClients. The chart's default entry leaves out organizations and acts in the main organization only, so add organizations and the slug before applying a resource. Without them every call is refused, and the resource reports Refused with OPERATION_NOT_GRANTED or OUTSIDE_GRANT.

The main organization cannot be declared this way. A resource cannot name the slug default, and the server refuses to create, change or delete the main organization over the control plane whatever the grant says. Configure it with the deployment instead, under orgs.main (see Organizations).

What the operator does

  • Creates or adopts. A resource whose slug no organization holds creates one. One whose slug is taken adopts that organization and writes every setting that differs: displayName (the slug when unset), fapiMode, emailVerificationRequired, branding, secondFactor and networkZones.
  • Sends only what changed. On every generation the server does not hold yet, the operator reads the organization and sends only the settings that differ. An unchanged resource produces no write.
  • Fixed at creation. slug, fipsMode and deletionPolicy cannot be edited. An adopted organization whose FIPS mode differs from spec.fipsMode is reported as FixedAtCreation, and nothing is written until they agree.
  • Held to the level above. secondFactor narrows the deployment's mfa policy and can never loosen it. A policy that states more than the deployment allows (a method it does not offer, passwordless sign-in it keeps closed, a longer rememberForSeconds, a zone it does not spare in) or a rule naming a zone the organization cannot see is refused, and the resource reports Refused naming the field and the bound. See Multi-Factor Authentication.
  • Admits its namespaces. namespaces lists the namespaces whose OIDCClient, IdentityProvider, LDAPDirectory, Branding and BrokerMembership resources may configure the organization. A resource anywhere else is refused before anything reaches the server; see Which organization a resource configures. Adding or removing a namespace re-evaluates the resources in it.
  • Claims email domains. Each of emailDomains is claimed on the server, and status.emailDomains shows the TXT record to publish under it. The operator looks a pending domain up every five minutes and a settled one every hour, so a record that disappears is noticed. A domain another organization verified is reported Refused; dropping one from the list releases its claim. A broker routes an address at a verified domain to this organization.
  • Network zones are named address ranges that the organization's rules, and its clients' rules, may name beside the deployment's security.network_zones. A zone may not take a deployment zone's name, and only deployment zones can spare a challenge (spareZones).
  • Default branding. branding is what every sign-in page under the organization wears, with a client's own Branding laid over it field by field. The organization's admin dashboard wears its color, typography and radius tokens, fonts and logo. Removing branding from the resource clears the default.

The operator writes the declared settings when the resource changes. A setting changed afterwards through the admin API or nauthera-cli update org is not compared against the resource, and is written over only when the resource's next generation differs from what the server holds.

Deleting a resource

spec.deletionPolicy decides, and defaults to Retain:

  • Retain leaves the organization serving, with its users, keys and audit log.
  • Delete removes the organization from the server. It must be chosen when the resource is created, so a later edit cannot arm a deletion. Only the organization this resource created or adopted is removed: one it never reached, or one recreated under the slug since, is left alone.

A finalizer (nauthera.io/organization) holds the resource until that is done. A removal the server does not take keeps the resource in phase Deleting with reason OrganizationNotRemoved, and is retried. Each outcome is recorded as a Removed or Retained event.

The definition's description below says Delete removes the organization "with everything it holds". The server deletes the organization's own record and stops serving it, but its users, clients and sessions stay in the database. See Deleting an org.

Spec

spec.branding

Type: object | Optional

The organization's default branding: what every sign-in page under it wears, with a client's own Branding laid over it field by field; what its admin dashboard wears, reduced to its color, typography and radius tokens, fonts and logo; and what its email wears, its logo and accent color. The same document a Branding carries. Removing it clears the default.

FieldTypeRequiredDefaultDescription
appNamestringNo—App name, shown as "Continue to {appName}".
companyNamestringNo—Copyright holder shown in the footer.
faviconUrlstringNo—Icon shown in the browser tab and bookmarks: an https URL or an inline data:image/ URI.
fonts[]stringNo—Font stylesheet URLs to load, on fonts.googleapis.com or fonts.gstatic.com only: a stylesheet can restyle the password field, so the font CDN is the one host trusted with it.
heroobjectNo—Hero pane content for the split layout.
layoutstringNo—Page layout — centered (default) or split. One of: centered, split.
logoUrlstringNo—Logo image rendered in the header: an https URL or an inline data:image/ URI. The /ui CSP img-src blocks http images (mixed content). The admin dashboard shows an inline logo of up to 64 KiB, or one on its own origin, and nothing else. The organization's email shows its logo too; Gmail and Outlook show no SVG, so a PNG suits both.
modestringNo—Default color mode. One of: system, light, dark.
privacyUrlstringNo—
productNamestringNo—Tenant/product name shown in the auth header.
supportUrlstringNo—
termsUrlstringNo—
themeobjectNo—The design system's theme, as its defineTheme takes it. A field the design system does not know is refused; the values of its token and component maps are stored as written and checked by the server.

spec.deletionPolicy

Type: string | Optional

What deleting this resource does to the organization. Retain leaves it serving, with its users, keys and audit log. Delete removes the organization's record and its own settings, such as its zones and email domains, and stops serving it; its users, clients, sessions and audit log stay in the database. Immutable, so a later edit cannot arm a deletion.

Defaults to "Retain".

One of: Retain, Delete.

spec.displayName

Type: string | Optional

Human-readable name shown in the hosted UI. Defaults to the slug.

spec.emailDomains

Type: []string | Optional

The email domains whose addresses a broker routes to this organization, lower case, an internationalized name in its xn-- form. Each is claimed on the server and verified once the TXT record status.emailDomains names is published under it; a domain another organization verified is refused. Removing one releases its claim.

spec.emailVerificationRequired

Type: boolean | Optional

Keeps an account whose address is not verified from signing in until it follows an emailed link. An organization with no email relay can send no link, so its unverified accounts stay out.

Defaults to false.

spec.fapiMode

Type: boolean | Optional

Holds the organization's clients to the FAPI 2.0 Security Profile: pushed authorization requests are mandatory and PKCE is S256 only. It can only tighten what the deployment requires of every organization, never relax it.

Defaults to false.

spec.fipsMode

Type: boolean | Optional

Restricts the organization to the FIPS 140-3 approved algorithm set, such as PBKDF2 instead of argon2id for passwords. A server not running the validated module refuses to serve such an organization rather than serve it other algorithms. Immutable.

Defaults to false.

spec.namespaces

Type: []string | Optional

The namespaces whose OIDCClient, IdentityProvider, LDAPDirectory, Branding and BrokerMembership resources may configure this organization. A resource in a namespace no organization lists is refused, and one in a namespace several list names its organization in spec.organization. Empty admits none.

spec.networkZones

Type: []object | Optional

The organization's own network zones, beside the deployment's: its rules and its clients' rules may name either. A zone may not take a deployment zone's name, and only deployment zones spare a challenge.

FieldTypeRequiredDefaultDescription
addressRanges[]stringYes—CIDR ranges, IPv4 or IPv6; one covering every address of its family is refused.
namestringYes—A lowercase label of up to 63 letters, digits and hyphens.

spec.secondFactor

Type: object | Optional

The organization's second-factor policy, narrowing the deployment's: which methods its users may use, whether holding one is a condition of a session, whether a passkey alone signs a user in, when a user who holds one is spared the challenge, and the rules that narrow it further for some sign-ins. Absent is the empty policy. The organization's admin dashboard runs under it as it is, but is never spared; its other clients narrow it. A policy stating more than the deployment allows is refused, and the resource reports the refusal naming the bound.

FieldTypeRequiredDefaultDescription
alwaysChallengebooleanNo—Spares no sign-in, on a remembered browser or in a zone.
methods[]stringNo—The methods a user may enroll and answer with. Empty inherits the level above.
passwordlessbooleanNo—Opens sign-in with a discoverable passkey and no password. It is open only where the deployment, the organization and the client all open it.
rememberForSecondsintegerNo—Spares a user who holds a permitted factor the challenge on a browser that passed a second factor for them within this many seconds, while their password and factors are the ones it passed under. Zero inherits the level above's window.
requiredbooleanNo—Sends a user who holds no permitted factor through enrollment before a session is issued.
rules[]objectNo—Narrow this level's policy for the sign-ins that meet them. A rule only ever narrows its own level.
spareZones[]stringNo—Spares such a user the challenge from these of the deployment's network zones. Empty inherits the level above's.

spec.slug

Type: string | Required

The slug the organization is addressed at (/orgs/{slug}/) and known by on the server: lowercase letters, digits and hyphens, not starting with a hyphen. Immutable.

Status

The operator writes status from the server's answer. id, issuer and observedGeneration come from the server; lastReconciledTime moves on every reconcile. status.issuer is the issuer the OIDCClient, IdentityProvider, LDAPDirectory, Branding and BrokerMembership resources in the namespaces it admits are sent under. status.emailDomains reports each of spec.emailDomains: its state (Pending, Verified or Refused) and the TXT record that proves it.

phase is one of Pending, Ready, Error or Deleting. Beside the connection reasons every resource shares (Refused, Unreachable, Unsupported, CredentialUnavailable, TrustAnchorUnavailable; see the OIDCClient reference), the Ready condition's reason is one of:

ReasonPhaseMeaning
CreatedReadyThe server created the organization from this resource.
AdoptedReadyAn organization already held the slug. This resource now manages it, and any setting that differed was written.
SyncedReadyThe server holds the current generation of the settings.
FixedAtCreationErrorThe organization's FIPS mode differs from spec.fipsMode. Nothing is written.
OrganizationNotRemovedDeletingUnder deletionPolicy: Delete, the server has not removed the organization yet.

A refusal is retried every five minutes, and a server that does not answer about once a minute.

FieldTypeDescription
conditions[]objectStandard Kubernetes conditions (Ready, Synced, ...).
emailDomains[]objectEach domain of spec.emailDomains as the server holds its claim.
idstringThe server-assigned organization ID, stable for the organization's life.
issuerstringThe organization's OIDC issuer: the iss its tokens carry, and the issuer the resources in the namespaces it admits are sent under.
lastReconciledTimestringWhen the operator last reconciled the resource, whatever the outcome. A stale value means the operator is not running, not the leader, or cannot see the resource.
observedGenerationinteger.metadata.generation last reconciled by the server.
phasestringHigh-level lifecycle phase.