{"record":{"id":"28c17a18a7492b24","repo":"hyperledger/fabric","slug":"access-denied-no-authentication-info-in-request","errorCode":null,"errorMessage":"access denied, no authentication info in request","messagePattern":"access denied, no authentication info in request","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"discovery/service.go","lineNumber":242,"sourceCode":"\t\t\t\tIdentity:       id.Identity,\n\t\t\t\tMembershipInfo: aliveInfo.Envelope,\n\t\t\t}\n\t\t}\n\t}\n\treturn peersByOrg\n}\n\n// validateStructure validates that the request contains all the needed fields and that they are computed correctly\nfunc validateStructure(ctx context.Context, request *discovery.SignedRequest, tlsEnabled bool, certHashFromContext certHashExtractor) (*discovery.Request, error) {\n\tif request == nil {\n\t\treturn nil, errors.New(\"nil request\")\n\t}\n\treq, err := protoext.SignedRequestToRequest(request)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed parsing request\")\n\t}\n\tif req.Authentication == nil {\n\t\treturn nil, errors.New(\"access denied, no authentication info in request\")\n\t}\n\tif len(req.Authentication.ClientIdentity) == 0 {\n\t\treturn nil, errors.New(\"access denied, client identity wasn't supplied\")\n\t}\n\tif !tlsEnabled {\n\t\treturn req, nil\n\t}\n\tcomputedHash := certHashFromContext(ctx)\n\tif len(computedHash) == 0 {\n\t\treturn nil, errors.New(\"client didn't send a TLS certificate\")\n\t}\n\tif !bytes.Equal(computedHash, req.Authentication.ClientTlsCertHash) {\n\t\tclaimed := hex.EncodeToString(req.Authentication.ClientTlsCertHash)\n\t\tlogger.Warningf(\"client claimed TLS hash %s doesn't match computed TLS hash from gRPC stream %s\", claimed, hex.EncodeToString(computedHash))\n\t\treturn nil, errors.New(\"client claimed TLS hash doesn't match computed TLS hash from gRPC stream\")\n\t}\n\treturn req, nil\n}","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/discovery/service.go#L224-L260","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nreq := discovery.NewRequest()\nreq.AddQueryToPeersMapper(...) // Authentication left nil\nsigned := req.ToSignedRequest()\n// after\nreq := discovery.NewRequest()\nreq.Authentication = &discovery.AuthInfo{ClientIdentity: identity, ClientTlsCertHash: tlsCertHash}\nsigned := req.ToSignedRequest()","handlingStrategy":"validation","validationCode":"if req.Authentication == nil || len(req.Authentication.ClientIdentity) == 0 {\n    return errors.New(\"discovery: AuthInfo with ClientIdentity required before sending\")\n}","typeGuard":"func hasAuth(r *discovery.Request) bool {\n    return r != nil && r.GetAuthentication() != nil && len(r.GetAuthentication().GetClientIdentity()) > 0\n}","tryCatchPattern":"resp, err := client.Send(ctx, signedReq)\nif err != nil {\n    if strings.Contains(err.Error(), \"no authentication info\") {\n        return nil, fmt.Errorf(\"request missing AuthInfo; call SetAuthentication before signing: %w\", err)\n    }\n    return nil, err\n}","preventionTips":["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"],"tags":["hyperledger-fabric","discovery-service","authentication","access-denied"],"backgroundTag":"missing-authentication-info","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}