spring-projects/spring-security · error · Saml2Exception
Saml2Exception wrapping SecurityException while signing quer
Error message
Saml2Exception wrapping SecurityException while signing query string (redirect binding)
What it means
OpenSaml5Template wraps OpenSAML's SecurityException in a Saml2Exception when signing a SAML protocol message's query string for the Redirect binding. SecurityException from XMLSigningUtil.signWithURI means the signing credential could not be used to produce the signature (e.g. the credential's private key is unusable or mismatched with the signing algorithm). This uniform Saml2Exception is Spring Security's translation layer so callers only handle one exception type.
Source
Thrown at saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/web/OpenSaml5Template.java:279
Credential credential = parameters.getSigningCredential();
Assert.notNull(credential, "credential cannot be null when signing a SAML payload");
String algorithmUri = parameters.getSignatureAlgorithm();
Assert.notNull(algorithmUri, "algorithmUri cannot be null when signing a SAML payload");
this.components.put(Saml2ParameterNames.SIG_ALG, algorithmUri);
UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
for (Map.Entry<String, String> component : this.components.entrySet()) {
builder.queryParam(component.getKey(),
UriUtils.encode(component.getValue(), StandardCharsets.ISO_8859_1));
}
String queryString = builder.build(true).toString().substring(1);
try {
byte[] rawSignature = XMLSigningUtil.signWithURI(credential, algorithmUri,
queryString.getBytes(StandardCharsets.UTF_8));
String b64Signature = Saml2Utils.samlEncode(rawSignature);
this.components.put(Saml2ParameterNames.SIGNATURE, b64Signature);
}
catch (SecurityException ex) {
throw new Saml2Exception(ex);
}
return this.components;
}
private SignatureSigningParameters resolveSigningParameters() {
List<Credential> credentials = resolveSigningCredentials();
List<String> digests = Collections.singletonList(SignatureConstants.ALGO_ID_DIGEST_SHA256);
String canonicalization = SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS;
SignatureSigningParametersResolver resolver = new SAMLMetadataSignatureSigningParametersResolver();
BasicSignatureSigningConfiguration signingConfiguration = new BasicSignatureSigningConfiguration();
signingConfiguration.setSigningCredentials(credentials);
signingConfiguration.setSignatureAlgorithms(this.algs);
signingConfiguration.setSignatureReferenceDigestMethods(digests);
signingConfiguration.setSignatureCanonicalizationAlgorithm(canonicalization);
signingConfiguration.setKeyInfoGeneratorManager(buildSignatureKeyInfoGeneratorManager());
CriteriaSet criteria = new CriteriaSet(new SignatureSigningConfigurationCriterion(signingConfiguration));
try {
SignatureSigningParameters parameters = resolver.resolveSingle(criteria);View on GitHub (pinned to 96852e8860)
Solutions
- Verify the signing credential includes a usable RSAPrivateKey/ECPrivateKey matching the certificate
- Ensure the configured signatureAlgorithm URI matches the credential key type
- Check that the keystore/password configuration loads the private key correctly and log credential.getPrivateKey() != null
- Catch Saml2Exception and surface the wrapped SecurityException cause for diagnosis
Example fix
// before .signWith(algorithmRegistry, credentialWithoutPrivateKey) // after .signWith(SignatureAlgorithm.RSA_SHA256, credential) // credential built from keyStore with matching private key
Defensive patterns
Strategy: try-catch
Validate before calling
if (credential.getPrivateKey() == null) throw new IllegalStateException("Signing credential has no private key");
if (!algorithmUri.contains("rsa") && keyIsRsa) throw new IllegalStateException("Algorithm/key mismatch"); Type guard
function hasUsableSigningKey(cred) { return cred != null && cred.getPrivateKey() != null; } Try / catch
try { signed = signingUtils.sign(...); } catch (Saml2Exception e) { log.error("SAML signing failed", e.getCause()); throw new SamlAuthException(e); } Prevention
- Always build signing credentials from a keystore entry containing both certificate and private key
- Match signatureAlgorithm to key type (RSA vs EC)
- Test redirect-binding signing at startup with a smoke test
- Log the wrapped cause, not just Saml2Exception
When it happens
Trigger: Calling OpenSamlSigningUtils/Template.sign() on a query string (redirect binding SignableSAMLObject or query-string path) where resolveSigningParameters produced a credential+algorithm pair that XMLSigningUtil cannot use, e.g. a credential whose private key is not an RSA/EC key compatible with the resolved signature algorithm URI.
Common situations: Registering an X509 certificate without the matching private key or a key in a format the JDK provider cannot load; configuring a signatureAlgorithm that does not match the key type (e.g. SHA256withRSA on an EC key); credentials loaded from a broken/wrong keystore so the private key handle is invalid.
Related errors
- Saml2Exception wrapping exception from signature signing par
- Spring Security does not support OpenSAML {Version.getVersio
- Spring Security does not support OpenSAML {Version.getVersio
- decryption_error
- Saml2Exception wrapping exception while signing XMLObject
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/58846b2110bd1f71.
Report an issue: GitHub.