{"record":{"id":"ed3733057dc32b29","repo":"apereo/cas","slug":"token-encryption-signing-is-not-enabled-explicitly","errorCode":null,"errorMessage":"Token encryption/signing is not enabled explicitly in the configuration, yet signing/encryption keys are defined for operations. CAS will proceed to enable the token encryption/signing functionality.","messagePattern":"Token encryption/signing is not enabled explicitly in the configuration, yet signing/encryption keys are defined for operations\\. CAS will proceed to enable the token encryption/signing functionality\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"support/cas-server-support-token-core/src/main/java/org/apereo/cas/config/TokenCoreConfiguration.java","lineNumber":85,"sourceCode":"            final CentralAuthenticationService centralAuthenticationService) {\n            return new InternalTicketValidator(centralAuthenticationService,\n                webApplicationServiceFactory, authenticationAttributeReleasePolicy, servicesManager);\n        }\n    }\n\n    @Configuration(value = \"TokenCoreJwtConfiguration\", proxyBeanMethods = false)\n    @EnableConfigurationProperties(CasConfigurationProperties.class)\n    static class TokenCoreJwtConfiguration {\n        @Bean\n        @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)\n        @ConditionalOnMissingBean(name = \"tokenCipherExecutor\")\n        public CipherExecutor tokenCipherExecutor(final CasConfigurationProperties casProperties) {\n            val crypto = casProperties.getAuthn().getToken().getCrypto();\n            val enabled = FunctionUtils.doIf(!crypto.isEnabled()\n                    && StringUtils.isNotBlank(crypto.getEncryption().getKey())\n                    && StringUtils.isNotBlank(crypto.getSigning().getKey()),\n                () -> {\n                    LOGGER.warn(\"Token encryption/signing is not enabled explicitly in the configuration, yet signing/encryption keys \"\n                        + \"are defined for operations. CAS will proceed to enable the token encryption/signing functionality.\");\n                    return Boolean.TRUE;\n                }, crypto::isEnabled).get();\n            if (enabled) {\n                return CipherExecutorUtils.newStringCipherExecutor(crypto, JwtTicketCipherExecutor.class);\n            }\n            LOGGER.info(\"Token cookie encryption/signing is turned off. This \"\n                + \"MAY NOT be safe in a production environment. Consider using other choices to handle encryption, \"\n                + \"signing and verification of generated tokens.\");\n            return CipherExecutor.noOp();\n        }\n\n        @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)\n        @Bean\n        @ConditionalOnMissingBean(name = JwtBuilder.TICKET_JWT_BUILDER_BEAN_NAME)\n        public JwtBuilder tokenTicketJwtBuilder(\n            @Qualifier(WebApplicationService.BEAN_NAME_FACTORY)\n            final ServiceFactory<WebApplicationService> webApplicationServiceFactory,","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-token-core/src/main/java/org/apereo/cas/config/TokenCoreConfiguration.java#L67-L103","documentation":"TokenCoreConfiguration.tokenCipherExecutor decides whether token encryption/signing is active. Because crypto.isEnabled() is false but both signing and encryption keys are provided, CAS infers intent, logs this warning, and enables the cipher anyway, building a JwtTicketCipherExecutor from the crypto settings. Tokens will be signed/encrypted despite the explicit enabled=false.","triggerScenarios":"Configuration sets cas.authn.token.crypto.enabled=false while also defining non-blank cas.authn.token.crypto.signing.key and cas.authn.token.crypto.encryption.key.","commonSituations":"Operator disabled crypto expecting keys to be ignored, but leftover keys silently re-enable it; copy-pasted crypto block from another module with enabled=false; migration between environments leaving stale keys in config.","solutions":["Set cas.authn.token.crypto.enabled=true to make the effective behavior explicit and silence the warning.","Remove the signing/encryption key values if token crypto is genuinely unwanted.","Ensure keys are stored securely (e.g. via JCEK keystore) rather than inline where possible.","Restart and verify the JwtTicketCipherExecutor bean is created as intended."],"exampleFix":"// before\ncas.authn.token.crypto.enabled=false\ncas.authn.token.crypto.signing.key=abc...\ncas.authn.token.crypto.encryption.key=xyz...\n// after\ncas.authn.token.crypto.enabled=true\ncas.authn.token.crypto.signing.key=abc...\ncas.authn.token.crypto.encryption.key=xyz...","handlingStrategy":"validation","validationCode":"// fail fast on contradictory token crypto config\nvar crypto = casProperties.getAuthn().getToken().getCrypto();\nif (!crypto.isEnabled() && (StringUtils.isNotBlank(crypto.getSigning().getKey())\n        || StringUtils.isNotBlank(crypto.getEncryption().getKey())))\n    throw new IllegalStateException(\"Token crypto disabled but keys defined; set enabled=true or remove keys\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always set crypto.enabled explicitly; never rely on key presence inference.","Remove stale crypto blocks when copying config between modules.","Grep environment config for orphaned keys after enabling/disabling crypto."],"tags":["configuration","crypto","tokens","jwt"],"backgroundTag":"conflicting-config-options","analyzedSha":"e7288fc434b4f4505b8452e1a57e8fb3111bb863","analyzedAt":"2026-09-08T15:39:16.015Z","contentChangedAt":"2026-09-08T15:39:16.015Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}