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
- Verify RelyingPartyRegistration's decryptionX509Credentials contains the private key matching the certificate the IdP encrypted the NameID to
- Check the IdP metadata/certificate to confirm which encryption key was used and import it
- Test decrypting the encrypted element manually with the private key to isolate key vs. format issues
- 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
- Always register decryptionX509Credentials, not just signing credentials
- Keep SP encryption metadata in sync with the IdP after key rotation
- Log DecryptionException causes to distinguish key-mismatch from algorithm issues
- Test SAML responses against both staging and production IdP keys
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
- decryption_error
- Saml2Exception wrapping exception during encrypted attribute
- Saml2Exception wrapping DecryptionException during encrypted
- Saml2Exception wrapping DecryptionException during encrypted
- Saml2Exception wrapping DecryptionException during encrypted
AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10).
Data as JSON: /api/errors/841d3590a29e4b22.
Report an issue: GitHub.