Authentication#
Navarch supports pluggable authentication for the control plane API. This document covers the built-in bearer token authentication and how to implement custom authentication methods.
Bearer token authentication#
The control plane includes built-in support for bearer token authentication. When enabled, all API requests (except health endpoints) require a valid token in the Authorization header.
Enabling authentication#
To enable authentication on the control plane:
# Using environment variable
export NAVARCH_AUTH_TOKEN="your-secret-token"
control-plane --config config.yaml
# Using command-line flag
control-plane --auth-token "your-secret-token"
The environment variable takes precedence if both are set.
Exempt endpoints#
The following endpoints do not require authentication:
/healthz— Liveness probe for orchestrators./readyz— Readiness probe for load balancers./metrics— Prometheus metrics endpoint.
Client configuration#
Clients must include the token in the Authorization header using the Bearer scheme.
For the CLI:
For curl:
curl -H "Authorization: Bearer your-secret-token" \
http://localhost:50051/navarch.ControlPlaneService/ListNodes
For node agents:
Token generation#
Generate a secure token using a cryptographically secure random source:
Store tokens securely using your cloud provider's secret manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault).
Custom authentication#
For authentication methods beyond bearer tokens (JWT, OIDC, mTLS), implement the Authenticator interface and rebuild the control plane.
Authenticator interface#
Return values:
(*Identity, true, nil)— Authentication succeeded.(nil, false, nil)— No credentials found; try the next authenticator.(nil, false, error)— Credentials found but invalid.
Identity#
The Identity struct represents an authenticated entity:
type Identity struct {
Subject string // Primary identifier (e.g., "user:jane@example.com")
Groups []string // Group memberships for authorization
Extra map[string][]string // Additional claims from the auth source
}
The Subject field aligns with the JWT sub claim and X.509 certificate subject.
Chaining authenticators#
Use ChainAuthenticator to try multiple authentication methods in sequence:
chain := auth.NewChainAuthenticator(
jwtAuthenticator, // Try JWT first
bearerAuthenticator, // Fall back to static token
)
middleware := auth.NewMiddleware(chain,
auth.WithExcludedPaths("/healthz", "/readyz", "/metrics"),
)
The first authenticator to return success wins. If an authenticator returns an error (invalid credentials), the chain stops and returns that error.
Example: JWT authenticator#
type JWTAuthenticator struct {
keyFunc jwt.Keyfunc
issuer string
}
func (a *JWTAuthenticator) AuthenticateRequest(r *http.Request) (*auth.Identity, bool, error) {
header := r.Header.Get("Authorization")
if !strings.HasPrefix(header, "Bearer ") {
return nil, false, nil // No JWT, try next authenticator
}
tokenString := strings.TrimPrefix(header, "Bearer ")
token, err := jwt.Parse(tokenString, a.keyFunc)
if err != nil {
return nil, false, fmt.Errorf("invalid token: %w", err)
}
claims := token.Claims.(jwt.MapClaims)
return &auth.Identity{
Subject: claims["sub"].(string),
Groups: extractGroups(claims),
}, true, nil
}
Security considerations#
When implementing custom authenticators:
- Use
crypto/subtle.ConstantTimeComparefor secret comparison to prevent timing attacks. - Return generic error messages ("unauthorized") to avoid leaking why authentication failed.
- Copy slices and maps in the returned
Identityto prevent mutation between requests. - Validate token expiration, issuer, and audience claims for JWT/OIDC.
Retrieving identity in handlers#
After authentication, the Identity is available in the request context:
func handleRequest(w http.ResponseWriter, r *http.Request) {
identity := auth.IdentityFromContext(r.Context())
if identity == nil {
// Unauthenticated request (only possible if WithRequireAuth(false))
return
}
log.Printf("Request from %s", identity.Subject)
}
What is next#
- Configuration reference — Server and pool configuration.
- Deployment guide — Production deployment with TLS.