crowdsecurity/crowdsec · error
tls authentication required
Error message
tls authentication required
What it means
JWT.authTLS handles mTLS client-certificate authentication for LAPI. It returns "tls authentication required" when j.TlsAuth is nil, i.e. the JWT middleware was constructed without TLS auth wired up even though the request arrived via the TLS-auth path. Normally NewJWT sets TlsAuth: &TLSAuth{}, so nil indicates a manually built JWT or a modified construction path.
Source
Thrown at pkg/apiserver/middlewares/v1/jwt.go:62
machineID := claims[MachineIDKey].(string)
return &models.WatcherAuthRequest{
MachineID: &machineID,
}
}
type authInput struct {
machineID string
clientMachine *ent.Machine
scenariosInput []string
}
func (j *JWT) authTLS(c *gin.Context) (*authInput, error) {
ctx := c.Request.Context()
ret := authInput{}
if j.TlsAuth == nil {
err := errors.New("tls authentication required")
log.Warn(err)
return nil, err
}
extractedCN, err := j.TlsAuth.ValidateCert(c)
if err != nil {
log.Warn(err)
return nil, err
}
logger := log.WithField("ip", c.ClientIP())
ret.machineID = fmt.Sprintf("%s@%s", extractedCN, c.ClientIP())
ret.clientMachine, err = j.DbClient.Ent.Machine.Query().
Where(machine.MachineId(ret.machineID)).
First(ctx)View on GitHub (pinned to 909b515798)
Solutions
- Construct the middleware with NewJWT(dbClient) so TlsAuth is initialized
- If embedding, replicate NewJWT's setup: TlsAuth: &TLSAuth{}
- Enable client-certificate auth properly in lapi.yaml under api.server.tls and restart crowdsec
- Ensure clients not using mTLS fall back to API-key auth and don't hit the TLS path
Example fix
// before
jwtMiddleware := &JWT{DbClient: dbClient}
// after
jwtMiddleware, err := NewJWT(dbClient) // sets TlsAuth: &TLSAuth{} Defensive patterns
Strategy: validation
Validate before calling
// before relying on mTLS auth, confirm the middleware has TLS auth wired:
if j.TlsAuth == nil {
return errors.New("TLS auth middleware not initialized; use NewJWT")
} Try / catch
authInput, err := j.Authenticator(c)
if err != nil {
log.WithError(err).Warn("authentication failed")
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"message": "authentication failed"})
return
} Prevention
- Always build the JWT middleware via NewJWT(dbClient), never with a bare struct literal
- Configure api.server.tls in lapi.yaml before enabling client-cert auth on clients
- Keep API-key auth available as the fallback path for non-mTLS clients
When it happens
Trigger: A request authenticated via client certificate reaches Authenticator -> authTLS while the JWT struct's TlsAuth field is nil — e.g. JWT built with &JWT{} instead of NewJWT, or code that nils TlsAuth when TLS is disabled but the server still presents/receives a client cert.
Common situations: Custom embedding of crowdsec's LAPI in another binary; config where api.tls is partially set so the server requests a client cert but the middleware lacks TlsAuth; tests constructing JWT{} directly.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- missing TLS key file
- missing TLS cert file
- invalid token for auto registration
- IP not in allowed range for auto registration
- bouncer not found
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/d1eb2985ff9381a8.
Report an issue: GitHub.