{"record":{"id":"63c03bbec2ee91aa","repo":"hyperledger/fabric","slug":"client-identity-expired","errorCode":null,"errorMessage":"client identity expired","messagePattern":"client identity expired","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/ledger/snapshotgrpc/snapshot_service.go","lineNumber":117,"sourceCode":"\t\treturn nil, err\n\t}\n\n\tresult, err := lgr.PendingSnapshotRequests()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &pb.QueryPendingSnapshotsResponse{BlockNumbers: result}, nil\n}\n\nfunc (s *SnapshotService) checkACL(resName string, signatureHdr *cb.SignatureHeader, signedRequest *pb.SignedSnapshotRequest) error {\n\tif signatureHdr == nil {\n\t\treturn errors.New(\"missing signature header\")\n\t}\n\n\texpirationTime := crypto.ExpiresAt(signatureHdr.Creator)\n\tif !expirationTime.IsZero() && time.Now().After(expirationTime) {\n\t\treturn errors.New(\"client identity expired\")\n\t}\n\n\tif err := s.ACLProvider.CheckACLNoChannel(\n\t\tresName,\n\t\t[]*protoutil.SignedData{{\n\t\t\tIdentity:  signatureHdr.Creator,\n\t\t\tData:      signedRequest.Request,\n\t\t\tSignature: signedRequest.Signature,\n\t\t}},\n\t); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (s *SnapshotService) getLedger(channelID string) (ledger.PeerLedger, error) {\n\tif channelID == \"\" {","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/ledger/snapshotgrpc/snapshot_service.go#L99-L135","documentation":"checkACL extracts the creator from the SignatureHeader and checks its certificate's expiration via crypto.ExpiresAt. If the identity has an expiration timestamp and that time is in the past, the request is rejected with 'client identity expired' before the ACL policy is evaluated.","triggerScenarios":"Any snapshot request (Generate/Cancel/QueryPendings) signed by an identity whose x509 certificate expiry has passed, or a header whose Creator cert carries an expired/notAfter field.","commonSituations":"Long-running clients whose enrollment certificates expired (Fabric default 1-year certs); peers/clients not rotated after CA certificate renewal; offline signatures assembled long ago and replayed after expiry.","solutions":["Renew the client's enrollment certificate from the CA (fabric-ca enroll again) and rebuild the request.","Verify node clock skew — a badly skewed clock can flag a valid cert as expired.","Update MSP/certificates across the network per the Fabric operational guide after CA rotation.","Re-sign the request with the fresh identity rather than reusing cached signed payloads."],"exampleFix":"// before\nsigner := loadSigner(\"expired-cert.pem\")\n// after\nsigner := loadSigner(\"renewed-cert.pem\") // re-enrolled via fabric-ca; check crypto.ExpiresAt(hdr.Creator)","handlingStrategy":"validation","validationCode":"hdr := req.GetSignatureHeader()\nif hdr != nil {\n    if exp := crypto.ExpiresAt(hdr.Creator); !exp.IsZero() && time.Now().After(exp) {\n        return fmt.Errorf(\"identity expired at %s; re-enroll before submitting\", exp)\n    }\n}","typeGuard":"func identityValid(hdr *cb.SignatureHeader) bool {\n    exp := crypto.ExpiresAt(hdr.GetCreator())\n    return exp.IsZero() || time.Now().Before(exp)\n}","tryCatchPattern":"_, err := svc.Generate(ctx, signedReq)\nif err != nil && strings.Contains(err.Error(), \"client identity expired\") {\n    return reenrollAndRetry(ctx, signedReq) // fabric-ca re-enroll, rebuild & re-sign request\n}\nreturn err","preventionTips":["Monitor certificate expiry (Fabric default ~1 year) and rotate before deadlines.","After CA renewal, re-enroll all clients and update MSPs network-wide.","Keep clocks synced via NTP to avoid false expiry detection.","Never replay long-cached signed requests across cert rotations."],"tags":["grpc","snapshot","acl","certificate","expiry"],"backgroundTag":"client-certificate-expired","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}