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

Branding

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

A Branding resource themes the hosted sign-in pages for a single OAuth client: the product name, logo, favicon, links, layout and a full design-system theme. The operator serializes spec.branding to JSON and writes it to the server's gRPC AdminService (UpsertBranding). The server checks it, stores it and serves it on the sign-in pages for that client, laid over the organization's default branding field by field.

PropertyValue
API group / versionnauthera.io/v1alpha1
KindBranding
Plural / short namebrandings / brand
ScopeNamespaced
Definitiondeploy/crds/branding-crd.yaml in nauthera-server

Example

apiVersion: nauthera.io/v1alpha1
kind: Branding
metadata:
  name: example-webapp-branding
  namespace: nauthera
spec:
  clientId: example-webapp
  branding:
    productName: Acme
    logoUrl: https://acme.example/logo.svg
    faviconUrl: https://acme.example/favicon.svg
    mode: system
    supportUrl: https://acme.example/support
    fonts:
      - https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap
    theme:
      color:
        accent: "#7B61FF"
        neutralStyle: cool
      typography:
        scale:
          base: 14
          ratio: 1.2
        body:
          family: Inter
          fallbacks: "-apple-system, sans-serif"
      radius:
        base: 8
        multiplier: 1

kubectl get brandings shows the client ID, the phase and the Ready condition's status and reason; -o wide adds the message.

The operator's identity needs the brandings operation, and the organization and namespace, in its server.grpc.tls.allowed_clients entry. The Helm chart's default entry grants it in the main organization from every namespace.

Each tab is one of the example brandings in nauthera-server's sign-in Storybook (web/packages/theme/src/presets.ts), shown on the sign-in screen in light and dark mode with the Branding resource that produces it. The pictures and the documents are captured from the same build, so the manifest is exactly what the picture wears. Inline hero images are shortened here. For a step-by-step walk through designing a theme in the Astryx playground and applying it, see Customize the sign-in UI.

Nauthera's sign-in screen, light
Nauthera's sign-in screen, dark
branding-neutral.yaml
apiVersion: nauthera.io/v1alpha1
kind: Branding
metadata:
  name: neutral-branding
  namespace: nauthera
spec:
  clientId: neutral-web
  branding:
    productName: Nauthera

What the operator does

  • Keyed by client. spec.clientId names the client, in the organization the resource's namespace configures (spec.organization where several admit it). The server refuses a change to either, so moving a branding to another client is a delete and a new resource. The client does not have to be declared from a manifest, or exist yet: the pages served for that client_id wear the document once it does.
  • Writes against the revision it last wrote. Each write names status.etag, the server's revision the resource last recorded. A document changed or removed over the API since is not written over: the resource goes to Error under Drifted, naming the revision the server holds. Annotate the resource nauthera.io/restore (any value) to write the declared document back; the operator removes the annotation when it has. The change is noticed on the operator's next write, that is, when the manifest changes.
  • Reports a refused document with its field. The resource goes to Error under Refused, and the message names the field.
  • Removes the document when the resource is deleted, and the client's pages fall back to the organization's default. There is no deletionPolicy: a branding decorates one client's pages and costs nothing to recreate. A finalizer (nauthera.io/branding) holds the resource until the server has removed it; until then the resource is in phase Deleting with reason BrandingNotRemoved. The hourly orphan sweep removes a branding this operator wrote whose manifest went without the finalizer running.

Validation

The resource definition types the whole document. theme is the design system's own theme by its names: kubectl explain branding.spec.branding.theme lists every axis with its enums and bounds, and a field the design system does not know, or a value outside those, is refused when the resource is applied. The token, custom-property and component maps keep their values as written, bounded only in number. The server then checks each of those values against the design system's contract and refuses one the sign-in pages could not render, naming the field.

The server also refuses a document that is not a JSON object or is larger than 128 KiB. Every fonts entry must be an https stylesheet on fonts.googleapis.com or fonts.gstatic.com, and at most 8 are allowed: a stylesheet can restyle anything on the page, the password field included, so the font CDN is the only host trusted with one. logoUrl, faviconUrl and hero.imageUrl must be an https URL or an inline data:image/ URI of a type the pages show (PNG, JPEG, GIF, WebP, SVG or ICO) whose bytes match that type. supportUrl, termsUrl and privacyUrl must be http or https URLs.

The resource definition holds the URL fields, the https scheme of a font and the font limit to the same rules at apply time. It does not check a font's host or the 128 KiB total, so a font from another host, or a document over the total, is applied and then reported as Refused, with the message naming fonts for a font.

Spec

spec.branding

Type: object | Required

The auth UI branding document. Chrome fields drive screen UI; theme is the design system's theme (color, typography, radius, motion, tokens, components, …). The operator serializes this object to JSON and sends it as BrandingSpec.branding_json.

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.clientId

Type: string | Required

The OAuth2 client_id this branding applies to.

spec.organization

Type: string | Optional

The slug of the organization this branding belongs to. Needed only where more than one organization admits the namespace in its spec.namespaces; otherwise the one that does is taken. The main organization is "default". Immutable.

Status

phase is one of Pending, Ready, Error or Deleting. The Ready condition's reason is Registered when the server holds the current generation, Drifted or Refused as above, NamespaceNotCovered when the resource's namespace is not in the operator's --namespaces, BrandingNotRemoved while a deletion waits for the server, or one of the connection and namespace reasons every resource shares (NamespaceNotAdmitted, OrganizationAmbiguous, OrganizationNotReady, OrganizationChanged; see the OIDCClient reference). A Restored event records a document written back over a drifted one.

FieldTypeDescription
clientIdstringThe resolved client_id the branding is bound to.
conditions[]objectStandard Kubernetes conditions (Ready, Synced, …).
etagstringThe server's revision of this resource, returned on every write and read. A controller compares it against what it last wrote to tell its own change from one made elsewhere, and sends it back as the expected revision so a write that would overwrite someone else's is refused instead.
issuerstringThe issuer the server homed the branding at, after its default was applied: the organization whose sign-in pages wear it.
lastReconciledTimestring
observedGenerationinteger.metadata.generation last reconciled by the server.
organizationstringThe slug of the organization the server holds the branding in. Once set, a namespace that comes to configure another organization is refused rather than moving the branding.
phasestring