{"record":{"id":"dd23d27b11bf2b3b","repo":"apache/rocketmq","slug":"check-signature-failed","errorCode":null,"errorMessage":"check signature failed.","messagePattern":"check signature failed\\.","errorType":"exception","errorClass":"AuthenticationException","httpStatus":null,"severity":"error","filePath":"auth/src/main/java/org/apache/rocketmq/auth/authentication/chain/DefaultAuthenticationHandler.java","lineNumber":68,"sourceCode":"            throw new AuthenticationException(\"The authenticationMetadataProvider is not configured\");\n        }\n        if (StringUtils.isEmpty(context.getUsername())) {\n            throw new AuthenticationException(\"username cannot be null.\");\n        }\n        return this.authenticationMetadataProvider.getUser(context.getUsername());\n    }\n\n    protected void doAuthenticate(DefaultAuthenticationContext context, User user) {\n        if (user == null) {\n            throw new AuthenticationException(\"User:{} is not found.\", context.getUsername());\n        }\n        if (user.getUserStatus() == UserStatus.DISABLE) {\n            throw new AuthenticationException(\"User:{} is disabled.\", context.getUsername());\n        }\n        String signature = AclSigner.calSignature(context.getContent(), user.getPassword());\n        if (context.getSignature() == null\n            || !MessageDigest.isEqual(signature.getBytes(AclSigner.DEFAULT_CHARSET), context.getSignature().getBytes(AclSigner.DEFAULT_CHARSET))) {\n            throw new AuthenticationException(\"check signature failed.\");\n        }\n    }\n}\n","sourceCodeStart":50,"sourceCodeEnd":72,"githubUrl":"https://github.com/apache/rocketmq/blob/293f5885719fc4aa3619446a1900f58ccfcfdd29/auth/src/main/java/org/apache/rocketmq/auth/authentication/chain/DefaultAuthenticationHandler.java#L50-L72","documentation":"Signature verification failed: the server recomputed HMAC (AclSigner.calSignature over the datetime content with the stored user password) and it does not constant-time-match the client-supplied signature (or the client sent none). The credential was parsed and the user exists, so this specifically means secret mismatch or content/signature divergence.","triggerScenarios":"Client signs the datetime string with the wrong secret (password changed server-side), signs different content than the datetime metadata it sends, or produces the signature in a different encoding (base64 vs hex). Also thrown when the signature pair is missing entirely, making context.getSignature() null.","commonSituations":"Password rotated on the broker but client still uses the old secret; client clock skew where a different datetime string is signed than transmitted; custom clients not replicating AclSigner's HMAC-SHA256 + hex; a proxy rewriting the datetime header.","solutions":["Ensure the client secret matches the server-stored password for that user (re-enter or re-create the credential pair).","Sign exactly the same datetime string that is put into the datetime metadata, using HMAC-SHA256 then hex encoding, i.e. replicate AclSigner.calSignature semantics.","Verify no intermediary alters the datetime or authorization metadata between signing and arrival; synchronize clocks if the signed timestamp is generated twice."],"exampleFix":"// before: signs a freshly generated timestamp, then sends a different one\nString sig = sign(LocalDateTime.now() ...);\nmetadata.put(DATETIME, LocalDateTime.now() ...); // second now() differs\n\n// after\nString datetime = DateTimeFormatter.ofPattern(\"yyyyMMddHHmmss\").withZone(ZoneOffset.UTC).format(Instant.now());\nString sig = hexHmacSha256(datetime.getBytes(UTF_8), secretKey);\nmetadata.put(DATETIME, datetime);\nmetadata.put(AUTHORIZATION, \"RocketMQ Credential=\" + user + \",Signature=\" + sig);","handlingStrategy":"validation","validationCode":"// Reuse the exact datetime for metadata AND signature\nString datetime = DateTimeFormatter.ofPattern(\"yyyyMMddHHmmss\")\n        .withZone(ZoneOffset.UTC).format(Instant.now());\nString signature = hex(HmacSHA256(datetime.getBytes(StandardCharsets.UTF_8), secretKey));\nassert signature != null && !signature.isEmpty();","typeGuard":null,"tryCatchPattern":"catch (AuthenticationException e) { if message contains \"check signature failed\" -> re-verify secret against server record and clock sync; one retry with fresh datetime, then surface a credentials-config alert. }","preventionTips":["Single-source the datetime string: sign it, then send the same string","Rotate secrets atomically: update client config and server password in a coordinated window","NTP-sync hosts so datetime-based content stays stable"],"tags":["rocketmq","authentication","signature","hmac"],"backgroundTag":null,"analyzedSha":"293f5885719fc4aa3619446a1900f58ccfcfdd29","analyzedAt":"2026-08-14T11:50:13.822Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}