{"record":{"id":"6abdbbcab6c4aee1","repo":"nathanmarz/storm","slug":"could-not-find-a-authutils-login-context-client-entry-in","errorCode":null,"errorMessage":"Could not find a '${AuthUtils.LOGIN_CONTEXT_CLIENT}' entry in this configuration: Client cannot start.","messagePattern":"Could not find a '(.+?)' entry in this configuration: Client cannot start\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"critical","filePath":"storm-core/src/jvm/backtype/storm/security/auth/digest/ClientCallbackHandler.java","lineNumber":59,"sourceCode":"    private static final Logger LOG = LoggerFactory.getLogger(ClientCallbackHandler.class);\n    private String _username = null;\n    private String _password = null;\n\n    /**\n     * Constructor based on a JAAS configuration\n     * \n     * For digest, you should have a pair of user name and password defined.\n     * \n     * @param configuration\n     * @throws IOException\n     */\n    public ClientCallbackHandler(Configuration configuration) throws IOException {\n        if (configuration == null) return;\n        AppConfigurationEntry configurationEntries[] = configuration.getAppConfigurationEntry(AuthUtils.LOGIN_CONTEXT_CLIENT);\n        if (configurationEntries == null) {\n            String errorMessage = \"Could not find a '\"+AuthUtils.LOGIN_CONTEXT_CLIENT\n                    + \"' entry in this configuration: Client cannot start.\";\n            throw new IOException(errorMessage);\n        }\n\n        _password = \"\";\n        for(AppConfigurationEntry entry: configurationEntries) {\n            if (entry.getOptions().get(USERNAME) != null) {\n                _username = (String)entry.getOptions().get(USERNAME);\n            }\n            if (entry.getOptions().get(PASSWORD) != null) {\n                _password = (String)entry.getOptions().get(PASSWORD);\n            }\n        }\n    }\n\n    /**\n     * This method is invoked by SASL for authentication challenges\n     * @param callbacks a collection of challenge callbacks \n     */\n    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/nathanmarz/storm/blob/cdb116e942666973bc4eaa0df098d5bab82739e7/storm-core/src/jvm/backtype/storm/security/auth/digest/ClientCallbackHandler.java#L41-L77","documentation":"ClientCallbackHandler implements JAAS callbacks for the DIGEST-MD5 client side of Storm's digest authentication. In its constructor it asks the java.security.Configuration for the JAAS entry named AuthUtils.LOGIN_CONTEXT_CLIENT (\"Client\"); if no such section exists in the supplied JAAS configuration it throws this IOException, because the client cannot obtain its username/password and must refuse to start.","triggerScenarios":"Constructing ClientCallbackHandler with a Configuration whose JAAS config file has no section titled 'Client' (configuration.getAppConfigurationEntry(AuthUtils.LOGIN_CONTEXT_CLIENT) returns null), e.g. the storm.yaml 'storm.thrift.transport' points to a digest-MD5 transport but the jaas.conf passed via -Djava.security.auth.login.config lacks a 'Client {' block, or the section is misspelled.","commonSituations":"Deploying a Storm cluster with DigestMd5 authentication where the operator only configured a 'Server' section in jaas.conf and forgot the 'Client' section; running a topology on a worker node without the JAAS file on the classpath/path so the default config has no 'Client' entry; typos in the section name (lowercase 'client' — JAAS section names are case-sensitive).","solutions":["Add a 'Client { ... }' section to the JAAS config file passed via -Djava.security.auth.login.config, e.g. Client { org.apache.storm.security.auth.digest.MD5DigestLoginModule required username=\"user\" password=\"pass\"; };","Verify the section name is exactly 'Client' with correct capitalization.","Ensure the JAAS file is actually loaded: check -Djava.security.auth.login.config JVM option (or STORM_JAAS_CONF / java.security.auth.login.config in worker childopts) points to the right file on every node.","If digest auth is not intended, switch storm.thrift.transport back to backtype.storm.security.auth.SimpleTransportPlugin so the digest ClientCallbackHandler is never used."],"exampleFix":"// jaas.conf before (missing client section)\nServer { com.myauth.MD5DigestLoginModule required user_admin=\"secret\"; };\n// after\nServer { com.myauth.MD5DigestLoginModule required user_admin=\"secret\"; };\nClient { com.myauth.MD5DigestLoginModule required username=\"admin\" password=\"secret\"; };","handlingStrategy":"validation","validationCode":"Configuration jaas = Configuration.getConfiguration();\nif (jaas == null || jaas.getAppConfigurationEntry(\"Client\") == null) {\n    throw new IllegalStateException(\"JAAS config is missing the required 'Client' section\");\n}","typeGuard":null,"tryCatchPattern":"try (InputStream in = new FileInputStream(jaasFile)) {\n    // parse/verify sections before installing as the login configuration\n} catch (IOException e) {\n    throw new IllegalStateException(\"Client JAAS section missing: \" + e.getMessage(), e);\n}","preventionTips":["Always ship a jaas.conf containing both 'Server' and 'Client' sections when digest auth is enabled","Validate jaas.conf sections as part of cluster provisioning (e.g. a smoke test that loads the Configuration and asserts both entries)","Set -Djava.security.auth.login.config explicitly in worker and master childopts so every JVM loads the same file","Remember JAAS section names are case-sensitive; lint for 'Client' exactly"],"tags":["jaas","authentication","configuration","storm"],"backgroundTag":"missing-required-config","analyzedSha":"cdb116e942666973bc4eaa0df098d5bab82739e7","analyzedAt":"2026-09-12T14:30:00.714Z","contentChangedAt":"2026-09-12T14:30:00.714Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}