Skip to main content
Version: Next

Split Identity Proxy Configuration

The split identity proxy configuration separates browser-facing IdP work from persistent identity backend ownership.

  • Edge instances terminate public OIDC/SAML/MFA/WebAuthn browser flows and store only edge-owned flow/session state.
  • Authority instances own local backend access, persistent identity data, MFA data, WebAuthn credentials, backend references, and authority-side caller tokens.
  • Remote backends let the edge use the authority through hardened internal gRPC without direct LDAP, Lua, or authority Redis access.

This page documents the configuration surface. For a step-by-step deployment guide, see Building a Distributed Identity Proxy.

Minimal Shape

The edge and authority can run the same Nauthilus binary. The role comes from configuration.

Authority-Side Configuration

The authority needs:

  • a local backend such as LDAP, Lua, or the test backend;
  • a gRPC authority listener;
  • caller authentication for authority RPCs;
  • Redis for caller tokens, backend references, idempotency, and backend cache;
  • optional HTTP/OIDC token endpoint when edge caller auth uses client credentials.

gRPC Authority Listener

runtime:
servers:
grpc:
authority:
enabled: true
address: "0.0.0.0:9444"
tls:
enabled: true
cert: "/etc/nauthilus/tls/authority.crt"
key: "/etc/nauthilus/tls/authority.key"
client_ca: "/etc/nauthilus/tls/edge-ca.crt"
require_client_cert: true
min_tls_version: "TLS1.3"

Non-loopback authority listeners must use TLS. Split deployments should use mTLS so the authority can bind backend references to the edge client identity.

Authority Caller Authentication

Authority RPCs use the same backchannel caller-auth roots as other internal API surfaces:

auth:
backchannel:
oidc_bearer:
enabled: true

For service-principal caller tokens, enable OIDC and define a client that can use client_credentials. private_key_jwt is the recommended method for edge-to-authority caller tokens:

identity:
oidc:
enabled: true
issuer: "https://authority.internal.example"
access_token_type: "opaque"
token_endpoint_auth_methods_supported:
- private_key_jwt
scopes_supported:
- openid
- nauthilus:authenticate
- nauthilus:lookup_identity
- nauthilus:list_accounts
- nauthilus:mfa_read
- nauthilus:mfa_verify
- nauthilus:mfa_write
- nauthilus:webauthn_read
- nauthilus:webauthn_write
- nauthilus:attribute_read
clients:
- name: "Edge service principal"
client_id: "edge-primary"
grant_types:
- client_credentials
token_endpoint_auth_method: "private_key_jwt"
client_public_key_file: "/etc/nauthilus/keys/edge-primary.pub"
client_public_key_algorithm: "RS256"
access_token_type: "opaque"
access_token_lifetime: 5m
scopes:
- nauthilus:authenticate
- nauthilus:lookup_identity
- nauthilus:list_accounts
- nauthilus:mfa_read
- nauthilus:mfa_verify
- nauthilus:mfa_write
- nauthilus:webauthn_read
- nauthilus:webauthn_write
- nauthilus:attribute_read

Opaque caller tokens are stored and validated by the authority using authority Redis.

Local Authority Backend

The authority keeps the normal local backend configuration:

auth:
backends:
order:
- ldap
ldap:
default:
# LDAP backend settings

or:

auth:
backends:
order:
- lua
lua:
backend:
default:
# Lua backend settings

The authority is the only role that needs these backend credentials in a strict split deployment.

Edge-Side Configuration

The edge needs:

  • browser-facing HTTP/HTTPS IdP endpoints;
  • edge Redis for sessions and IdP flow state;
  • an outbound authority client;
  • a remote backend definition that references the outbound authority client;
  • OIDC/SAML client or SP-facing configuration as usual.

Outbound Authority Client

runtime:
clients:
grpc:
nauthilus_authorities:
primary:
address: "authority.internal.example:9444"
timeout: 5s
edge_cluster_id: "dmz-edge"
edge_instance_id: "edge-a"
tls:
enabled: true
server_name: "authority.internal.example"
ca: "/etc/nauthilus/tls/authority-ca.pem"
cert: "/etc/nauthilus/tls/edge-a.crt"
key: "/etc/nauthilus/tls/edge-a.key"
min_tls_version: "TLS1.3"
caller_auth:
oidc_bearer:
enabled: true
mode: "client_credentials"
token_endpoint: "https://authority.internal.example/oidc/token"
client_id: "edge-primary"
token_endpoint_auth_method: "private_key_jwt"
client_private_key_file: "/etc/nauthilus/keys/edge-primary.key"
client_key_id: "edge-primary-rs256"
client_assertion_alg: "RS256"
audience: "https://authority.internal.example/oidc/token"
scopes:
- nauthilus:authenticate
- nauthilus:lookup_identity
- nauthilus:list_accounts
- nauthilus:mfa_read
- nauthilus:mfa_verify
- nauthilus:mfa_write
- nauthilus:webauthn_read
- nauthilus:webauthn_write
- nauthilus:attribute_read
token_cache:
backend: "redis"
key_prefix: "grpc:authority_tokens:"
refresh_before_expiry: 30s
refresh_lock_ttl: 10s

Authority Client Fields

PathRequiredDefaultDescription
addressyesnoneAuthority gRPC target as host:port.
timeoutno5sAuthority RPC timeout, maximum one minute.
edge_cluster_idrecommendedemptyStable cluster identifier used in metadata and backend-reference validation.
edge_instance_idrecommendedemptyEdge node identifier used in metadata and logs.
split_strict_modenotrueEnables strict split-deployment safety checks where applicable.
tls.enabledrequired off-loopbackfalseEnables TLS for the outbound authority client.
tls.server_namerecommendedtarget hostServer name used for certificate verification.
tls.carequired off-loopback with TLSnoneCA bundle for authority server verification.
tls.certrequired off-loopback with mTLSnoneEdge client certificate.
tls.keyrequired off-loopback with mTLSnoneEdge client private key.
tls.min_tls_versionnoTLS1.2TLS1.2 or TLS1.3. Use TLS1.3 for new split deployments.

Plaintext authority clients are accepted only for loopback targets. Non-loopback authority targets require TLS and, in split deployments, mTLS certificate material.

Caller Auth Fields

The current recommended caller-auth mode is OIDC bearer tokens from the authority token endpoint:

PathRequiredDefaultDescription
caller_auth.oidc_bearer.enabledyesfalseEnables client-credentials caller-token acquisition.
caller_auth.oidc_bearer.modeyesnoneMust be client_credentials.
caller_auth.oidc_bearer.token_endpointyesnoneAuthority OIDC token endpoint.
caller_auth.oidc_bearer.client_idyesnoneEdge service-principal client id.
caller_auth.oidc_bearer.token_endpoint_auth_methodyesnoneprivate_key_jwt, client_secret_basic, or client_secret_post.
caller_auth.oidc_bearer.client_private_key_filefor private_key_jwtnonePrivate key used to sign the client assertion.
caller_auth.oidc_bearer.client_key_idrecommendedemptykid for the client assertion.
caller_auth.oidc_bearer.client_assertion_algfor private_key_jwtnoneRS256 or EdDSA.
caller_auth.oidc_bearer.audiencerecommendedtoken endpointJWT audience expected by the authority.
caller_auth.oidc_bearer.client_secretfor client-secret methodsnoneClient secret for client_secret_basic or client_secret_post.
caller_auth.oidc_bearer.scopesrecommendedemptyAuthority scopes requested by the edge.
caller_auth.oidc_bearer.static_token_filedev/emergency onlyemptyStatic bearer token file. Requires developer or emergency mode.
caller_auth.oidc_bearer.static_token_emergency_modenofalseAllows static-token use outside developer mode.

Token Cache Fields

PathRequiredDefaultDescription
token_cache.backendnoredisCache backend. The current supported value is redis.
token_cache.key_prefixnogrpc:authority_tokens:Redis key prefix for edge-cached authority caller tokens.
token_cache.refresh_before_expiryno30sRefresh skew before token expiry.
token_cache.refresh_lock_ttlno10sDistributed refresh-lock TTL for multi-edge deployments.

The token cache belongs to edge Redis, not authority Redis.

Remote Backend

auth:
backends:
order:
- remote
remote:
default:
authority: "primary"
mode: "nauthilus"
timeout: 5s
allowed_operations:
- auth
- lookup_identity
- list_accounts
- mfa_read
- mfa_verify
- mfa_write
- webauthn_read
- webauthn_write
- attribute_read

See Remote Authority Backend for the backend-specific reference.

Required Scopes

The authority checks OAuth scopes independently from the edge allowed_operations list:

ScopeTypical remote operation
nauthilus:authenticateAuthenticate
nauthilus:lookup_identityLookupIdentity, identity resolution
nauthilus:list_accountsListAccounts
nauthilus:mfa_readRead MFA state
nauthilus:mfa_verifyVerify TOTP or consume recovery codes
nauthilus:mfa_writeRegister/delete TOTP and recovery codes
nauthilus:webauthn_readRead WebAuthn public credentials
nauthilus:webauthn_writeSave, update, or delete WebAuthn credentials
nauthilus:attribute_readRead identity attributes for OIDC/SAML claims

Grant only the scopes the edge actually needs.

Redis Separation

Use separate Redis instances or hard network separation:

This split matters because edge Redis contains public IdP flow and session state, while authority Redis contains backend references, caller access tokens, idempotency outcomes, and backend cache data. Do not share a Redis database between the two roles.

Standalone Compatibility

Split identity proxy is optional. A single Nauthilus instance can still run as IdP and authority in one process:

runtime:
servers:
grpc:
authority:
enabled: true

auth:
backends:
order:
- ldap

In that shape, the same process owns the IdP endpoints, the local backend, and optionally the gRPC authority listener. Do not configure auth.backends.order: [remote] against itself unless you explicitly want to test the remote path; local backends are the normal standalone model.