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

  1. Verify the signing credential includes a usable RSAPrivateKey/ECPrivateKey matching the certificate
  2. Ensure the configured signatureAlgorithm URI matches the credential key type
  3. Check that the keystore/password configuration loads the private key correctly and log credential.getPrivateKey() != null
  4. 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

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


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/58846b2110bd1f71. Report an issue: GitHub.