hyperledger/fabric · error
access denied, no authentication info in request
Error message
access denied, no authentication info in request
What it means
validateStructure returns this error when the parsed request has no Authentication section. Discovery requires authentication info (the client's identity) so the service can compute the TLS cert hash and authorize the caller; a request without it is rejected as access denied.
Source
Thrown at discovery/service.go:242
Identity: id.Identity,
MembershipInfo: aliveInfo.Envelope,
}
}
}
return peersByOrg
}
// validateStructure validates that the request contains all the needed fields and that they are computed correctly
func validateStructure(ctx context.Context, request *discovery.SignedRequest, tlsEnabled bool, certHashFromContext certHashExtractor) (*discovery.Request, error) {
if request == nil {
return nil, errors.New("nil request")
}
req, err := protoext.SignedRequestToRequest(request)
if err != nil {
return nil, errors.Wrap(err, "failed parsing request")
}
if req.Authentication == nil {
return nil, errors.New("access denied, no authentication info in request")
}
if len(req.Authentication.ClientIdentity) == 0 {
return nil, errors.New("access denied, client identity wasn't supplied")
}
if !tlsEnabled {
return req, nil
}
computedHash := certHashFromContext(ctx)
if len(computedHash) == 0 {
return nil, errors.New("client didn't send a TLS certificate")
}
if !bytes.Equal(computedHash, req.Authentication.ClientTlsCertHash) {
claimed := hex.EncodeToString(req.Authentication.ClientTlsCertHash)
logger.Warningf("client claimed TLS hash %s doesn't match computed TLS hash from gRPC stream %s", claimed, hex.EncodeToString(computedHash))
return nil, errors.New("client claimed TLS hash doesn't match computed TLS hash from gRPC stream")
}
return req, nil
}View on GitHub (pinned to 2736b63f8f)
Solutions
- Populate req.Authentication with the client identity (e.g. discovery.NewRequest().SetAuthentication(identity, certHash)) before signing
- Verify your client library version and use its high-level discovery client, which sets authentication automatically
- Ensure the mTLS client certificate hash is supplied when TLS is enabled (see the subsequent tlsCertHash check)
- Check the server log to confirm this is the exact rejection line, distinguishing it from the empty-identity variant
Example fix
// before
req := discovery.NewRequest()
req.AddQueryToPeersMapper(...) // Authentication left nil
signed := req.ToSignedRequest()
// after
req := discovery.NewRequest()
req.Authentication = &discovery.AuthInfo{ClientIdentity: identity, ClientTlsCertHash: tlsCertHash}
signed := req.ToSignedRequest() Defensive patterns
Strategy: validation
Validate before calling
if req.Authentication == nil || len(req.Authentication.ClientIdentity) == 0 {
return errors.New("discovery: AuthInfo with ClientIdentity required before sending")
} Type guard
func hasAuth(r *discovery.Request) bool {
return r != nil && r.GetAuthentication() != nil && len(r.GetAuthentication().GetClientIdentity()) > 0
} Try / catch
resp, err := client.Send(ctx, signedReq)
if err != nil {
if strings.Contains(err.Error(), "no authentication info") {
return nil, fmt.Errorf("request missing AuthInfo; call SetAuthentication before signing: %w", err)
}
return nil, err
} Prevention
- Always call SetAuthentication (identity + TLS cert hash) before signing discovery requests
- Prefer the high-level discovery client which populates AuthInfo automatically
- Include the mTLS cert hash whenever TLS is enabled
- Add a pre-send assertion unit test that AuthInfo is populated
When it happens
Trigger: A discovery client sends a valid SignedRequest whose embedded Request lacks the Authentication field — i.e. SetAuthentication (or the equivalent identity population) was never called before signing/sending.
Common situations: Using a low-level SDK call and skipping the authentication step; an SDK version change that made explicit SetAuthentication calls necessary; copying example code that omitted authentication; custom request builders that leave Auth nil.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- empty signature bytes
- access denied: channel [%s] creator org unknown, creator is
- access denied: channel [%s] creator org [%s]
- failed computing key of signed data
- failed marshaling signed data
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/28c17a18a7492b24.
Report an issue: GitHub.