hyperledger/fabric · error

certificate extracted from TLS connection isn't authorized

Error message

certificate extracted from TLS connection isn't authorized

What it means

A TLS client certificate was present in the request context, but mapping.LookupByClientCert(cert) found no stub in the channel's member mapping matching that certificate. The certificate is not one of the authorized cluster members (orderer nodes) configured for the channel, so the sender's identity is rejected.

Source

Thrown at orderer/common/cluster/comm.go:108

		return nil, errors.Errorf("badly formatted message, cannot extract channel")
	}

	c.Lock.RLock()
	mapping, exists := c.Chan2Members[channel]
	c.Lock.RUnlock()

	if !exists {
		return nil, errors.Errorf("channel %s doesn't exist", channel)
	}

	cert := util.ExtractRawCertificateFromContext(ctx)
	if len(cert) == 0 {
		return nil, errors.Errorf("no TLS certificate sent")
	}

	stub := mapping.LookupByClientCert(cert)
	if stub == nil {
		return nil, errors.Errorf("certificate extracted from TLS connection isn't authorized")
	}
	return &requestContext{
		channel: channel,
		sender:  stub.ID,
	}, nil
}

// Remote obtains a RemoteContext linked to the destination node on the context
// of a given channel
func (c *Comm) Remote(channel string, id uint64) (*RemoteContext, error) {
	c.Lock.RLock()
	defer c.Lock.RUnlock()

	if c.shutdown {
		return nil, errors.New("communication has been shut down")
	}

	mapping, exists := c.Chan2Members[channel]

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Verify the sender's TLS cert is included in the channel's cluster members configuration (orderer addresses/certs) via a config update
  2. If certs were rotated, update the channel config with the new TLS certs and restart both ends
  3. Ensure the orderer's General.TLS.Certificate matches the cert registered in the channel config (not a stale/other node's cert)
  4. Confirm both ends trust the same TLS CA and the client cert (not server cert) is presented

Example fix

// before (channel config missing new orderer's TLS cert)
members := []Member{oldOrdererCert}
// after — add the new orderer's TLS cert to channel config
configUpdate := addClusterMemberTLS(members, newOrdererTLSCert)
channelConfigUpdate("mychannel", configUpdate)
Defensive patterns

Strategy: type-guard

Validate before calling

// Sender-side: confirm your TLS cert matches one in the channel's cluster members
func certInChannelConfig(certPEM []byte, channelConfig *common.Config) bool {
    members := channelConfig.ChannelGroup.Groups["Orderer"].Values
    tlsCerts := string(members["Cluster"].Value.Value)
    return strings.Contains(tlsCerts, strings.TrimSpace(string(certPEM)))
}

Type guard

func isAuthorizedClusterStub(stub *Stub) bool {
    return stub != nil && stub.ID != ""
}
// usage: only proceed when guard passes
if stub := mapping.LookupByClientCert(cert); isAuthorizedClusterStub(stub) { ... }

Try / catch

if _, err := comm.Remote(channel, id); err != nil {
    if strings.Contains(err.Error(), "isn't authorized") {
        // trigger cert/config sync: fetch latest channel config and compare TLS certs
        return fmt.Errorf("orderer TLS cert not in channel cluster config: %w", err)
    }
}

Prevention

When it happens

Trigger: DispatchSubmit or DispatchConsensus receives a request whose TLS cert doesn't match any entry in the channel's Cluster membership (cluster.Server root certs / members list) — e.g. an unauthorized node, a renewed cert not yet in channel config, or cert loaded in the wrong order (DER vs PEM byte mismatch in lookup).

Common situations: Orderer TLS certificate rotated/re-enrolled but the channel's cluster membership config not updated; joining a new orderer whose cert wasn't added via config update; connecting with the server cert instead of the client cert; CA mismatch between sender cert and configured members.

Understand the failure class

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/3726d734b4bea294. Report an issue: GitHub.