apereo/cas · warning
Token encryption/signing is not enabled explicitly in the…
Error message
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.
What it means
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.
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.
Example fix
// before cas.authn.token.crypto.enabled=false cas.authn.token.crypto.signing.key=abc... cas.authn.token.crypto.encryption.key=xyz... // after cas.authn.token.crypto.enabled=true cas.authn.token.crypto.signing.key=abc... cas.authn.token.crypto.encryption.key=xyz...
Defensive patterns
Strategy: validation
Validate before calling
// fail fast on contradictory token crypto config
var crypto = casProperties.getAuthn().getToken().getCrypto();
if (!crypto.isEnabled() && (StringUtils.isNotBlank(crypto.getSigning().getKey())
|| StringUtils.isNotBlank(crypto.getEncryption().getKey())))
throw new IllegalStateException("Token crypto disabled but keys defined; set enabled=true or remove keys"); Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- No federation keys defined for entity
- Token has an invalid issuer that does not match
- Unable to validate JWT signature
- Interrupt webflow cookie encryption/signing is not enabled…
- Ticket registry encryption/signing for
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/ed3733057dc32b29.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-token-core/src/main/java/org/apereo/cas/config/TokenCoreConfiguration.java:85
final CentralAuthenticationService centralAuthenticationService) {
return new InternalTicketValidator(centralAuthenticationService,
webApplicationServiceFactory, authenticationAttributeReleasePolicy, servicesManager);
}
}
@Configuration(value = "TokenCoreJwtConfiguration", proxyBeanMethods = false)
@EnableConfigurationProperties(CasConfigurationProperties.class)
static class TokenCoreJwtConfiguration {
@Bean
@RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
@ConditionalOnMissingBean(name = "tokenCipherExecutor")
public CipherExecutor tokenCipherExecutor(final CasConfigurationProperties casProperties) {
val crypto = casProperties.getAuthn().getToken().getCrypto();
val enabled = FunctionUtils.doIf(!crypto.isEnabled()
&& StringUtils.isNotBlank(crypto.getEncryption().getKey())
&& StringUtils.isNotBlank(crypto.getSigning().getKey()),
() -> {
LOGGER.warn("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.");
return Boolean.TRUE;
}, crypto::isEnabled).get();
if (enabled) {
return CipherExecutorUtils.newStringCipherExecutor(crypto, JwtTicketCipherExecutor.class);
}
LOGGER.info("Token cookie encryption/signing is turned off. This "
+ "MAY NOT be safe in a production environment. Consider using other choices to handle encryption, "
+ "signing and verification of generated tokens.");
return CipherExecutor.noOp();
}
@RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
@Bean
@ConditionalOnMissingBean(name = JwtBuilder.TICKET_JWT_BUILDER_BEAN_NAME)
public JwtBuilder tokenTicketJwtBuilder(
@Qualifier(WebApplicationService.BEAN_NAME_FACTORY)
final ServiceFactory<WebApplicationService> webApplicationServiceFactory,View on GitHub (pinned to e7288fc434)