{"record":{"id":"65afb01bfbf02881","repo":"apereo/cas","slug":"secret-key-for-signing-is-not-defined-under","errorCode":null,"errorMessage":"Secret key for signing is not defined under [{}]. CAS will attempt to auto-generate the signing key","messagePattern":"Secret key for signing is not defined under \\[(.+?)\\]\\. CAS will attempt to auto-generate the signing key","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/cas-server-core-util-api/src/main/java/org/apereo/cas/util/cipher/BaseBinaryCipherExecutor.java","lineNumber":203,"sourceCode":"            } else if (encryptionSecretKey.length() != encryptionKeySize) {\n                LOGGER.warn(\"Secret key for encryption defined under [{}] is Base64 encoded but the size does not match the key size [{}].\",\n                    getEncryptionKeySetting(), encryptionKeySize);\n                genEncryptionKey = encryptionSecretKey.getBytes(StandardCharsets.UTF_8);\n            } else {\n                LOGGER.warn(\"Secret key for encryption defined under [{}] is not Base64 encoded. Clear the setting to regenerate (Recommended) or replace with\"\n                            + \" [{}].\", getEncryptionKeySetting(), EncodingUtils.encodeBase64(encryptionSecretKey));\n                genEncryptionKey = encryptionSecretKey.getBytes(StandardCharsets.UTF_8);\n            }\n        } else {\n            genEncryptionKey = EncodingUtils.decodeBase64(encryptionSecretKey);\n        }\n        this.encryptionSecretKey = genEncryptionKey;\n    }\n\n    private void ensureSigningKeyExists(final String signingSecretKey, final int signingKeySize) {\n        var signingKeyToUse = signingSecretKey;\n        if (StringUtils.isBlank(signingKeyToUse)) {\n            LOGGER.warn(\"Secret key for signing is not defined under [{}]. CAS will attempt to auto-generate the signing key\",\n                getSigningKeySetting());\n            signingKeyToUse = generateOctetJsonWebKeyOfSize(signingKeySize);\n            val prop = String.format(\"%s=%s\", getSigningKeySetting(), signingKeyToUse);\n            issueWarningToAddKeyToSettings(\"signing\", signingKeySize, signingKeyToUse, prop);\n        }\n        configureSigningKey(signingKeyToUse);\n    }\n    \n    //CHECKSTYLE:OFF\n    private static void issueWarningToAddKeyToSettings(final String keyType, final int encryptionKeySize, final String key, final String prop) {\n        LOGGER.warn(\"Generated {} key [{}] of size [{}]. The generated key MUST be added to CAS settings:\\n\\n\\t{}\\n\\n\",\n            keyType, key, encryptionKeySize, prop);\n    }\n    //CHECKSTYLE:ON\n    \n}\n","sourceCodeStart":185,"sourceCodeEnd":220,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/core/cas-server-core-util-api/src/main/java/org/apereo/cas/util/cipher/BaseBinaryCipherExecutor.java#L185-L220","documentation":"Warning from BaseBinaryCipherExecutor.ensureSigningKeyExists when the configured signing secret key is blank. CAS auto-generates an octet JWK of the configured size and warns that the generated signing key must be added to settings; regenerating at each startup invalidates previously signed values.","triggerScenarios":"Starting CAS with signing enabled (e.g. cas.ticket.crypto.signing.key empty) for a binary cipher executor; tokens/cookies signed in a previous run cannot be verified after restart because a new random key is generated.","commonSituations":"First-time setup without running the keygen step; multi-node CAS deployments where each node generates a different key, breaking signed-ticket validation across nodes.","solutions":["Generate a signing JWK of the required size and set the cas.*.crypto.signing.key property.","Copy the generated key from the log warning into your configuration so it survives restarts.","In clustered deployments, share the same signing key property across all nodes.","Disable signing if the feature does not require it instead of leaving the key blank."],"exampleFix":"// before\ncas.ticket.crypto.signing.enabled=true\n// after\ncas.ticket.crypto.signing.enabled=true\ncas.ticket.crypto.signing.key=eyJhbGciOiJIUzUxMiJ9...generated-oct-jwk...","handlingStrategy":"validation","validationCode":"String signingKey = casProperties.getTicket().getCrypto().getSigning().getKey();\nif (signingKey == null || signingKey.isBlank()) {\n    throw new IllegalStateException(\"Signing key missing: set cas.ticket.crypto.signing.key before startup\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate and persist signing JWKs before enabling crypto features.","Share identical signing keys across all cluster nodes.","Expect invalidation of previously signed artifacts after any key rotation."],"tags":["signing","jwk","missing-config"],"backgroundTag":"missing-config-value","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"}