{"record":{"id":"83e28e051a492155","repo":"apache/pulsar","slug":"unrecognized-sasl-gssapi-client-callback","errorCode":null,"errorMessage":"Unrecognized SASL GSSAPI Client Callback.","messagePattern":"Unrecognized SASL GSSAPI Client Callback\\.","errorType":"exception","errorClass":"UnsupportedCallbackException","httpStatus":null,"severity":"warning","filePath":"pulsar-client-auth-sasl/src/main/java/org/apache/pulsar/client/impl/auth/PulsarSaslClient.java","lineNumber":128,"sourceCode":"            }\n        } catch (Exception e) {\n            log.error().exception(e.getCause()).log(\"SASL error\");\n            throw new AuthenticationException(\"SASL/JAAS error\" + e.getCause());\n        }\n    }\n\n    public boolean hasInitialResponse() {\n        return saslClient.hasInitialResponse();\n    }\n\n    static class ClientCallbackHandler implements CallbackHandler {\n        @Override\n        public void handle(Callback[] callbacks) throws UnsupportedCallbackException {\n            for (Callback callback : callbacks) {\n                if (callback instanceof AuthorizeCallback) {\n                    handleAuthorizeCallback((AuthorizeCallback) callback);\n                } else {\n                    throw new UnsupportedCallbackException(callback, \"Unrecognized SASL GSSAPI Client Callback.\");\n                }\n            }\n        }\n\n        private void handleAuthorizeCallback(AuthorizeCallback ac) {\n            String authid = ac.getAuthenticationID();\n            String authzid = ac.getAuthorizationID();\n            if (authid.equals(authzid)) {\n                ac.setAuthorized(true);\n            } else {\n                ac.setAuthorized(false);\n            }\n            if (ac.isAuthorized()) {\n                ac.setAuthorizedID(authzid);\n            }\n            log.info().attr(\"authenticationID\", authid).attr(\"authorizationID\", authzid)\n                    .log(\"Successfully authenticated\");\n        }","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-auth-sasl/src/main/java/org/apache/pulsar/client/impl/auth/PulsarSaslClient.java#L110-L146","documentation":"PulsarSaslClient's ClientCallbackHandler only understands javax.security.sasl.AuthorizeCallback. When the JVM's SASL/GSSAPI implementation hands it any other Callback type during client creation or evaluation, it throws UnsupportedCallbackException with this message. It indicates a callback type the client handler does not support was requested.","triggerScenarios":"A SASL mechanism or provider (e.g. a non-GSSAPI mechanism, or a provider variant) invoking the handler with callbacks like NameCallback, PasswordCallback, or RealmCallback instead of only AuthorizeCallback; plugging this handler into a different SASL mechanism than GSSAPI.","commonSituations":"Using the Pulsar SASL client code with a mechanism other than GSSAPI (e.g. SCRAM/DIGEST-MD5 via shared code); a JVM SASL provider that requests extra callbacks; custom provider implementations with non-standard callback requirements.","solutions":["Only use this ClientCallbackHandler with the GSSAPI mechanism — GSSAPI obtains credentials from the JAAS Subject and should only ask AuthorizeCallback","If a different mechanism is required, extend the handler with instanceof branches for the needed callbacks (NameCallback, PasswordCallback, etc.)","Verify the configured SASL mechanism string is \"GSSAPI\" (as in PulsarSaslClient's mechs array) and no other provider is picking up the creation","Check the JVM's SASL provider order so the standard GSSAPI provider handles the mechanism rather than a custom one"],"exampleFix":"// before\npublic void handle(Callback[] callbacks) throws UnsupportedCallbackException {\n    for (Callback callback : callbacks) {\n        if (callback instanceof AuthorizeCallback) {\n            handleAuthorizeCallback((AuthorizeCallback) callback);\n        } else {\n            throw new UnsupportedCallbackException(callback, \"Unrecognized SASL GSSAPI Client Callback.\");\n        }\n    }\n}\n\n// after\npublic void handle(Callback[] callbacks) throws UnsupportedCallbackException {\n    for (Callback callback : callbacks) {\n        if (callback instanceof AuthorizeCallback) {\n            handleAuthorizeCallback((AuthorizeCallback) callback);\n        } else if (callback instanceof NameCallback) {\n            ((NameCallback) callback).setName(clientPrincipalName);\n        } else {\n            throw new UnsupportedCallbackException(callback, \"Unrecognized SASL GSSAPI Client Callback.\");\n        }\n    }\n}","handlingStrategy":"try-catch","validationCode":"// ensure GSSAPI is the negotiated mechanism so only AuthorizeCallback is delivered\nString[] mechs = {\"GSSAPI\"};\nif (!java.util.Arrays.asList(javax.security.sasl.Sasl.getSaslClientFactories().stream()\n        .flatMap(f -> java.util.Arrays.stream(f.getMechanismNames(new java.util.HashMap<>())))\n        .toArray(String[]::new)).contains(\"GSSAPI\")) {\n    throw new IllegalStateException(\"GSSAPI mechanism not available; handler only supports AuthorizeCallback\");\n}","typeGuard":"boolean isSupportedCallback(javax.security.auth.callback.Callback c) {\n    return c instanceof javax.security.sasl.AuthorizeCallback;\n}","tryCatchPattern":"try {\n    saslClient.evaluateChallenge(token);\n} catch (javax.security.sasl.SaslException e) {\n    if (e.getCause() instanceof javax.security.auth.callback.UnsupportedCallbackException) {\n        log.error(\"ClientCallbackHandler received an unsupported callback: {}\",\n            ((javax.security.auth.callback.UnsupportedCallbackException) e.getCause()).getCallback().getClass());\n        // switch mechanism to GSSAPI or extend the handler\n    }\n}","preventionTips":["Restrict this CallbackHandler to the GSSAPI mechanism only","Inspect JVM SASL provider order so GSSAPI requests come from the standard provider","If supporting more mechanisms, add instanceof branches for NameCallback/PasswordCallback/RealmCallback","Log the callback class name before throwing to speed up diagnosis"],"tags":["sasl","kerberos","callback","unsupported-operation"],"backgroundTag":"unsupported-sasl-callback","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"}