ory/hydra · error

the CA certificate does not have the client authentication…

Error message

the CA certificate does not have the client authentication extended key usage (OID 1.3.6.1.5.5.7.3.2) set

What it means

NewClientCert signs a client certificate using the provided CA. Before doing any work it checks that the CA certificate declares ExtKeyUsageClientAuth (OID 1.3.6.1.5.5.7.3.2). If the CA was created without the client-auth extended key usage, signing a client cert from it would yield a certificate peers reject, so the function fails fast with this error. It is a configuration problem with the CA certificate, not with the client key.

Solutions

  1. Re-create the CA with the client-auth EKU: pass an option that sets ExtKeyUsage to include x509.ExtKeyUsageClientAuth.
  2. If you cannot re-issue the CA, provision a separate CA that is allowed for client authentication.
  3. Verify the loaded CA with cert.CheckSignature/cert.ExtKeyUsage before calling NewClientCert.

Example fix

// before
caCert, _ := tlsx.CreateSelfSignedCertificate(caKey) // no EKU opts
client, err := tlsx.NewClientCert(caCert, caKey)
// after
caCert, _ := tlsx.CreateSelfSignedCertificate(caKey, func(c *x509.Certificate) {
    c.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}
    c.IsCA = true
})
client, err := tlsx.NewClientCert(caCert, caKey)
Defensive patterns

Strategy: validation

Validate before calling

func caSupportsClientAuth(caCert *x509.Certificate) bool {
    return slices.Contains(caCert.ExtKeyUsage, x509.ExtKeyUsageClientAuth)
}
// call before NewClientCert

Type guard

func isClientAuthCA(cert *x509.Certificate) bool {
    return cert != nil && slices.Contains(cert.ExtKeyUsage, x509.ExtKeyUsageClientAuth)
}

Try / catch

client, err := tlsx.NewClientCert(caCert, caKey)
if err != nil && strings.Contains(err.Error(), "client authentication extended key usage") {
    // re-issue the CA with ExtKeyUsageClientAuth before retrying
}

Prevention

When it happens

Trigger: Calling NewClientCert with a CA certificate generated without the ClientAuth extended key usage option (e.g. created via CreateSelfSignedCertificate with default opts, which sets server auth, or with ExtKeyUsage opts that omitted x509.ExtKeyUsageClientAuth).

Common situations: Reusing a server-only TLS CA to mint client certificates for mTLS; loading a CA from an external PKI that was provisioned for server authentication only; forgetting to pass the ExtKeyUsage option when creating the CA.

Understand the failure class

Related errors


AI-assisted analysis of ory/hydra@4174065ffb (2026-09-03). Data as JSON: /api/errors/02a30ee30a1f5ccb. Report an issue: GitHub.

Appendix: source

Thrown at oryx/tlsx/cert.go:301

	if err != nil {
		return cert, errors.Errorf("failed to encode private key: %s", err)
	}
	return cert, nil
}

// PEMBlockForKey returns a PEM-encoded block for key.
func PEMBlockForKey(key interface{}) (*pem.Block, error) {
	b, err := x509.MarshalPKCS8PrivateKey(key)
	if err != nil {
		return nil, errors.WithStack(err)
	}
	return &pem.Block{Type: "PRIVATE KEY", Bytes: b}, nil
}

// NewClientCert creates a new client TLS certificate signed by the given CA.
func NewClientCert(CAcert *x509.Certificate, CAkey crypto.PrivateKey, opts ...CertificateOpts) (*tls.Certificate, error) {
	if !slices.Contains(CAcert.ExtKeyUsage, x509.ExtKeyUsageClientAuth) {
		return nil, errors.Errorf("the CA certificate does not have the client authentication extended key usage (OID 1.3.6.1.5.5.7.3.2) set")
	}
	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
	if err != nil {
		return nil, errors.Errorf("failed to generate serial number: %s", err)
	}

	key, err := rsa.GenerateKey(rand.Reader, 3072)
	if err != nil {
		return nil, errors.Errorf("failed to generate private key: %s", err)
	}

	template := &x509.Certificate{
		SerialNumber: serialNumber,
		Subject: pkix.Name{
			Organization: []string{"Ory GmbH"},
			CommonName:   "ORY",
		},

View on GitHub (pinned to 4174065ffb)