apereo/cas · warning
Secret key for encryption defined under
Error message
Secret key for encryption defined under [{}] is not Base64 encoded. Clear the setting to regenerate (Recommended) or replace with [{}]. What it means
Warning from BaseBinaryCipherExecutor.ensureEncryptionKeyExists when the configured encryption key is neither validly sized Base64 nor missing: it is not Base64 at all (or the length branch did not match). CAS uses the raw UTF-8 bytes of the string as the AES key and suggests clearing the setting so a proper key is regenerated.
Solutions
- Clear the property and restart so CAS auto-generates a proper Base64 key (recommended by the message), then persist the printed key.
- Replace the value with the Base64 encoding of the existing secret if you must keep the same key material.
- Validate the value is Base64 (java.util.Base64.getDecoder().decode throws on invalid input) before configuring it.
Example fix
// before cas.ticket.crypto.encryption.key=my-secret-password // after cas.ticket.crypto.encryption.key=bXktc2VjcmV0LXBhc3N3b3Jk
Defensive patterns
Strategy: validation
Validate before calling
try {
java.util.Base64.getDecoder().decode(configuredKey);
} catch (IllegalArgumentException e) {
throw new IllegalStateException("Encryption key is not Base64 encoded: re-generate or Base64-encode it");
} Prevention
- Always paste the exact 'property=value' line CAS prints when generating keys.
- Do not type human-readable secrets as cipher keys.
- Strip whitespace/quotes when copying keys into properties files.
- Prefer clearing the setting and letting CAS regenerate (then persist) over hand-rolling keys.
When it happens
Trigger: Setting cas.*.crypto.encryption.key to a plain-text string (not Base64) whose length also equals the key size — e.g. a 16-character ASCII password used directly as the encryption key.
Common situations: Operators typing a human-readable secret instead of a generated Base64 key; keys copied from another system that hex- or URL-encodes rather than Base64; whitespace or prefix corruption that invalidates Base64 decoding.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Secret key for encryption defined under
- Unable to use 'none' as introspection encryption algorithm
- Unable to use 'none' as user-info encryption algorithm
- Service with client id is configured to encrypt tokens, yet…
- Unable to use 'none' as ID token encryption algorithm
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/06e701e404270583.
Report an issue: GitHub.
Appendix: source
Thrown at core/cas-server-core-util-api/src/main/java/org/apereo/cas/util/cipher/BaseBinaryCipherExecutor.java:190
keyGenerator.init(encryptionKeySize);
val secretKey = keyGenerator.generateKey();
genEncryptionKey = secretKey.getEncoded();
val encodedKey = EncodingUtils.encodeBase64(genEncryptionKey);
val prop = String.format("%s=%s", getEncryptionKeySetting(), encodedKey);
issueWarningToAddKeyToSettings("encryption", encryptionKeySize, encodedKey, prop);
}
} else if (encryptionKeySize <= MINIMUM_ENCRYPTION_KEY_LENGTH) {
val base64 = EncodingUtils.isBase64(encryptionSecretKey);
val key = base64 ? EncodingUtils.decodeBase64(encryptionSecretKey) : ArrayUtils.EMPTY_BYTE_ARRAY;
if (base64 && key.length == encryptionKeySize) {
LOGGER.trace("Secret key for encryption defined under [{}] is Base64 encoded.", getEncryptionKeySetting());
genEncryptionKey = key;
} else if (encryptionSecretKey.length() != encryptionKeySize) {
LOGGER.warn("Secret key for encryption defined under [{}] is Base64 encoded but the size does not match the key size [{}].",
getEncryptionKeySetting(), encryptionKeySize);
genEncryptionKey = encryptionSecretKey.getBytes(StandardCharsets.UTF_8);
} else {
LOGGER.warn("Secret key for encryption defined under [{}] is not Base64 encoded. Clear the setting to regenerate (Recommended) or replace with"
+ " [{}].", getEncryptionKeySetting(), EncodingUtils.encodeBase64(encryptionSecretKey));
genEncryptionKey = encryptionSecretKey.getBytes(StandardCharsets.UTF_8);
}
} else {
genEncryptionKey = EncodingUtils.decodeBase64(encryptionSecretKey);
}
this.encryptionSecretKey = genEncryptionKey;
}
private void ensureSigningKeyExists(final String signingSecretKey, final int signingKeySize) {
var signingKeyToUse = signingSecretKey;
if (StringUtils.isBlank(signingKeyToUse)) {
LOGGER.warn("Secret key for signing is not defined under [{}]. CAS will attempt to auto-generate the signing key",
getSigningKeySetting());
signingKeyToUse = generateOctetJsonWebKeyOfSize(signingKeySize);
val prop = String.format("%s=%s", getSigningKeySetting(), signingKeyToUse);
issueWarningToAddKeyToSettings("signing", signingKeySize, signingKeyToUse, prop);
}View on GitHub (pinned to e7288fc434)