spring-projects/spring-security · error · Saml2Exception

Saml2Exception wrapping DecryptionException during encrypted

Error message

Saml2Exception wrapping DecryptionException during encrypted NameID decryption

What it means

OpenSaml5Template.decryptAssertion decrypts the assertion's EncryptedID (NameID) via OpenSAML's Decrypter. When OpenSAML throws a DecryptionException, it is wrapped in a Spring Security Saml2Exception and rethrown. This signals that an encrypted NameID in the assertion could not be decrypted with the configured decryption credentials.

Source

Thrown at saml2/saml2-service-provider/src/opensaml5Main/java/org/springframework/security/saml2/provider/service/registration/OpenSaml5Template.java:556

			for (AttributeStatement statement : assertion.getAttributeStatements()) {
				decryptAttributes(statement);
			}
			decryptSubject(assertion.getSubject());
			if (assertion.getConditions() != null) {
				for (Condition c : assertion.getConditions().getConditions()) {
					if (!(c instanceof DelegationRestrictionType delegation)) {
						continue;
					}
					for (Delegate d : delegation.getDelegates()) {
						if (d.getEncryptedID() != null) {
							try {
								NameID decrypted = (NameID) this.decrypter.decrypt(d.getEncryptedID());
								if (decrypted != null) {
									d.setNameID(decrypted);
								}
							}
							catch (DecryptionException ex) {
								throw new Saml2Exception(ex);
							}
						}
					}
				}
			}
		}

		private void decryptAttributes(AttributeStatement statement) {
			Collection<Attribute> decrypteds = new ArrayList<>();
			for (EncryptedAttribute encrypted : statement.getEncryptedAttributes()) {
				try {
					Attribute decrypted = this.decrypter.decrypt(encrypted);
					if (decrypted != null) {
						decrypteds.add(decrypted);
					}
				}
				catch (Exception ex) {
					throw new Saml2Exception(ex);

View on GitHub (pinned to 96852e8860)

Solutions

  1. Verify RelyingPartyRegistration's decryptionX509Credentials contains the private key matching the certificate the IdP encrypted the NameID to
  2. Check the IdP metadata/certificate to confirm which encryption key was used and import it
  3. Test decrypting the encrypted element manually with the private key to isolate key vs. format issues
  4. Confirm JVM JCE unlimited-strength policy / supported algorithms match the IdP's chosen encryption algorithm

Example fix

// before
X509PasswordEncoder enc = X509PasswordEncoder.pkcs12(); // wrong or stale keystore
.registration.signingX509Credentials(c -> c.add(signingCred)) // only signing cred
// after
.registration.decryptionX509Credentials(c -> c.add(
    new X509Certificate(CertificateUtils.decodePem(encCert)),
    keyPair.getPrivate())) // credential matching the IdP's encryption cert
Defensive patterns

Strategy: try-catch

Validate before calling

// before decrypting, check that a decryption credential is registered
if (registration.getDecryptionX509Credentials().isEmpty())
    throw new IllegalStateException("No SAML decryption credentials configured");

Type guard

if (assertion.getEncryptedID() == null) { /* nothing to decrypt */ return; }

Try / catch

try {
    decrypter.decrypt(encryptedId);
} catch (Saml2Exception ex) {
    if (ex.getCause() instanceof DecryptionException de)
        throw new Saml2AuthenticationException("Encrypted NameID decryption failed: " + de.getMessage());
    throw ex;
}

Prevention

When it happens

Trigger: Calling decrypt/decryptAssertion on a Response whose Assertion contains an <saml2:EncryptedID>; the configured RelyingPartyRegistration decryption credential does not match the key the IdP used, the EncryptedData algorithm is unsupported, or the ciphertext is malformed.

Common situations: IdP re-keyed its encryption certificate but the SP still holds the old key; SP registered the signing credential instead of the encryption credential in RelyingPartyRegistration; wrong X509 certificate/key pair loaded from keystore; multi-tenant setups where the wrong registration is matched to the response.

Related errors


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