{"record":{"id":"e12322d8c75e89b0","repo":"apache/pulsar","slug":"no-secret-key-was-provided-for-token-authenticatio","errorCode":null,"errorMessage":"No secret key was provided for token authentication","messagePattern":"No secret key was provided for token authentication","errorType":"validation","errorClass":"IOException","httpStatus":null,"severity":"critical","filePath":"pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderToken.java","lineNumber":300,"sourceCode":"            Optional<String> firstEntry = list.stream().findFirst().map(Object::toString);\n            return firstEntry.orElse(null);\n        }\n    }\n\n    /**\n     * Try to get the validation key for tokens from several possible config options.\n     */\n    private Key getValidationKey(ServiceConfiguration conf) throws IOException {\n        String tokenSecretKey = (String) conf.getProperty(confTokenSecretKeySettingName);\n        String tokenPublicKey = (String) conf.getProperty(confTokenPublicKeySettingName);\n        if (StringUtils.isNotBlank(tokenSecretKey)) {\n            final byte[] validationKey = AuthTokenUtils.readKeyFromUrl(tokenSecretKey);\n            return AuthTokenUtils.decodeSecretKey(validationKey);\n        } else if (StringUtils.isNotBlank(tokenPublicKey)) {\n            final byte[] validationKey = AuthTokenUtils.readKeyFromUrl(tokenPublicKey);\n            return AuthTokenUtils.decodePublicKey(validationKey, publicKeyAlg);\n        } else {\n            throw new IOException(\"No secret key was provided for token authentication\");\n        }\n    }\n\n    private String getTokenRoleClaim(ServiceConfiguration conf) throws IOException {\n        String tokenAuthClaim = (String) conf.getProperty(confTokenAuthClaimSettingName);\n        if (StringUtils.isNotBlank(tokenAuthClaim)) {\n            return tokenAuthClaim;\n        } else {\n            return Claims.SUBJECT;\n        }\n    }\n\n    private SignatureAlgorithm getPublicKeyAlgType(ServiceConfiguration conf) throws IllegalArgumentException {\n        String tokenPublicAlg = (String) conf.getProperty(confTokenPublicAlgSettingName);\n        if (StringUtils.isNotBlank(tokenPublicAlg)) {\n            try {\n                return SignatureAlgorithm.forName(tokenPublicAlg);\n            } catch (SignatureException ex) {","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-broker-common/src/main/java/org/apache/pulsar/broker/authentication/AuthenticationProviderToken.java#L282-L318","documentation":"During provider initialization, getValidationKey looks for a token validation key in the configuration: first tokenSecretKey (symmetric), then tokenPublicKey (asymmetric). If neither property is set (blank), it throws this IOException because the provider has no key with which to verify token signatures.","triggerScenarios":"The broker/client configuration sets authenticationProvider=org.apache.pulsar.broker.authentication.AuthenticationProviderToken (or the client sets the token auth provider) but neither tokenSecretKey nor tokenPublicKey is provided at initialize time.","commonSituations":"Enabling token authentication without supplying the secret key file/URL; key property name misspelled in conf; key file path exists but the property value is empty after env-var substitution; copying a config template that left the key fields blank.","solutions":["Set tokenSecretKey in broker.conf/standalone.conf to the base64-encoded secret key (or data: URL) used to sign tokens, e.g. tokenSecretKey=data:;base64,<key>.","For asymmetric setups, set tokenPublicKey (and tokenPublicKeyAlg for non-RS256 algorithms) instead.","Verify the property names are spelled correctly and the values are non-blank after config loading.","Generate a key if none exists: bin/pulsar tokens create-secret-key --output my-secret.key --base64."],"exampleFix":"// before (broker.conf)\n# tokenSecretKey=\n// after\ntokenSecretKey=data:;base64,base64EncodedSecretKeyHere","handlingStrategy":"validation","validationCode":"// Fail fast at deploy time before starting the broker:\nString secretKey = (String) conf.getProperty(\"tokenSecretKey\");\nString publicKey = (String) conf.getProperty(\"tokenPublicKey\");\nif ((secretKey == null || secretKey.isBlank()) && (publicKey == null || publicKey.isBlank())) {\n    throw new IllegalStateException(\n        \"Token auth requires either tokenSecretKey or tokenPublicKey in the configuration\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    authenticationProvider.initialize(conf);\n} catch (IOException e) {\n    if (e.getMessage().contains(\"No secret key was provided\")) {\n        throw new IllegalStateException(\"Set tokenSecretKey or tokenPublicKey in broker.conf before enabling token auth\", e);\n    }\n    throw e;\n}","preventionTips":["Generate and provision the key (bin/pulsar tokens create-secret-key) as part of deployment before enabling token auth.","Keep tokenSecretKey/tokenPublicKey in a secrets store and template them into the conf, verifying the value is non-empty after substitution.","Validate broker.conf in CI with a config lint that requires the key when the token auth provider is selected.","Document that exactly one of tokenSecretKey / tokenPublicKey must be set."],"tags":["configuration","authentication","missing-key","startup"],"backgroundTag":"missing-secret-key-config","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}