Skip to content

Pre-1.0 · Self-hosted · Design-partner program

OAuth clients as Kubernetes resources.

A self-hosted OpenID Connect server with a Kubernetes operator. The operator registers each OIDCClient declared beside your Deployment and writes its secret into a Secret.

By joining, you agree to our Privacy Policy and Terms.

How the operator works
oidcclient.yaml
apiVersion: nauthera.io/v1alpha1
kind: OIDCClient
metadata:
  name: example-webapp
  namespace: storefront
spec:
  clientId: example-webapp
  redirectUris:
    - https://app.example.com/callback
  grantTypes:
    - authorization_code
    - refresh_token
  tokenEndpointAuthMethod: client_secret_basic
  pkcePolicy: required_s256
  allowRefresh: true
  secret:
    generate: true
Checked against the OIDCClient CRD that the operator reconciles.

Runs with

  • Kubernetes
  • Helm
  • cert-manager
  • PostgreSQL
  • Redis
  • Prometheus
  • OpenTelemetry

Operator · tested on kind

From manifest to mounted Secret

OAuth clients from reviewed manifests, with no ticket and no secret copied by hand.

  1. Declare

    Built
    kind: OIDCClient

    The OIDCClient CRD refuses contradictory clients at apply time, before anything reaches the server.

  2. Register

    Built
    AdminService.UpsertOIDCClient · :9091

    The operator upserts it over mutual TLS: idempotent, etag-guarded writes, and drift noticed when someone edits the client elsewhere.

  3. Deliver

    Built
    Secret · status.secretRef

    The server mints the secret once and keeps only a hash. The operator writes it into a Secret your Deployment mounts.

Refused at apply by the CRD
$ grep -E 'tokenEndpointAuthMethod|pkcePolicy' storefront-spa.yaml
  tokenEndpointAuthMethod: none
  pkcePolicy: optional
$ kubectl apply -f storefront-spa.yaml
The OIDCClient "storefront-spa" is invalid: spec: Invalid value: public clients (tokenEndpointAuthMethod 'none') must set pkcePolicy to 'required_s256'

Why an operator, vs. Terraform and Ansible Operator roadmap

The dashboard and sign-in pages you get

Threat analytics: the critical-signal banner, the shape of the refused sign-ins and who was behind them

Take the tour

Caught before anything is applied

These unsafe production settings stop the server at startup. The Helm chart catches them at install, with the fix.

Also built in

  • Exact redirect-URI matching
  • Per-IP and per-account brute-force limits
  • Control plane needs mTLS off loopback
Read the hardening guide
helm install · production issuer
$ helm install nauthera ./deploy/helm/nauthera-server \
    --set config.issuer.url=https://auth.example.com
Error: INSTALLATION FAILED: execution error at (…):

nauthera-server: issuer "https://auth.example.com" is a real, fronted deployment (host "auth.example.com" is not
loopback), and the server refuses to start in this configuration:

  * cache.enabled is false. …
    Fix: set config.cache.enabled=true and config.cache.address.

  * the signing key is ephemeral (keys.provider=memory). …
    Fix: leave certManager.signingKey.enabled=true (…), or set config.keys.provider=file …

  * the MFA seed-encryption key is ephemeral (mfa.provider=memory). …
    Fix: set config.mfa.provider=file and supply secrets.mfaEncryptionKey.

Each of these is a startup error in the server itself, not a warning. They are
reported here so you meet them before anything is applied.

Hear when the operator ships

One email when the operator ships. No newsletter.

By joining, you agree to our Privacy Policy and Terms.