{"record":{"id":"f804f423b31194b6","repo":"apache/pulsar","slug":"invalid-authentication-token","errorCode":null,"errorMessage":"Invalid authentication token","messagePattern":"Invalid authentication token","errorType":"exception","errorClass":"AuthenticationException","httpStatus":null,"severity":"error","filePath":"pulsar-broker-auth-sasl/src/main/java/org/apache/pulsar/broker/authentication/SaslRoleToken.java","lineNumber":217,"sourceCode":"\n    /**\n     * Splits the string representation of a token into attributes pairs.\n     *\n     * @param tokenStr string representation of a token.\n     *\n     * @return a map with the attribute pairs of the token.\n     *\n     * @throws AuthenticationException thrown if the string representation of the token could not be broken into\n     * attribute pairs.\n     */\n    private static Map<String, String> split(String tokenStr) throws AuthenticationException {\n        Map<String, String> map = new HashMap<String, String>();\n        StringTokenizer st = new StringTokenizer(tokenStr, ATTR_SEPARATOR);\n        while (st.hasMoreTokens()) {\n            String part = st.nextToken();\n            int separator = part.indexOf('=');\n            if (separator == -1) {\n                throw new AuthenticationException(\"Invalid authentication token\");\n            }\n            String key = part.substring(0, separator);\n            String value = part.substring(separator + 1);\n            map.put(key, value);\n        }\n        return map;\n    }\n\n}\n","sourceCodeStart":199,"sourceCodeEnd":227,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker-auth-sasl/src/main/java/org/apache/pulsar/broker/authentication/SaslRoleToken.java#L199-L227","documentation":"javax.naming.AuthenticationException thrown by SaslRoleToken.split when a '&'-separated segment of the token string contains no '=' character, meaning it is neither a key=value attribute pair nor parseable. split tokenizes on '&' and requires each part to have at least one '='; a bare fragment (e.g. \"garbage\" between '&' separators, or a value that itself contained '&' from an unvalidated token) triggers this before the attribute-set check in parse.","triggerScenarios":"Calling SaslRoleToken.parse(tokenStr) where any '&'-delimited segment lacks '=' — e.g. \"u=bob&&i=1&e=9\" (empty segment), \"u=bob&i=1&e=9&extra\" (trailing junk), or a token whose attribute value illegally contained '&' (bypassing checkForIllegalArgument) so the value split into fragments.","commonSituations":"Manually built or concatenated token strings; token values that legitimately contain '&' because producers skipped SaslRoleToken validation; corrupted/stored tokens with stray '&' or empty sections; clients sending arbitrary strings to the token endpoint probing the parser.","solutions":["Regenerate the token with SaslRoleToken/toString() so it contains only valid u=, i=, e= segments separated by '&', with no empty or '='-less segments","Reject or sanitize any user-supplied component containing '&' before constructing the token (enforce checkForIllegalArgument on all inputs)","Validate token shape before parsing: each '&'-separated part must contain '=' (regex like ^([^&=]+=[^&]*&)*[^&=]+=[^&]*$), else re-authenticate","Catch AuthenticationException in the caller and return a clear invalid-token error so the client fetches a fresh token"],"exampleFix":"// before\nSaslRoleToken token = SaslRoleToken.parse(tokenStr); // tokenStr may contain \"u=bob&&i=1\"\n// after\nif (Arrays.stream(tokenStr.split(\"&\")).anyMatch(part -> !part.contains(\"=\"))) {\n    throw new AuthenticationException(\"Invalid authentication token\");\n}\nSaslRoleToken token = SaslRoleToken.parse(tokenStr);","handlingStrategy":"validation","validationCode":"// run before SaslRoleToken.parse(tokenStr)\nstatic boolean everySegmentHasKey(String tokenStr) {\n    if (tokenStr == null) return false;\n    for (String part : tokenStr.split(\"&\", -1)) {\n        if (!part.contains(\"=\")) return false; // empty or bare fragment\n    }\n    return true;\n}","typeGuard":null,"tryCatchPattern":"try {\n    SaslRoleToken token = SaslRoleToken.parse(tokenStr);\n} catch (AuthenticationException e) {\n    if (e.getMessage().equals(\"Invalid authentication token\")) {\n        throw new AuthenticationException(\"Malformed token: a segment lacks '='; client must re-authenticate\");\n    }\n    throw e;\n}","preventionTips":["Never allow '&' inside token attribute values — enforce the checkForIllegalArgument rule on all inputs","Reject tokens containing empty segments (consecutive '&') before parsing","Build tokens exclusively via the SaslRoleToken constructors, never by string concatenation","Treat parse failures as client errors and force a fresh authentication rather than retrying with the same token"],"tags":["sasl","token","parsing","authentication"],"backgroundTag":"malformed-auth-token","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}