{"record":{"id":"d19387bcaacca2ff","repo":"apereo/cas","slug":"unable-to-identify-the-public-key-from-the-signing","errorCode":null,"errorMessage":"Unable to identify the public key from the signing credential","messagePattern":"Unable to identify the public key from the signing credential","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"support/cas-server-support-saml-idp-web/src/main/java/org/apereo/cas/support/saml/web/idp/profile/builders/enc/DefaultSamlIdPObjectSigner.java","lineNumber":387,"sourceCode":"        }\n        return config;\n    }\n\n    protected @Nullable AbstractCredential getResolvedSigningCredential(final Credential credential,\n                                                                        final PrivateKey privateKey,\n                                                                        final SamlRegisteredService service) {\n        try {\n            val samlIdp = casProperties.getAuthn().getSamlIdp();\n            val credType = SamlIdPResponseProperties.SignatureCredentialTypes.valueOf(\n                StringUtils.defaultIfBlank(service.getSigningCredentialType(),\n                    samlIdp.getResponse().getCredentialType().name()).toUpperCase(Locale.ENGLISH));\n            LOGGER.trace(\"Requested credential type [{}] is found for service [{}]\", credType, service.getName());\n\n            return switch (credType) {\n                case BASIC -> {\n                    LOGGER.debug(\"Building credential signing key [{}] based on requested credential type\", credType);\n                    if (credential.getPublicKey() == null) {\n                        throw new IllegalArgumentException(\"Unable to identify the public key from the signing credential\");\n                    }\n                    yield finalizeSigningCredential(new BasicCredential(credential.getPublicKey(), privateKey), credential);\n                }\n                case X509 -> {\n                    if (credential instanceof final BasicX509Credential value) {\n                        val certificate = value.getEntityCertificate();\n                        LOGGER.debug(\"Locating signature signing certificate from credential [{}]\", CertUtils.toString(certificate));\n                        yield finalizeSigningCredential(new BasicX509Credential(certificate, privateKey), credential);\n                    }\n                    val signingCert = samlIdPMetadataLocator.resolveSigningCertificate(Optional.of(service));\n                    LOGGER.debug(\"Locating signature signing certificate file from [{}]\", signingCert);\n                    val certificate = SamlUtils.readCertificate(signingCert);\n                    yield finalizeSigningCredential(new BasicX509Credential(certificate, privateKey), credential);\n                }\n            };\n        } catch (final Throwable e) {\n            LoggingUtils.error(LOGGER, e);\n        }","sourceCodeStart":369,"sourceCodeEnd":405,"githubUrl":"https://github.com/apereo/cas/blob/e7288fc434b4f4505b8452e1a57e8fb3111bb863/support/cas-server-support-saml-idp-web/src/main/java/org/apereo/cas/support/saml/web/idp/profile/builders/enc/DefaultSamlIdPObjectSigner.java#L369-L405","documentation":"After resolving a candidate signing credential, the signer builds the appropriate OpenSAML credential type. For BASIC credential type the code requires credential.getPublicKey() to be non-null to construct a BasicCredential; a credential without a public key (e.g. secret-key based or failed keystore load artifact) cannot be used and IllegalArgumentException is thrown.","triggerScenarios":"getResolvedSigningCredential with credential type BASIC where the resolved credential's getPublicKey() returns null — e.g. the configured credential is a symmetric/secret key or was loaded incompletely from the keystore.","commonSituations":"Configured cas.authn.saml.idp signing credential is actually a secret key credential while the code path requests BASIC/X509 public-key credential; keystore entry loaded without certificate; misconfigured credential type in service settings.","solutions":["Use an X509 certificate-based signing credential (keystore entry with private key + certificate chain).","Check the requested credential type (getSigningCredentialType on service/config) and set it to X509.","Inspect why getPublicKey() is null: the credential source loaded only a private or secret key.","Regenerate the keystore entry so it includes the certificate."],"exampleFix":"// before\nservice.setSigningCredentialType(BasicCredentialCredentialTypes.BASIC);\n// after\nservice.setSigningCredentialType(BasicCredentialCredentialTypes.X509);","handlingStrategy":"validation","validationCode":"val cred = resolveSigningCredential(service);\nif (cred == null || cred.getPublicKey() == null) throw new IllegalStateException(\"Configure an X509 certificate-based signing credential\");","typeGuard":"boolean hasUsableSigningKey(Credential c) { return c != null && c.getPublicKey() != null; }","tryCatchPattern":"try {\n    val cred = signer.getResolvedSigningCredential(service, adaptor);\n} catch (IllegalArgumentException e) {\n    LOGGER.error(\"Signing credential lacks a public key; check credential type and keystore entry\", e);\n}","preventionTips":["Prefer X509 credential type (private key + certificate) for SAML signing.","Never point signing configuration at secret/symmetric key stores for public-key profiles.","Verify keystore entries contain the certificate chain, not just the private key.","Check getSigningCredentialType on the service matches the actual credential."],"tags":["saml","signing","credentials","public-key","keystore"],"backgroundTag":"invalid-argument-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"}