apereo/cas · info

Encryption/Signing is not enabled explicitly in the…

Error message

Encryption/Signing is not enabled explicitly in the configuration for cookie [{}], yet signing/encryption keys are defined for operations. CAS will proceed to enable the cookie encryption/signing functionality.

What it means

CAS detects an inconsistent cookie crypto configuration: crypto.enabled is false, but both a signing key and an encryption key are supplied. Rather than silently ignoring the keys, CAS warns and enables encryption/signing for the SAML IdP distributed-session cookie.

Solutions

  1. If you want crypto ON: set cas.authn.saml-idp.session-replication.cookie.crypto.enabled=true (behavior already forced anyway).
  2. If you want crypto OFF: remove crypto.signing.key and crypto.encryption.key from configuration.
  3. Ensure all CAS nodes use identical keys, or cluster session replication breaks on decryption.
  4. Note the forced-enable in deployment docs so future operators don't get surprised.

Example fix

// before
cas.authn.saml-idp.session-replication.cookie.crypto.enabled=false
cas.authn.saml-idp.session-replication.cookie.crypto.signing.key=abc...
cas.authn.saml-idp.session-replication.cookie.crypto.encryption.key=xyz...
// after (crypto intentionally off)
cas.authn.saml-idp.session-replication.cookie.crypto.enabled=false
// keys removed
Defensive patterns

Strategy: validation

Validate before calling

var crypto = props.getAuthn().getSamlIdp().getCore().getSessionReplication().getCookie().getCrypto();
boolean explicit = crypto.isEnabled();
boolean hasKeys = isNotBlank(crypto.getSigning().getKey()) && isNotBlank(crypto.getEncryption().getKey());
if (!explicit && hasKeys) {
    LOGGER.warn("Crypto disabled but keys present — remove keys or enable crypto");
}

Prevention

When it happens

Trigger: cas.authn.saml-idp.session-replication.cookie.crypto.enabled=false while crypto.signing.key and crypto.encryption.key are both set when building samlIdPDistributedSessionCookieCipherExecutor.

Common situations: Operator disabled crypto intending to turn it off but left generated keys in config; copied a template with keys present; migration from an older CAS version where keys existed by default.

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


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/0ef9e4e280127c78. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-saml-idp/src/main/java/org/apereo/cas/config/SamlIdPEndpointsConfiguration.java:488

                        Strings.CI.prependIfMissing(SamlIdPConstants.BASE_ENDPOINT_SAML2, "/"));
                }
            };
        }

        @ConditionalOnMissingBean(name = "samlIdPDistributedSessionCookieCipherExecutor")
        @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
        @Bean
        @Deprecated(since = "7.3.0", forRemoval = true)
        public CipherExecutor samlIdPDistributedSessionCookieCipherExecutor(final CasConfigurationProperties casProperties) {
            val type = casProperties.getAuthn().getSamlIdp().getCore().getSessionStorageType();
            return FunctionUtils.doIf(type.isTicketRegistry(),
                () -> {
                    val cookie = casProperties.getAuthn().getSamlIdp().getCore().getSessionReplication().getCookie();
                    val crypto = cookie.getCrypto();
                    var enabled = crypto.isEnabled();
                    if (!enabled && StringUtils.isNotBlank(crypto.getEncryption().getKey())
                        && StringUtils.isNotBlank(crypto.getSigning().getKey())) {
                        LOGGER.warn("Encryption/Signing is not enabled explicitly in the configuration for cookie [{}], yet signing/encryption keys "
                                    + "are defined for operations. CAS will proceed to enable the cookie encryption/signing functionality.", cookie.getName());
                        enabled = true;
                    }
                    return enabled
                        ? CipherExecutorUtils.newStringCipherExecutor(crypto, SamlIdPDistributedSessionCookieCipherExecutor.class)
                        : CipherExecutor.noOp();
                },
                CipherExecutor::noOp).get();
        }

        @ConditionalOnMissingBean(name = "samlIdPDistributedSessionCookieGenerator")
        @Bean
        @RefreshScope(proxyMode = ScopedProxyMode.DEFAULT)
        @Deprecated(since = "7.3.0", forRemoval = true)
        public CasCookieBuilder samlIdPDistributedSessionCookieGenerator(
            @Qualifier(TenantExtractor.BEAN_NAME)
            final TenantExtractor tenantExtractor,
            @Qualifier(GeoLocationService.BEAN_NAME)

View on GitHub (pinned to e7288fc434)